From c400419414d491bb1e907da89be634c5f4ce3749 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 8 Apr 2005 20:31:43 +0000 Subject: [PATCH] * bsd_mutex.cc (msleep_cnt): Remove. (msleep_max_cnt): Remove. (msleep_arr): Remove. (class msleep_sync_array): New class to encapsulate msleep/wakeup thread synchronization. (msleep_sync): New object pointer. (msleep_init): Initialize new msleep_sync object. (_mutex): Just call msleep_sync->enter() and msleep_sync->leave() for thread synchronization. Improve debug output a bit more. (wakeup): Just call msleep_sync->wakeup(). (wakeup_all): Whitespace fix. --- winsup/cygserver/ChangeLog | 14 +++ winsup/cygserver/bsd_mutex.cc | 194 +++++++++++++++++++++------------- 2 files changed, 137 insertions(+), 71 deletions(-) diff --git a/winsup/cygserver/ChangeLog b/winsup/cygserver/ChangeLog index 06bd7aff6..c832296c4 100644 --- a/winsup/cygserver/ChangeLog +++ b/winsup/cygserver/ChangeLog @@ -1,3 +1,17 @@ +2005-04-08 Corinna Vinschen + + * bsd_mutex.cc (msleep_cnt): Remove. + (msleep_max_cnt): Remove. + (msleep_arr): Remove. + (class msleep_sync_array): New class to encapsulate msleep/wakeup + thread synchronization. + (msleep_sync): New object pointer. + (msleep_init): Initialize new msleep_sync object. + (_mutex): Just call msleep_sync->enter() and msleep_sync->leave() for + thread synchronization. Improve debug output a bit more. + (wakeup): Just call msleep_sync->wakeup(). + (wakeup_all): Whitespace fix. + 2005-04-06 Corinna Vinschen * bsd_helper.cc (ipcexit_hookthread): Fix whitespace and handle leak. diff --git a/winsup/cygserver/bsd_mutex.cc b/winsup/cygserver/bsd_mutex.cc index a470b26d5..bbd7fd280 100644 --- a/winsup/cygserver/bsd_mutex.cc +++ b/winsup/cygserver/bsd_mutex.cc @@ -165,14 +165,117 @@ set_priority (int priority) * flag the mutex is not entered before returning. */ static HANDLE msleep_glob_evt; -CRITICAL_SECTION msleep_cs; -static long msleep_cnt; -static long msleep_max_cnt; -static struct msleep_record { - void *ident; - HANDLE wakeup_evt; - LONG threads; -} *msleep_arr; + +class msleep_sync_array +{ + enum msleep_action { + MSLEEP_ENTER = 0, + MSLEEP_LEAVE, + MSLEEP_WAKEUP + }; + + CRITICAL_SECTION cs; + long cnt; + long max_cnt; + struct msleep_record { + void *ident; + HANDLE wakeup_evt; + LONG threads; + } *a; + + int find_ident (void *ident, msleep_action action) + { + int i; + for (i = 0; i < cnt; ++i) + if (a[i].ident == ident) + return i; + if (i >= max_cnt) + panic ("ident %x not found and run out of slots.", ident); + if (i >= cnt && action == MSLEEP_LEAVE) + panic ("ident %x not found (%d).", ident, action); + return i; + } + + HANDLE first_entry (int i, void *ident) + { + debug ("New ident %x, index %d", ident, i); + a[i].ident = ident; + a[i].wakeup_evt = CreateEvent (NULL, TRUE, FALSE, NULL); + if (!a[i].wakeup_evt) + panic ("CreateEvent failed: %E"); + debug ("i = %d, CreateEvent: %x", i, a[i].wakeup_evt); + a[i].threads = 1; + ++cnt; + return a[i].wakeup_evt; + } + + HANDLE next_entry (int i) + { + if (a[i].ident && WaitForSingleObject (a[i].wakeup_evt, 0) != WAIT_OBJECT_0) + { + ++a[i].threads; + return a[i].wakeup_evt; + } + return NULL; + } + +public: + + msleep_sync_array (int count) : cnt (0), max_cnt (count) + { + InitializeCriticalSection (&cs); + if (!(a = new msleep_record[count])) + panic ("Allocating msleep records failed: %d", errno); + } + + HANDLE enter (void *ident) + { + HANDLE evt = NULL; + while (!evt) + { + EnterCriticalSection (&cs); + int i = find_ident (ident, MSLEEP_ENTER); + if (i >= cnt) + evt = first_entry (i, ident); + else if (!(evt = next_entry (i))) + { + /* wakeup has been called, so sleep to wait until all + formerly waiting threads have left and retry. */ + LeaveCriticalSection (&cs); + Sleep (1L); + } + } + LeaveCriticalSection (&cs); + return evt; + } + + void leave (void *ident) + { + EnterCriticalSection (&cs); + int i = find_ident (ident, MSLEEP_LEAVE); + if (--a[i].threads == 0) + { + debug ("i = %d, CloseEvent: %x", i, a[i].wakeup_evt); + CloseHandle (a[i].wakeup_evt); + a[i].ident = NULL; + --cnt; + if (i < cnt) + a[i] = a[cnt]; + } + LeaveCriticalSection (&cs); + } + + void wakeup (void *ident) + { + EnterCriticalSection (&cs); + int i = find_ident (ident, MSLEEP_WAKEUP); + if (i < cnt && a[i].ident) + SetEvent (a[i].wakeup_evt); + LeaveCriticalSection (&cs); + } +}; + +static msleep_sync_array *msleep_sync; void msleep_init (void) @@ -183,17 +286,14 @@ msleep_init (void) msleep_glob_evt = CreateEvent (NULL, TRUE, FALSE, NULL); if (!msleep_glob_evt) panic ("CreateEvent in msleep_init failed: %E"); - InitializeCriticalSection (&msleep_cs); long msgmni = support_msgqueues ? msginfo.msgmni : 0; long semmni = support_semaphores ? seminfo.semmni : 0; TUNABLE_INT_FETCH ("kern.ipc.msgmni", &msgmni); TUNABLE_INT_FETCH ("kern.ipc.semmni", &semmni); debug ("Try allocating msgmni (%d) + semmni (%d) msleep records", msgmni, semmni); - msleep_max_cnt = msgmni + semmni; - msleep_arr = (struct msleep_record *) calloc (msleep_max_cnt, - sizeof (struct msleep_record)); - if (!msleep_arr) + msleep_sync = new msleep_sync_array (msgmni + semmni); + if (!msleep_sync) panic ("Allocating msleep records in msleep_init failed: %d", errno); } @@ -202,47 +302,15 @@ _msleep (void *ident, struct mtx *mtx, int priority, const char *wmesg, int timo, struct thread *td) { int ret = -1; - int i; - while (1) - { - EnterCriticalSection (&msleep_cs); - for (i = 0; i < msleep_cnt; ++i) - if (msleep_arr[i].ident == ident) - break; - if (!msleep_arr[i].ident) - { - debug ("New ident %x, index %d", ident, i); - if (i >= msleep_max_cnt) - panic ("Too many idents to wait for.\n"); - msleep_arr[i].ident = ident; - msleep_arr[i].wakeup_evt = CreateEvent (NULL, TRUE, FALSE, NULL); - if (!msleep_arr[i].wakeup_evt) - panic ("CreateEvent in msleep (%s) failed: %E", wmesg); - msleep_arr[i].threads = 1; - ++msleep_cnt; - LeaveCriticalSection (&msleep_cs); - break; - } - else if (WaitForSingleObject (msleep_arr[i].wakeup_evt, 0) - != WAIT_OBJECT_0) - { - ++msleep_arr[i].threads; - LeaveCriticalSection (&msleep_cs); - break; - } - /* Otherwise wakeup has been called, so sleep to wait until all - formerly waiting threads have left and retry. */ - LeaveCriticalSection (&msleep_cs); - Sleep (1L); - } + HANDLE evt = msleep_sync->enter (ident); if (mtx) mtx_unlock (mtx); int old_priority = set_priority (priority); HANDLE obj[4] = { - msleep_arr[i].wakeup_evt, + evt, msleep_glob_evt, td->client->handle (), td->client->signal_arrived () @@ -253,22 +321,21 @@ _msleep (void *ident, struct mtx *mtx, int priority, if ((priority & PCATCH) && td->client->signal_arrived () != INVALID_HANDLE_VALUE) obj_cnt = 4; - switch (WaitForMultipleObjects (obj_cnt, obj, FALSE, timo ?: INFINITE)) { case WAIT_OBJECT_0: /* wakeup() has been called. */ ret = 0; - debug ("msleep wakeup called"); + debug ("msleep wakeup called for %d", td->td_proc->winpid); break; case WAIT_OBJECT_0 + 1: /* Shutdown event (triggered by wakeup_all). */ priority |= PDROP; /*FALLTHRU*/ case WAIT_OBJECT_0 + 2: /* The dependent process has exited. */ - debug ("msleep process exit or shutdown"); + debug ("msleep process exit or shutdown for %d", td->td_proc->winpid); ret = EIDRM; break; case WAIT_OBJECT_0 + 3: /* Signal for calling process arrived. */ - debug ("msleep process got signal"); + debug ("msleep process got signal for %d", td->td_proc->winpid); ret = EINTR; break; case WAIT_TIMEOUT: @@ -283,20 +350,13 @@ _msleep (void *ident, struct mtx *mtx, int priority, hope for the best. */ if (GetLastError () != ERROR_INVALID_HANDLE) panic ("wait in msleep (%s) failed, %E", wmesg); + debug ("wait in msleep (%s) failed for %d, %E", wmesg, + td->td_proc->winpid); ret = EIDRM; break; } - EnterCriticalSection (&msleep_cs); - if (--msleep_arr[i].threads == 0) - { - CloseHandle (msleep_arr[i].wakeup_evt); - msleep_arr[i].ident = NULL; - --msleep_cnt; - if (i < msleep_cnt) - msleep_arr[i] = msleep_arr[msleep_cnt]; - } - LeaveCriticalSection (&msleep_cs); + msleep_sync->leave (ident); set_priority (old_priority); @@ -311,15 +371,7 @@ _msleep (void *ident, struct mtx *mtx, int priority, int wakeup (void *ident) { - int i; - - EnterCriticalSection (&msleep_cs); - for (i = 0; i < msleep_cnt; ++i) - if (msleep_arr[i].ident == ident) - break; - if (msleep_arr[i].ident) - SetEvent (msleep_arr[i].wakeup_evt); - LeaveCriticalSection (&msleep_cs); + msleep_sync->wakeup (ident); return 0; } @@ -330,6 +382,6 @@ wakeup (void *ident) void wakeup_all (void) { - SetEvent (msleep_glob_evt); + SetEvent (msleep_glob_evt); } #endif /* __OUTSIDE_CYGWIN__ */