OSDN Git Service

* cygwin.sc: New file -- linker script for building cygwin DLL.
authorcgf <cgf>
Fri, 31 Aug 2001 05:06:13 +0000 (05:06 +0000)
committercgf <cgf>
Fri, 31 Aug 2001 05:06:13 +0000 (05:06 +0000)
* Makefile.in: Use linker script to control location of cygheap.
* cygheap.cc (buckets): Make static.
(init_cheap): Remove special iswinnt handling.  Allocate cygheap at a fixed
location.  Display more info when allocation fails.
(cygheap_fixup_in_child): Try harder to move cygheap to correct location.
Display more info when allocation fails.
* fhandler.h (fhandler_socket): Add macros for tracking socket shutdown state.
* net.cc (cygwin_shutdown): Set appropriate shutdown value for future use.
* select.cc (select_stuff::cleanup): New method.
(cygwin_select): Call cleanup explicitly to avoid a race.
(select_stuff:~select_stuff): Call cleanup chain via cleanup method.
(fhandler_socket::select_read): Set *_ready when shutdown has been called on
the socket.
(fhandler_socket::select_write): Ditto.
(fhandler_socket::select_except): Ditto.
* winsup.h: Move NO_COPY to "COMMON" section.
* autoload.cc (wsock_started): Avoid initializing NO_COPY value.
* sigproc.cc: Remove initialization from NO_COPY variables.
(sigproc_init): Initialize sig_loop_wait here, rather than via initialization.
(subproc_init): Initialize proc_loop_wait here, rather than via initialization.

winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/autoload.cc
winsup/cygwin/cygheap.cc
winsup/cygwin/cygwin.sc [new file with mode: 0644]
winsup/cygwin/fhandler.h
winsup/cygwin/net.cc
winsup/cygwin/select.cc
winsup/cygwin/sigproc.cc
winsup/cygwin/winsup.h

index 88bf069..39e4236 100644 (file)
@@ -1,3 +1,34 @@
+Fri Aug 31 00:56:26 2001  Christopher Faylor <cgf@cygnus.com>
+
+       * cygwin.sc: New file -- linker script for building cygwin DLL.
+       * Makefile.in: Use linker script to control location of cygheap.
+       * cygheap.cc (buckets): Make static.
+       (init_cheap): Remove special iswinnt handling.  Allocate cygheap at a
+       fixed location.  Display more info when allocation fails.
+       (cygheap_fixup_in_child): Try harder to move cygheap to correct
+       location.  Display more info when allocation fails.
+       * fhandler.h (fhandler_socket): Add macros for tracking socket shutdown
+       state.
+       * net.cc (cygwin_shutdown): Set appropriate shutdown value for future
+       use.
+       * select.cc (select_stuff::cleanup): New method.
+       (cygwin_select): Call cleanup explicitly to avoid a race.
+       (select_stuff:~select_stuff): Call cleanup chain via cleanup method.
+       (fhandler_socket::select_read): Set *_ready when shutdown has been
+       called on the socket.
+       (fhandler_socket::select_write): Ditto.
+       (fhandler_socket::select_except): Ditto.
+
+       * winsup.h: Move NO_COPY to "COMMON" section.
+       * autoload.cc (wsock_started): Avoid initializing NO_COPY value.
+       * sigproc.cc: Remove initialization from NO_COPY variables.
+       (sigproc_init): Initialize sig_loop_wait here, rather than via
+       initialization.
+       (subproc_init): Initialize proc_loop_wait here, rather than via
+       initialization.
+
+
+
 Thu Aug 30 10:19:00 2001  Christopher Faylor <cgf@cygnus.com>
 
        * select.cc (select_read): Add setting read_ready flag.
index 317616b..5e2a562 100644 (file)
@@ -65,6 +65,7 @@ LD:=@LD@
 DLLTOOL:=@DLLTOOL@
 WINDRES:=@WINDRES@
 AS:=@AS@
+LDSCRIPT=cygwin.sc
 
 #
 # Include common definitions for winsup directory
@@ -194,9 +195,11 @@ new-$(LIB_NAME): $(LIB_NAME)
 
 # Rule to build cygwin.dll
 
-new-$(DLL_NAME): $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp
-       $(CXX) $(CXXFLAGS) -nostdlib -Wl,-shared -o $@ -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o \
-       winver.o $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) -lstdc++ -lgcc -lshell32 -luuid
+new-$(DLL_NAME): $(LDSCRIPT) $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp
+       $(CXX) $(CXXFLAGS) -nostdlib -Wl,-T$(firstword $^) -shared -o $@ \
+       -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o winver.o \
+       $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) \
+       -lstdc++ -lgcc -lshell32 -luuid
 
 dll_ofiles: $(DLL_OFILES)
 
index 1cd0e7e..336c4cb 100644 (file)
@@ -236,7 +236,7 @@ std_dll_init ()
 
 /* Initialization function for winsock stuff. */
 static long long wsock_init () __asm__ ("wsock_init") __attribute__ ((unused, regparm(1)));
-bool NO_COPY wsock_started = 0;
+bool NO_COPY wsock_started;
 static long long
 wsock_init ()
 {
index 39e3082..dc2c72e 100644 (file)
@@ -36,7 +36,7 @@ struct cygheap_entry
   };
 
 #define NBUCKETS 32
-char *buckets[NBUCKETS] = {0};
+static char *buckets[NBUCKETS] = {0};
 
 #define N0 ((_cmalloc_entry *) NULL)
 #define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (int) (N0->data)))
@@ -46,28 +46,21 @@ char *buckets[NBUCKETS] = {0};
 
 extern "C" {
 static void __stdcall _cfree (void *ptr) __attribute__((regparm(1)));
+extern void *_cygheap_start;
 }
 
 inline static void
 init_cheap ()
 {
-  if (!iswinnt)
+  cygheap = (init_cygheap *) VirtualAlloc ((void *) &_cygheap_start, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS);
+  if (!cygheap)
     {
-      cygheap = (init_cygheap *) VirtualAlloc (NULL, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS);
-      if (!cygheap)
-           api_fatal ("Couldn't reserve space for cygwin's heap, %E");
-    }
-  else
-    {
-      HANDLE h;
-      h = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_none, PAGE_READWRITE,
-                            0, CYGHEAPSIZE, NULL);
-      if (!h)
-        api_fatal ("CreateFileMapping failed, %E");
-      cygheap = (init_cygheap *) MapViewOfFile (h, FILE_MAP_WRITE, 0, 0, 0);
-      if (!cygheap)
-        api_fatal ("Couldn't allocate shared memory for cygwin heap, %E");
-      CloseHandle (h);
+      MEMORY_BASIC_INFORMATION m;
+      if (!VirtualQuery ((LPCVOID) &_cygheap_start, &m, sizeof m))
+       system_printf ("couldn't get memory info, %E");
+      small_printf ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
+                   m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
+      api_fatal ("Couldn't reserve space for cygwin's heap, %E");
     }
   cygheap_max = cygheap + 1;
 }
@@ -106,18 +99,30 @@ cygheap_fixup_in_child (child_info *ci, bool execed)
   cygheap_max = ci->cygheap_max;
   void *addr = iswinnt ? cygheap : NULL;
   void *newaddr;
+
   newaddr = MapViewOfFileEx (ci->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, addr);
-  if (!iswinnt || newaddr != addr)
+  if (newaddr != cygheap)
     {
+      if (!newaddr)
+       newaddr = MapViewOfFileEx (ci->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, NULL);
       DWORD n = (DWORD) cygheap_max - (DWORD) cygheap;
       /* Reserve cygwin heap in same spot as parent */
       if (!VirtualAlloc (cygheap, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS))
-           api_fatal ("Couldn't reserve space for cygwin's heap (%p <%p>) in child, %E", cygheap, newaddr);
+      {
+       MEMORY_BASIC_INFORMATION m;
+       memset (&m, 0, sizeof m);
+       if (!VirtualQuery ((LPCVOID) cygheap, &m, sizeof m))
+         system_printf ("couldn't get memory info, %E");
+
+       small_printf ("m.AllocationBase %p, m.BaseAddress %p, m.RegionSize %p, m.State %p\n",
+                     m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
+       api_fatal ("Couldn't reserve space for cygwin's heap (%p <%p>) in child, %E", cygheap, newaddr);
+      }
 
       /* Allocate same amount of memory as parent */
       if (!VirtualAlloc (cygheap, n, MEM_COMMIT, PAGE_READWRITE))
-           api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
-                              cygheap, n);
+       api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
+                  cygheap, n);
       memcpy (cygheap, newaddr, n);
       UnmapViewOfFile (newaddr);
     }
diff --git a/winsup/cygwin/cygwin.sc b/winsup/cygwin/cygwin.sc
new file mode 100644 (file)
index 0000000..42fdffc
--- /dev/null
@@ -0,0 +1,110 @@
+OUTPUT_FORMAT(pei-i386)
+SEARCH_DIR(/cygnus/i686-pc-cygwin/lib/w32api); SEARCH_DIR(/cygnus/i686-pc-cygwin/lib);
+ENTRY(_mainCRTStartup)
+SECTIONS
+{
+  .text  __image_base__ + __section_alignment__  :
+  {
+     *(.init)
+    *(.text)
+    *(SORT(.text$*))
+    *(.glue_7t)
+    *(.glue_7)
+     ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
+                       LONG (-1); *(.ctors); *(.ctor); LONG (0);
+     ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
+                       LONG (-1); *(.dtors); *(.dtor);  LONG (0);
+     *(.fini)
+    /* ??? Why is .gcc_exc here?  */
+     *(.gcc_exc)
+     etext = .;
+    *(.gcc_except_table)
+  }
+  /* The Cygwin32 library uses a section to avoid copying certain data
+     on fork.  This used to be named ".data".  The linker used
+     to include this between __data_start__ and __data_end__, but that
+     breaks building the cygwin32 dll.  Instead, we name the section
+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */
+  .data BLOCK(__section_alignment__) :
+  {
+    __data_start__ = . ;
+    *(.data)
+    *(.data2)
+    *(SORT(.data$*))
+    __data_end__ = . ;
+    *(COMMON)
+  }
+  .rdata BLOCK(__section_alignment__) :
+  {
+    *(.rdata)
+    *(SORT(.rdata$*))
+    *(.eh_frame)
+  }
+  .pdata BLOCK(__section_alignment__) :
+  {
+    *(.pdata)
+  }
+  .bss BLOCK(__section_alignment__) :
+  {
+    __bss_start__ = . ;
+    *(.bss)
+    __bss_end__ = . ;
+  }
+  .edata BLOCK(__section_alignment__) :
+  {
+    *(.edata)
+  }
+  /DISCARD/ :
+  {
+    *(.debug$S)
+    *(.debug$T)
+    *(.debug$F)
+    *(.drectve)
+  }
+  .idata BLOCK(__section_alignment__) :
+  {
+    /* This cannot currently be handled with grouped sections.
+       See pe.em:sort_sections.  */
+    SORT(*)(.idata$2)
+    SORT(*)(.idata$3)
+    /* These zeroes mark the end of the import list.  */
+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
+    SORT(*)(.idata$4)
+    SORT(*)(.idata$5)
+    SORT(*)(.idata$6)
+    SORT(*)(.idata$7)
+  }
+  .CRT BLOCK(__section_alignment__) :
+  {
+    *(SORT(.CRT$*))
+  }
+  .endjunk BLOCK(__section_alignment__) :
+  {
+    /* end is deprecated, don't use it */
+     end = .;
+     _end = .;
+     __end__ = .;
+  }
+  .rsrc BLOCK(__section_alignment__) :
+  {
+    *(.rsrc)
+    *(SORT(.rsrc$*))
+  }
+  .reloc BLOCK(__section_alignment__) :
+  {
+    *(.reloc)
+  }
+  .stab BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    [ .stab ]
+  }
+  .stabstr BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    [ .stabstr ]
+  }
+  .cygheap BLOCK(64 * 1024) :
+  {
+    __cygheap_start = ABSOLUTE(.) ;
+    __system_dlls__ = ABSOLUTE(.) + 4;
+  } 
+}
index dd1df29..6fe6fff 100644 (file)
@@ -70,7 +70,8 @@ enum
   FH_NOEINTR   = 0x01000000,   /* Set if I/O should be uninterruptible. */
   FH_FFIXUP    = 0x02000000,   /* Set if need to fixup after fork. */
   FH_LOCAL     = 0x04000000,   /* File is unix domain socket */
-  FH_FIFO      = 0x08000000,   /* File is FIFO */
+  FH_SHUTRD    = 0x08000000,   /* Socket saw a SHUT_RD */
+  FH_SHUTWR    = 0x10000000,   /* Socket saw a SHUT_WR */
   FH_ISREMOTE  = 0x10000000,   /* File is on a remote drive */
   FH_DCEXEC    = 0x20000000,   /* Don't care if this is executable */
   FH_HASACLS   = 0x40000000,   /* True if fs of file has ACLS */
@@ -157,7 +158,7 @@ enum executable_states
 
 class fhandler_base
 {
-private:
+protected:
   DWORD status;
 public:
   int cb;
@@ -398,6 +399,13 @@ public:
   ~fhandler_socket ();
   int get_socket () { return (int) get_handle(); }
   fhandler_socket * is_socket () { return this; }
+
+  int saw_shutdown_read () const {return FHISSETF (SHUTRD);}
+  int saw_shutdown_write () const {return FHISSETF (SHUTWR);}
+
+  void set_shutdown_read () {FHSETF (SHUTRD);}
+  void set_shutdown_write () {FHSETF (SHUTWR);}
+
   int write (const void *ptr, size_t len);
   int read (void *ptr, size_t len);
   int ioctl (unsigned int cmd, void *);
@@ -1066,6 +1074,7 @@ public:
                     fd_set *exceptfds);
   int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
   int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
+  void cleanup ();
 };
 
 int __stdcall set_console_state_for_spawn ();
index b9faa1b..7077220 100644 (file)
@@ -1349,6 +1349,20 @@ cygwin_shutdown (int fd, int how)
       res = shutdown (sock->get_socket (), how);
       if (res)
        set_winsock_errno ();
+      else
+       switch (how)
+         {
+         case SHUT_RD:
+           sock->set_shutdown_read ();
+           break;
+         case SHUT_WR:
+           sock->set_shutdown_write ();
+           break;
+         case SHUT_RDWR:
+           sock->set_shutdown_read ();
+           sock->set_shutdown_write ();
+           break;
+         }
     }
   syscall_printf ("%d = shutdown (%d, %d)", res, fd, how);
   return res;
index e72e63b..94326dc 100644 (file)
@@ -181,22 +181,34 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
   else if ((timeout = sel.wait (r, w, e, ms) < 0))
     return -1; /* some kind of error */
 
+  sel.cleanup ();
   copyfd_set (readfds, r, maxfds);
   copyfd_set (writefds, w, maxfds);
   copyfd_set (exceptfds, e, maxfds);
   return timeout ? 0 : sel.poll (readfds, writefds, exceptfds);
 }
 
-/* Cleanup */
-select_stuff::~select_stuff ()
+/* Call cleanup functions for all inspected fds.  Gets rid of any
+   executing threads. */
+void
+select_stuff::cleanup ()
 {
   select_record *s = &start;
 
   select_printf ("calling cleanup routines");
   while ((s = s->next))
     if (s->cleanup)
-      s->cleanup (s, this);
+      {
+       s->cleanup (s, this);
+       s->cleanup = NULL;
+      }
+}
 
+/* Destroy all storage associated with select stuff. */
+select_stuff::~select_stuff ()
+{
+  cleanup ();
+  select_record *s = &start;
   select_record *snext = start.next;
 
   select_printf ("deleting select records");
@@ -1375,6 +1387,7 @@ fhandler_socket::select_read (select_record *s)
       s->verify = verify_true;
       s->cleanup = socket_cleanup;
     }
+  s->read_ready = saw_shutdown_read ();
   s->read_selected = TRUE;
   return s;
 }
@@ -1390,6 +1403,7 @@ fhandler_socket::select_write (select_record *s)
       s->verify = verify_true;
       s->cleanup = socket_cleanup;
     }
+  s->write_ready = saw_shutdown_write ();
   s->write_selected = TRUE;
   return s;
 }
@@ -1405,6 +1419,8 @@ fhandler_socket::select_except (select_record *s)
       s->verify = verify_true;
       s->cleanup = socket_cleanup;
     }
+  /* FIXME: Is this right?  Should these be used as criteria for except? */
+  s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
   s->except_selected = TRUE;
   return s;
 }
index 768d6f1..e6071e0 100644 (file)
@@ -74,46 +74,46 @@ HANDLE NO_COPY signal_arrived;              // Event signaled when a signal has
 
 #define Static static NO_COPY
 
-Static DWORD proc_loop_wait = 1000;    // Wait for subprocesses to exit
-Static DWORD sig_loop_wait = INFINITE; // Wait for signals to arrive
+Static DWORD proc_loop_wait;           // Wait for subprocesses to exit
+Static DWORD sig_loop_wait;            // Wait for signals to arrive
 
-Static HANDLE sigcatch_nonmain = NULL; // The semaphore signaled when
+Static HANDLE sigcatch_nonmain;                // The semaphore signaled when
                                        //  signals are available for
                                        //  processing from non-main thread
-Static HANDLE sigcatch_main = NULL;    // Signalled when main thread sends a
+Static HANDLE sigcatch_main;           // Signalled when main thread sends a
                                        //  signal
-Static HANDLE sigcatch_nosync = NULL;  // Signal wait_sig to scan sigtodo
+Static HANDLE sigcatch_nosync;         // Signal wait_sig to scan sigtodo
                                        //  but not to bother with any
                                        //  synchronization
-Static HANDLE sigcomplete_main = NULL; // Event signaled when a signal has
+Static HANDLE sigcomplete_main;                // Event signaled when a signal has
                                        //  finished processing for the main
                                        //  thread
-Static HANDLE sigcomplete_nonmain = NULL;// Semaphore raised for non-main
+Static HANDLE sigcomplete_nonmain;     // Semaphore raised for non-main
                                        //  threads when a signal has finished
                                        //  processing
-Static HANDLE hwait_sig = NULL;                // Handle of wait_sig thread
-Static HANDLE hwait_subproc = NULL;    // Handle of sig_subproc thread
+Static HANDLE hwait_sig;               // Handle of wait_sig thread
+Static HANDLE hwait_subproc;           // Handle of sig_subproc thread
 
-Static HANDLE wait_sig_inited = NULL;  // Control synchronization of
+Static HANDLE wait_sig_inited;         // Control synchronization of
                                        //  message queue startup
 
 /* Used by WaitForMultipleObjects.  These are handles to child processes.
  */
-Static HANDLE events[PSIZE + 1] = {0}; // All my children's handles++
+Static HANDLE events[PSIZE + 1];       // All my children's handles++
 #define hchildren (events + 1)         // Where the children handles begin
 Static pinfo pchildren[PSIZE];         // All my children info
 Static pinfo zombies[16384];           // All my deceased children info
 Static int nchildren = 0;              // Number of active children
 Static int nzombies = 0;               // Number of deceased children
 
-Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
+Static waitq waitq_head;               // Start of queue for wait'ing threads
 Static waitq waitq_main;               // Storage for main thread
 
-muto NO_COPY *sync_proc_subproc = NULL;        // Control access to subproc stuff
+muto NO_COPY *sync_proc_subproc;       // Control access to subproc stuff
 
-DWORD NO_COPY sigtid = 0;              // ID of the signal thread
+DWORD NO_COPY sigtid;                  // ID of the signal thread
 
-int NO_COPY pending_signals = 0;       // TRUE if signals pending
+int NO_COPY pending_signals;           // TRUE if signals pending
 
 /* Functions
  */
@@ -543,6 +543,7 @@ sig_dispatch_pending (int justwake)
 void __stdcall
 sigproc_init ()
 {
+  sig_loop_wait = INFINITE;
   wait_sig_inited = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
   ProtectHandle (wait_sig_inited);
 
@@ -814,6 +815,7 @@ subproc_init (void)
   if (hwait_subproc)
     return;
 
+  proc_loop_wait = 1000;
   /* A "wakeup" handle which can be toggled to make wait_subproc reexamine
    * the hchildren array.
    */
index 1b73a2f..32cecd0 100644 (file)
@@ -24,7 +24,7 @@ details. */
 # define memset __builtin_memset
 #endif
 
-#define NO_COPY __attribute__((section(".data_cygwin_nocopy")))
+#define NO_COPY __attribute__((section("COMMON")))
 
 #ifdef __cplusplus