From dafef5e249a5ddd5e9a935b802e5e61e4cc8aaa9 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 6 Apr 2005 11:11:07 +0000 Subject: [PATCH] * bsd_helper.cc (ipcexit_hookthread): Fix whitespace and handle leak. * bsd_mutex.cc: Include stdlib.h, sys/msg.h and sys/sem.h. (mtx_init): Initialize lock counter to 0. (_mtx_lock): Increment and log mutex lock counter. (mtx_owned): Add winpid argument. Return true only if mutex is actually owned by process winpid. (_mtx_assert): Add winpid argument accordingly. (_mtx_unlock): Log owner and lock count. (MSLEEP_MUTEX): Remove. (MSLEEP_SEM): Ditto. (MSLEEP_EVENT): Ditto. (msleep_event_name): Ditto. (msleep_cs): New global critical section. (msleep_cnt): New global variable indicating msleep record usage. (msleep_max_cnt): New global variable indicating msleep record size. (msleep_arr): New global pointer to msleep records. (msleep_init): Initialize msleep_cs. Allocate msleep_arr array. (_msleep): Rewrite using new msleep_cs/msleep_arr based thread synchronization. Don't be shy with debug output. (wakeup): Rewrite using new msleep_cs/msleep_arr based thread synchronization. * bsd_mutex.h (struct mtx): Add lock counter for better debugging. (mtx_owned): Declare with winpid argument. (_mtx_assert): Ditto. (mtx_assert): Define with winpid argument. * cygserver.cc (version): Remove. (SERVER_VERSION): New define, decoupling server version information from source code control system. (print_version): Simplify printing server version. * process.cc (process::process): Fix wrong bracketing (and handle leak). (process::~process): Only try to close _signal_arrived if valid. * sysv_sem.cc: Include sys/smallprint.h. (semundo_clear): Define with additional struct thread pointer argument. Accomodate throughout. (SEMUNDO_LOCKASSERT): Define with winpid argument. Accomodate throughout. (struct sem_undo): Define un_proc as pid_t on Cygwin. Accomodate throughout. (seminit): Improve debugging by adding the semid to the mutex name. (semget): Correctly print key value as 64 bit hex value in debug output. (semexit_myhook): Remove Cygwin specific unlocking of mutexes owned by exiting process. Keep semaphore global lock throughout whole function to avoid races. * sysv_shm.cc (GIANT_REQUIRED): Define empty on Cygwin. We know that Giant is locked. --- winsup/cygserver/ChangeLog | 49 +++++++ winsup/cygserver/bsd_helper.cc | 5 +- winsup/cygserver/bsd_mutex.cc | 240 +++++++++++++++------------------ winsup/cygserver/bsd_mutex.h | 9 +- winsup/cygserver/cygserver.cc | 29 +--- winsup/cygserver/process.cc | 11 +- winsup/cygserver/sysv_sem.cc | 92 ++++++++----- winsup/cygserver/sysv_shm.cc | 4 + 8 files changed, 233 insertions(+), 206 deletions(-) diff --git a/winsup/cygserver/ChangeLog b/winsup/cygserver/ChangeLog index 9bf453ace..06bd7aff6 100644 --- a/winsup/cygserver/ChangeLog +++ b/winsup/cygserver/ChangeLog @@ -1,3 +1,52 @@ +2005-04-06 Corinna Vinschen + + * bsd_helper.cc (ipcexit_hookthread): Fix whitespace and handle leak. + * bsd_mutex.cc: Include stdlib.h, sys/msg.h and sys/sem.h. + (mtx_init): Initialize lock counter to 0. + (_mtx_lock): Increment and log mutex lock counter. + (mtx_owned): Add winpid argument. Return true only if mutex is + actually owned by process winpid. + (_mtx_assert): Add winpid argument accordingly. + (_mtx_unlock): Log owner and lock count. + (MSLEEP_MUTEX): Remove. + (MSLEEP_SEM): Ditto. + (MSLEEP_EVENT): Ditto. + (msleep_event_name): Ditto. + (msleep_cs): New global critical section. + (msleep_cnt): New global variable indicating msleep record usage. + (msleep_max_cnt): New global variable indicating msleep record size. + (msleep_arr): New global pointer to msleep records. + (msleep_init): Initialize msleep_cs. Allocate msleep_arr array. + (_msleep): Rewrite using new msleep_cs/msleep_arr based thread + synchronization. Don't be shy with debug output. + (wakeup): Rewrite using new msleep_cs/msleep_arr based thread + synchronization. + * bsd_mutex.h (struct mtx): Add lock counter for better debugging. + (mtx_owned): Declare with winpid argument. + (_mtx_assert): Ditto. + (mtx_assert): Define with winpid argument. + * cygserver.cc (version): Remove. + (SERVER_VERSION): New define, decoupling server version information + from source code control system. + (print_version): Simplify printing server version. + * process.cc (process::process): Fix wrong bracketing (and handle leak). + (process::~process): Only try to close _signal_arrived if valid. + * sysv_sem.cc: Include sys/smallprint.h. + (semundo_clear): Define with additional struct thread pointer argument. + Accomodate throughout. + (SEMUNDO_LOCKASSERT): Define with winpid argument. Accomodate + throughout. + (struct sem_undo): Define un_proc as pid_t on Cygwin. Accomodate + throughout. + (seminit): Improve debugging by adding the semid to the mutex name. + (semget): Correctly print key value as 64 bit hex value in debug + output. + (semexit_myhook): Remove Cygwin specific unlocking of mutexes owned + by exiting process. Keep semaphore global lock throughout whole + function to avoid races. + * sysv_shm.cc (GIANT_REQUIRED): Define empty on Cygwin. We know that + Giant is locked. + 2005-04-01 Corinna Vinschen * bsd_mutex.cc (_msleep): Whitespace fix. diff --git a/winsup/cygserver/bsd_helper.cc b/winsup/cygserver/bsd_helper.cc index 364dddd7f..9fb3c9bfa 100644 --- a/winsup/cygserver/bsd_helper.cc +++ b/winsup/cygserver/bsd_helper.cc @@ -1,6 +1,6 @@ /* bsd_helper.cc - Copyright 2003, 2004 Red Hat Inc. + Copyright 2003, 2004, 2005 Red Hat Inc. This file is part of Cygwin. @@ -129,7 +129,7 @@ ipcexit_hookthread (const LPVOID param) exiting process and shmexit_myhook to keep track of shared memory. */ if (Giant.owner == shs->ipcblk.winpid) - mtx_unlock (&Giant); + mtx_unlock (&Giant); if (support_semaphores == TUN_TRUE) semexit_myhook (NULL, &shs->ipcblk); if (support_sharedmem == TUN_TRUE) @@ -152,6 +152,7 @@ ipcexit_hookthread (const LPVOID param) if (ipcht_entry->winpid == shs->ipcblk.winpid) { SLIST_REMOVE (&ipcht_list, ipcht_entry, ipc_hookthread, sht_next); + CloseHandle (ipcht_entry->thread); delete ipcht_entry; } } diff --git a/winsup/cygserver/bsd_mutex.cc b/winsup/cygserver/bsd_mutex.cc index 82ce4bf27..a470b26d5 100644 --- a/winsup/cygserver/bsd_mutex.cc +++ b/winsup/cygserver/bsd_mutex.cc @@ -14,6 +14,9 @@ details. */ #define __BSD_VISIBLE 1 #include #include +#include +#include +#include #include "process.h" #include "cygserver_ipc.h" @@ -26,6 +29,7 @@ mtx_init (mtx *m, const char *name, const void *, int) { m->name = name; m->owner = 0; + m->cnt = 0; /* Can't use Windows Mutexes here since Windows Mutexes are only unlockable by the lock owner. */ m->h = CreateSemaphore (NULL, 1, 1, NULL); @@ -36,30 +40,32 @@ mtx_init (mtx *m, const char *name, const void *, int) void _mtx_lock (mtx *m, DWORD winpid, const char *file, int line) { - _log (file, line, LOG_DEBUG, "Try locking mutex %s", m->name); + _log (file, line, LOG_DEBUG, "Try locking mutex %s (%u) (hold: %u)", + m->name, winpid, m->owner); if (WaitForSingleObject (m->h, INFINITE) != WAIT_OBJECT_0) _panic (file, line, "wait for %s in %d failed, %E", m->name, winpid); m->owner = winpid; - _log (file, line, LOG_DEBUG, "Locked mutex %s", m->name); + _log (file, line, LOG_DEBUG, "Locked mutex %s/%u (%u)", + m->name, ++m->cnt, winpid); } int -mtx_owned (mtx *m) +mtx_owned (mtx *m, DWORD winpid) { - return m->owner > 0; + return m->owner == winpid; } void -_mtx_assert (mtx *m, int what, const char *file, int line) +_mtx_assert (mtx *m, int what, DWORD winpid, const char *file, int line) { switch (what) { case MA_OWNED: - if (!mtx_owned (m)) + if (!mtx_owned (m, winpid)) _panic (file, line, "Mutex %s not owned", m->name); break; case MA_NOTOWNED: - if (mtx_owned (m)) + if (mtx_owned (m, winpid)) _panic (file, line, "Mutex %s is owned", m->name); break; default: @@ -70,6 +76,8 @@ _mtx_assert (mtx *m, int what, const char *file, int line) void _mtx_unlock (mtx *m, const char *file, int line) { + DWORD owner = m->owner; + unsigned long cnt = m->cnt; m->owner = 0; /* Cautiously check if mtx_destroy has been called (shutdown). In that case, m->h is NULL. */ @@ -82,7 +90,8 @@ _mtx_unlock (mtx *m, const char *file, int line) || (wincap.is_winnt () && GetLastError () != ERROR_TOO_MANY_POSTS)) _panic (file, line, "release of mutex %s failed, %E", m->name); } - _log (file, line, LOG_DEBUG, "Unlocked mutex %s", m->name); + _log (file, line, LOG_DEBUG, "Unlocked mutex %s/%u (owner: %u)", + m->name, cnt, owner); } void @@ -98,22 +107,6 @@ mtx_destroy (mtx *m) * Helper functions for msleep/wakeup. */ -/* Values for which */ -#define MSLEEP_MUTEX 0 -#define MSLEEP_SEM 1 -#define MSLEEP_EVENT 2 - -static char * -msleep_event_name (void *ident, char *name, int which) -{ - if (wincap.has_terminal_services ()) - __small_sprintf (name, "Global\\cygserver.msleep.evt.%1d.%08x", - which, ident); - else - __small_sprintf (name, "cygserver.msleep.evt.%1d.%08x", which, ident); - return name; -} - static int win_priority (int priority) { @@ -172,13 +165,36 @@ 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; void msleep_init (void) { + extern struct msginfo msginfo; + extern struct seminfo seminfo; + 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) + panic ("Allocating msleep records in msleep_init failed: %d", errno); } int @@ -186,46 +202,47 @@ _msleep (void *ident, struct mtx *mtx, int priority, const char *wmesg, int timo, struct thread *td) { int ret = -1; - char name[64]; - - /* The mutex is used to indicate an ident specific critical section. - The critical section is needed to synchronize access to the - semaphore and eventually the event object. The whole idea is - that a wakeup is *guaranteed* to wakeup *all* threads. If that's - not synchronized, sleeping threads could return into the msleep - function before all other threads have called CloseHandle(evt). - That's bad, since the event still exists and is signalled! */ - HANDLE mutex = CreateMutex (NULL, FALSE, - msleep_event_name (ident, name, MSLEEP_MUTEX)); - if (!mutex) - panic ("CreateMutex in msleep (%s) failed: %E", wmesg); - WaitForSingleObject (mutex, INFINITE); + int i; - /* Ok, we're in the critical section now. We create an ident specific - semaphore, which is used to synchronize the waiting threads. */ - HANDLE sem = CreateSemaphore (NULL, 0, LONG_MAX, - msleep_event_name (ident, name, MSLEEP_SEM)); - if (!sem) - panic ("CreateSemaphore in msleep (%s) failed: %E", wmesg); - - /* This thread is one more thread sleeping. The semaphore value is - so used as a counter of sleeping threads. That info is needed by - the wakeup function. */ - ReleaseSemaphore (sem, 1, NULL); - - /* Leave critical section. */ - ReleaseMutex (mutex); + 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 = CreateEvent (NULL, TRUE, FALSE, - msleep_event_name (ident, name, MSLEEP_EVENT)); - if (!evt) - panic ("CreateEvent in msleep (%s) failed: %E", wmesg); if (mtx) mtx_unlock (mtx); int old_priority = set_priority (priority); HANDLE obj[4] = { - evt, + msleep_arr[i].wakeup_evt, msleep_glob_evt, td->client->handle (), td->client->signal_arrived () @@ -241,37 +258,45 @@ _msleep (void *ident, struct mtx *mtx, int priority, { case WAIT_OBJECT_0: /* wakeup() has been called. */ ret = 0; + debug ("msleep wakeup called"); 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"); ret = EIDRM; break; case WAIT_OBJECT_0 + 3: /* Signal for calling process arrived. */ + debug ("msleep process got signal"); ret = EINTR; break; case WAIT_TIMEOUT: ret = EWOULDBLOCK; break; default: - panic ("wait in msleep (%s) failed, %E", wmesg); + /* There's a chance that a process has been terminated before + WaitForMultipleObjects has been called. In this case the handles + might be invalid. The error code returned is ERROR_INVALID_HANDLE. + Since we can trust the values of these handles otherwise, we + treat an ERROR_INVALID_HANDLE as a normal process termination and + hope for the best. */ + if (GetLastError () != ERROR_INVALID_HANDLE) + panic ("wait in msleep (%s) failed, %E", wmesg); + ret = EIDRM; break; } - CloseHandle (evt); - /* wakeup has reset the semaphore to 0. Now indicate that this thread - has called CloseHandle (evt) and enter the critical section. The - critical section is still hold by wakeup, until all formerly sleeping - threads have indicated that the event has been dismissed. That's - the signal for wakeup that it's the only thread still holding a - handle to the event object. wakeup will then close the last handle - and leave the critical section. */ - ReleaseSemaphore (sem, 1, NULL); - WaitForSingleObject (mutex, INFINITE); - CloseHandle (sem); - ReleaseMutex (mutex); - CloseHandle (mutex); + 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); set_priority (old_priority); @@ -286,70 +311,15 @@ _msleep (void *ident, struct mtx *mtx, int priority, int wakeup (void *ident) { - char name[64]; - LONG threads; - - HANDLE evt = OpenEvent (EVENT_MODIFY_STATE, FALSE, - msleep_event_name (ident, name, MSLEEP_EVENT)); - if (!evt) /* No thread is waiting. */ - { - /* Another round of different error codes returned by 9x and NT - systems. Oh boy... */ - if ( (!wincap.is_winnt () && GetLastError () != ERROR_INVALID_NAME) - || (wincap.is_winnt () && GetLastError () != ERROR_FILE_NOT_FOUND)) - panic ("OpenEvent (%s) in wakeup failed: %E", name); - return 0; - } - - /* The mutex is used to indicate an ident specific critical section. - The critical section is needed to synchronize access to the - semaphore and eventually the event object. The whole idea is - that a wakeup is *guaranteed* to wakeup *all* threads. If that's - not synchronized, sleeping threads could return into the msleep - function before all other threads have called CloseHandle(evt). - That's bad, since the event still exists and is signalled! */ - HANDLE mutex = OpenMutex (MUTEX_ALL_ACCESS, FALSE, - msleep_event_name (ident, name, MSLEEP_MUTEX)); - if (!mutex) - panic ("OpenMutex (%s) in wakeup failed: %E", name); - WaitForSingleObject (mutex, INFINITE); - /* Ok, we're in the critical section now. We create an ident specific - semaphore, which is used to synchronize the waiting threads. */ - HANDLE sem = OpenSemaphore (SEMAPHORE_ALL_ACCESS, FALSE, - msleep_event_name (ident, name, MSLEEP_SEM)); - if (!sem) - panic ("OpenSemaphore (%s) in wakeup failed: %E", name); - ReleaseSemaphore (sem, 1, &threads); - /* `threads' is the number of waiting threads. Now reset the semaphore - to 0 and wait for this number of threads to indicate that they have - called CloseHandle (evt). Then it's save to do the same here in - wakeup, which then means that the event object is destroyed and - can get safely recycled. */ - for (int i = threads + 1; i > 0; --i) - WaitForSingleObject (sem, INFINITE); - - if (!SetEvent (evt)) - panic ("SetEvent (%s) in wakeup failed, %E", name); - - /* Now wait for all threads which were waiting for this wakeup. */ - while (threads-- > 0) - WaitForSingleObject (sem, INFINITE); - - /* Now our handle is the last handle to this event object. */ - CloseHandle (evt); - /* But paranoia rulez, so we check here again. */ - evt = OpenEvent (EVENT_MODIFY_STATE, FALSE, - msleep_event_name (ident, name, MSLEEP_EVENT)); - if (evt) - panic ("Event %s has not been destroyed. Obviously I can't count :-(", - name); - - CloseHandle (sem); - - /* Leave critical section (all of wakeup is critical). */ - ReleaseMutex (mutex); - CloseHandle (mutex); - + 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); return 0; } diff --git a/winsup/cygserver/bsd_mutex.h b/winsup/cygserver/bsd_mutex.h index 3b07bf3c6..c9f501576 100644 --- a/winsup/cygserver/bsd_mutex.h +++ b/winsup/cygserver/bsd_mutex.h @@ -1,6 +1,6 @@ /* bsd_mutex.h: BSD Mutex helper - Copyright 2003 Red Hat, Inc. + Copyright 2003, 2005 Red Hat, Inc. This file is part of Cygwin. @@ -25,6 +25,7 @@ struct mtx { HANDLE h; const char *name; DWORD owner; + unsigned long cnt; }; /* Some BSD kernel global mutex. */ @@ -33,9 +34,9 @@ extern struct mtx Giant; void mtx_init (mtx *, const char *, const void *, int); void _mtx_lock (mtx *, DWORD winpid, const char *, int); #define mtx_lock(m) _mtx_lock((m), (td->ipcblk->winpid), __FILE__, __LINE__) -int mtx_owned (mtx *); -void _mtx_assert(mtx *, int, const char *, int); -#define mtx_assert(m,w) _mtx_assert((m),(w),__FILE__,__LINE__) +int mtx_owned (mtx *, DWORD); +void _mtx_assert(mtx *, int, DWORD winpid, const char *, int); +#define mtx_assert(m,w,p) _mtx_assert((m),(w),(p),__FILE__,__LINE__) void _mtx_unlock (mtx *, const char *, int); #define mtx_unlock(m) _mtx_unlock((m),__FILE__,__LINE__) diff --git a/winsup/cygserver/cygserver.cc b/winsup/cygserver/cygserver.cc index 88f5e67a8..5cf82f38e 100644 --- a/winsup/cygserver/cygserver.cc +++ b/winsup/cygserver/cygserver.cc @@ -1,6 +1,6 @@ /* cygserver.cc - Copyright 2001, 2002, 2003, 2004 Red Hat Inc. + Copyright 2001, 2002, 2003, 2004, 2005 Red Hat Inc. Written by Egor Duda @@ -37,8 +37,7 @@ details. */ #define DEF_CONFIG_FILE "" SYSCONFDIR "/cygserver.conf" -// Version string. -static const char version[] = "$Revision$"; +#define SERVER_VERSION "1.12" GENERIC_MAPPING access_mapping; @@ -496,24 +495,6 @@ print_usage (const char *const pgm) static void print_version () { - char *vn = NULL; - - const char *const colon = strchr (version, ':'); - - if (!colon) - { - vn = strdup ("?"); - } - else - { - vn = strdup (colon + 2); // Skip ": " - - char *const spc = strchr (vn, ' '); - - if (spc) - *spc = '\0'; - } - char buf[200]; snprintf (buf, sizeof (buf), "%d.%d.%d(%d.%d/%d/%d)-(%d.%d.%d.%d) %s", cygwin_version.dll_major / 1000, @@ -531,12 +512,10 @@ print_version () log (LOG_INFO, "(cygwin) %s\n" "API version %s\n" - "Copyright 2001, 2002, 2003 Red Hat, Inc.\n" + "Copyright 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.\n" "Compiled on %s\n" "Default configuration file is %s", - vn, buf, __DATE__, DEF_CONFIG_FILE); - - free (vn); + SERVER_VERSION, buf, __DATE__, DEF_CONFIG_FILE); } /* diff --git a/winsup/cygserver/process.cc b/winsup/cygserver/process.cc index 6f8f40ea5..eb7e0940d 100644 --- a/winsup/cygserver/process.cc +++ b/winsup/cygserver/process.cc @@ -68,9 +68,11 @@ process::process (const pid_t cygpid, const DWORD winpid, HANDLE signal_arrived) if (!DuplicateHandle (_hProcess, signal_arrived, GetCurrentProcess (), &_signal_arrived, 0, FALSE, DUPLICATE_SAME_ACCESS)) - system_printf ("error getting signal_arrived to server (%lu)", - GetLastError ()); - _signal_arrived = INVALID_HANDLE_VALUE; + { + system_printf ("error getting signal_arrived to server (%lu)", + GetLastError ()); + _signal_arrived = INVALID_HANDLE_VALUE; + } } InitializeCriticalSection (&_access); debug ("initialized (%lu)", _cygpid); @@ -80,7 +82,8 @@ process::~process () { debug ("deleting (%lu)", _cygpid); DeleteCriticalSection (&_access); - CloseHandle (_signal_arrived); + if (_signal_arrived && _signal_arrived != INVALID_HANDLE_VALUE) + CloseHandle (_signal_arrived); CloseHandle (_hProcess); } diff --git a/winsup/cygserver/sysv_sem.cc b/winsup/cygserver/sysv_sem.cc index bcd0dc251..477df4a26 100644 --- a/winsup/cygserver/sysv_sem.cc +++ b/winsup/cygserver/sysv_sem.cc @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/kern/sysv_sem.c,v 1.70 2004/05/30 20 #include "cygserver.h" #include "process.h" #include "cygserver_ipc.h" +#include #ifdef __CYGWIN__ #define __semctl semctl @@ -53,7 +54,7 @@ static int semvalid(int semid, struct semid_ds *semaptr); static struct sem_undo *semu_alloc(struct thread *td); static int semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid, int semnum, int adjval); -static void semundo_clear(int semid, int semnum); +static void semundo_clear(int semid, int semnum, struct thread *td); #ifndef _SYS_SYSPROTO_H_ struct __semctl_args; @@ -88,7 +89,7 @@ static eventhandler_tag semexit_tag; #define SEMUNDO_LOCK() mtx_lock(&SEMUNDO_MTX); #define SEMUNDO_HOOKLOCK() _mtx_lock(&SEMUNDO_MTX, p->winpid, __FILE__, __LINE__); #define SEMUNDO_UNLOCK() mtx_unlock(&SEMUNDO_MTX); -#define SEMUNDO_LOCKASSERT(how) mtx_assert(&SEMUNDO_MTX, (how)); +#define SEMUNDO_LOCKASSERT(how,pid) mtx_assert(&SEMUNDO_MTX, (how), (pid)); struct sem { u_short semval; /* semaphore value */ @@ -108,7 +109,11 @@ struct undo { struct sem_undo { SLIST_ENTRY(sem_undo) un_next; /* ptr to next active undo structure */ +#ifdef __CYGWIN__ + DWORD un_proc; /* owner of this structure */ +#else struct proc *un_proc; /* owner of this structure */ +#endif short un_cnt; /* # of active entries */ struct undo un_ent[1]; /* undo entries */ }; @@ -240,10 +245,18 @@ seminit(void) sema[i].sem_perm.seq = 0; } for (i = 0; i < seminfo.semmni; i++) - mtx_init(&sema_mtx[i], "semid", NULL, MTX_DEF); + { + char *buf = (char *)malloc (16); + __small_sprintf (buf, "semid[%d]", i); + mtx_init(&sema_mtx[i], buf, NULL, MTX_DEF); + } for (i = 0; i < seminfo.semmnu; i++) { struct sem_undo *suptr = SEMU(i); +#ifdef __CYGWIN__ + suptr->un_proc = 0; +#else suptr->un_proc = NULL; +#endif } SLIST_INIT(&semu_list); mtx_init(&sem_mtx, "sem", NULL, MTX_DEF); @@ -351,7 +364,7 @@ semu_alloc(struct thread *td) struct sem_undo **supptr; int attempt; - SEMUNDO_LOCKASSERT(MA_OWNED); + SEMUNDO_LOCKASSERT(MA_OWNED, td->td_proc->winpid); /* * Try twice to allocate something. * (we'll purge an empty structure after the first pass so @@ -366,10 +379,14 @@ semu_alloc(struct thread *td) for (i = 0; i < seminfo.semmnu; i++) { suptr = SEMU(i); +#ifdef __CYGWIN__ + if (suptr->un_proc == 0) { +#else if (suptr->un_proc == NULL) { +#endif SLIST_INSERT_HEAD(&semu_list, suptr, un_next); suptr->un_cnt = 0; - suptr->un_proc = td->td_proc; + suptr->un_proc = td->td_proc->winpid; return(suptr); } } @@ -386,7 +403,11 @@ semu_alloc(struct thread *td) SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, un_next) { if (suptr->un_cnt == 0) { +#ifdef __CYGWIN__ + suptr->un_proc = 0; +#else suptr->un_proc = NULL; +#endif did_something = 1; *supptr = SLIST_NEXT(suptr, un_next); break; @@ -421,7 +442,7 @@ semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid, struct undo *sunptr; int i; - SEMUNDO_LOCKASSERT(MA_OWNED); + SEMUNDO_LOCKASSERT(MA_OWNED, td->td_proc->winpid); /* Look for and remember the sem_undo if the caller doesn't provide it */ @@ -429,7 +450,7 @@ semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid, if (suptr == NULL) { SLIST_FOREACH(suptr, &semu_list, un_next) { #ifdef __CYGWIN__ - if (suptr->un_proc->cygpid == p->cygpid) { + if (suptr->un_proc == p->winpid) { #else if (suptr->un_proc == p) { #endif @@ -486,11 +507,11 @@ semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid, } static void -semundo_clear(int semid, int semnum) +semundo_clear(int semid, int semnum, struct thread *td) { struct sem_undo *suptr; - SEMUNDO_LOCKASSERT(MA_OWNED); + SEMUNDO_LOCKASSERT(MA_OWNED, td->td_proc->winpid); SLIST_FOREACH(suptr, &semu_list, un_next) { struct undo *sunptr = &suptr->un_ent[0]; int i = 0; @@ -647,7 +668,7 @@ __semctl(struct thread *td, struct __semctl_args *uap) } semaptr->sem_perm.mode = 0; SEMUNDO_LOCK(); - semundo_clear(semid, -1); + semundo_clear(semid, -1, td); SEMUNDO_UNLOCK(); wakeup(semaptr); break; @@ -770,7 +791,7 @@ __semctl(struct thread *td, struct __semctl_args *uap) } semaptr->sem_base[semnum].semval = real_arg.val; SEMUNDO_LOCK(); - semundo_clear(semid, semnum); + semundo_clear(semid, semnum, td); SEMUNDO_UNLOCK(); wakeup(semaptr); break; @@ -808,7 +829,7 @@ raced: semaptr->sem_base[i].semval = usval; } SEMUNDO_LOCK(); - semundo_clear(semid, -1); + semundo_clear(semid, -1, td); SEMUNDO_UNLOCK(); wakeup(semaptr); break; @@ -821,7 +842,7 @@ raced: if (error == 0) td->td_retval[0] = rval; done2: - if (mtx_owned(sema_mtxp)) + if (mtx_owned(sema_mtxp, td->td_proc->winpid)) mtx_unlock(sema_mtxp); if (array != NULL) sys_free(array, M_TEMP); @@ -850,7 +871,7 @@ semget(struct thread *td, struct semget_args *uap) struct ucred *cred = td->td_ucred; #endif - DPRINTF(("semget(0x%x, %d, 0%o)\n", key, nsems, semflg)); + DPRINTF(("semget(0x%X, %d, 0%o)\n", key, nsems, semflg)); if (!jail_sysvipc_allowed && jailed(td->td_ucred)) return (ENOSYS); @@ -1056,7 +1077,7 @@ semop(struct thread *td, struct semop_args *uap) semptr = &semaptr->sem_base[sopptr->sem_num]; DPRINTF(( - "semop: semaptr=%x, sem_base=%x, " + "semop: semaptr=%x, sem_base=%x, " "semptr=%x, sem[%d]=%d : op=%d, flag=%s\n", semaptr, semaptr->sem_base, semptr, sopptr->sem_num, semptr->semval, sopptr->sem_op, @@ -1252,18 +1273,6 @@ semexit_myhook(void *arg, struct proc *p) struct sem_undo *suptr; struct sem_undo **supptr; -#ifdef __CYGWIN__ - /* - * Search all mutexes, if some of them are still owned by the - * leaving process. If so, unlock them. - */ - if (sem_mtx.owner == p->winpid) - mtx_unlock(&sem_mtx); - for (int i = 0; i < seminfo.semmni; i++) - if (sema_mtx[i].owner == p->winpid) - mtx_unlock(&sema_mtx[i]); -#endif /* __CYGWIN__ */ - /* * Go through the chain of undo vectors looking for one * associated with this process. @@ -1271,16 +1280,20 @@ semexit_myhook(void *arg, struct proc *p) SEMUNDO_HOOKLOCK(); SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, un_next) { #ifdef __CYGWIN__ - if (suptr->un_proc->cygpid == p->cygpid) + if (suptr->un_proc == p->winpid) #else if (suptr->un_proc == p) #endif break; } +#ifndef __CYGWIN__ SEMUNDO_UNLOCK(); +#endif - if (suptr == NULL) + if (suptr == NULL) { + SEMUNDO_UNLOCK(); return; + } #ifdef __CYGWIN__ DPRINTF(("proc @%u(%u) has undo structure with %d entries\n", @@ -1309,8 +1322,8 @@ semexit_myhook(void *arg, struct proc *p) _mtx_lock(sema_mtxp, p->winpid, __FILE__, __LINE__); #else mtx_lock(sema_mtxp); -#endif SEMUNDO_HOOKLOCK(); +#endif if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) panic("semexit - semid not allocated"); if (semnum >= semaptr->sem_nsems) @@ -1318,13 +1331,11 @@ semexit_myhook(void *arg, struct proc *p) DPRINTF(( #ifdef __CYGWIN__ - "semexit: %u(%u) id=%d num=%d(adj=%d) ; sem=%d\n", - suptr->un_proc->cygpid, suptr->un_proc->winpid, - suptr->un_ent[ix].un_id, + "semexit: %u id=%d num=%d(adj=%d) ; sem=%d\n", #else "semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n", - suptr->un_proc, suptr->un_ent[ix].un_id, #endif + suptr->un_proc, suptr->un_ent[ix].un_id, suptr->un_ent[ix].un_num, suptr->un_ent[ix].un_adjval, semaptr->sem_base[semnum].semval)); @@ -1340,17 +1351,26 @@ semexit_myhook(void *arg, struct proc *p) wakeup(semaptr); DPRINTF(("semexit: back from wakeup\n")); - mtx_unlock(sema_mtxp); + _mtx_unlock(sema_mtxp, __FILE__, __LINE__); +#ifndef __CYGWIN__ SEMUNDO_UNLOCK(); +#endif } } /* * Deallocate the undo vector. */ - DPRINTF(("removing vector\n")); + DPRINTF(("removing vector (%u)\n", suptr->un_proc)); +#ifdef __CYGWIN__ + suptr->un_proc = 0; +#else suptr->un_proc = NULL; +#endif *supptr = SLIST_NEXT(suptr, un_next); +#ifdef __CYGWIN__ + SEMUNDO_UNLOCK(); +#endif } #ifndef __CYGWIN__ diff --git a/winsup/cygserver/sysv_shm.cc b/winsup/cygserver/sysv_shm.cc index dc77103f5..2b6758755 100644 --- a/winsup/cygserver/sysv_shm.cc +++ b/winsup/cygserver/sysv_shm.cc @@ -68,7 +68,11 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/kern/sysv_shm.c,v 1.89 2003/11/07 04 #define btoc(b) (((b) + PAGE_MASK) / PAGE_SIZE) #define round_page(p) ((((unsigned long)(p)) + PAGE_MASK) & ~(PAGE_MASK)) #define ACCESSPERMS (0777) +#ifdef __CYGWIN__ +#define GIANT_REQUIRED +#else #define GIANT_REQUIRED mtx_assert(&Giant, MA_OWNED) +#endif #define KERN_SUCCESS 0 #define VM_PROT_READ PROT_READ #define VM_PROT_WRITE PROT_WRITE -- 2.43.5