From 2399967607ad177647986cc02efc3897213836a2 Mon Sep 17 00:00:00 2001 From: cgf Date: Fri, 31 Aug 2001 05:06:13 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 31 +++++++++++++ winsup/cygwin/Makefile.in | 9 ++-- winsup/cygwin/autoload.cc | 2 +- winsup/cygwin/cygheap.cc | 47 +++++++++++--------- winsup/cygwin/cygwin.sc | 110 ++++++++++++++++++++++++++++++++++++++++++++++ winsup/cygwin/fhandler.h | 13 +++++- winsup/cygwin/net.cc | 14 ++++++ winsup/cygwin/select.cc | 22 ++++++++-- winsup/cygwin/sigproc.cc | 32 +++++++------- winsup/cygwin/winsup.h | 2 +- 10 files changed, 236 insertions(+), 46 deletions(-) create mode 100644 winsup/cygwin/cygwin.sc diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 88bf06920a..39e4236190 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,34 @@ +Fri Aug 31 00:56:26 2001 Christopher Faylor + + * 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 * select.cc (select_read): Add setting read_ready flag. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 317616bdc1..5e2a5620ed 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -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) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 1cd0e7e129..336c4cb854 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -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 () { diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 39e308217c..dc2c72ed22 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -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 index 0000000000..42fdffc988 --- /dev/null +++ b/winsup/cygwin/cygwin.sc @@ -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; + } +} diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index dd1df29789..6fe6ffff00 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -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 (); diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index b9faa1bc9c..7077220bc2 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -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; diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index e72e63b688..94326dc41c 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -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; } diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 768d6f1fd8..e6071e05d9 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -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. */ diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 1b73a2f520..32cecd0bfd 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -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 -- 2.11.0