* 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.
This commit is contained in:
parent
f0fdfd3454
commit
dafef5e249
@ -1,3 +1,52 @@
|
|||||||
|
2005-04-06 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* 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 <corinna@vinschen.de>
|
2005-04-01 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* bsd_mutex.cc (_msleep): Whitespace fix.
|
* bsd_mutex.cc (_msleep): Whitespace fix.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* bsd_helper.cc
|
/* bsd_helper.cc
|
||||||
|
|
||||||
Copyright 2003, 2004 Red Hat Inc.
|
Copyright 2003, 2004, 2005 Red Hat Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
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
|
exiting process and shmexit_myhook to keep track of shared
|
||||||
memory. */
|
memory. */
|
||||||
if (Giant.owner == shs->ipcblk.winpid)
|
if (Giant.owner == shs->ipcblk.winpid)
|
||||||
mtx_unlock (&Giant);
|
mtx_unlock (&Giant);
|
||||||
if (support_semaphores == TUN_TRUE)
|
if (support_semaphores == TUN_TRUE)
|
||||||
semexit_myhook (NULL, &shs->ipcblk);
|
semexit_myhook (NULL, &shs->ipcblk);
|
||||||
if (support_sharedmem == TUN_TRUE)
|
if (support_sharedmem == TUN_TRUE)
|
||||||
@ -152,6 +152,7 @@ ipcexit_hookthread (const LPVOID param)
|
|||||||
if (ipcht_entry->winpid == shs->ipcblk.winpid)
|
if (ipcht_entry->winpid == shs->ipcblk.winpid)
|
||||||
{
|
{
|
||||||
SLIST_REMOVE (&ipcht_list, ipcht_entry, ipc_hookthread, sht_next);
|
SLIST_REMOVE (&ipcht_list, ipcht_entry, ipc_hookthread, sht_next);
|
||||||
|
CloseHandle (ipcht_entry->thread);
|
||||||
delete ipcht_entry;
|
delete ipcht_entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,9 @@ details. */
|
|||||||
#define __BSD_VISIBLE 1
|
#define __BSD_VISIBLE 1
|
||||||
#include <sys/smallprint.h>
|
#include <sys/smallprint.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/msg.h>
|
||||||
|
#include <sys/sem.h>
|
||||||
|
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "cygserver_ipc.h"
|
#include "cygserver_ipc.h"
|
||||||
@ -26,6 +29,7 @@ mtx_init (mtx *m, const char *name, const void *, int)
|
|||||||
{
|
{
|
||||||
m->name = name;
|
m->name = name;
|
||||||
m->owner = 0;
|
m->owner = 0;
|
||||||
|
m->cnt = 0;
|
||||||
/* Can't use Windows Mutexes here since Windows Mutexes are only
|
/* Can't use Windows Mutexes here since Windows Mutexes are only
|
||||||
unlockable by the lock owner. */
|
unlockable by the lock owner. */
|
||||||
m->h = CreateSemaphore (NULL, 1, 1, NULL);
|
m->h = CreateSemaphore (NULL, 1, 1, NULL);
|
||||||
@ -36,30 +40,32 @@ mtx_init (mtx *m, const char *name, const void *, int)
|
|||||||
void
|
void
|
||||||
_mtx_lock (mtx *m, DWORD winpid, const char *file, int line)
|
_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)
|
if (WaitForSingleObject (m->h, INFINITE) != WAIT_OBJECT_0)
|
||||||
_panic (file, line, "wait for %s in %d failed, %E", m->name, winpid);
|
_panic (file, line, "wait for %s in %d failed, %E", m->name, winpid);
|
||||||
m->owner = 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
|
int
|
||||||
mtx_owned (mtx *m)
|
mtx_owned (mtx *m, DWORD winpid)
|
||||||
{
|
{
|
||||||
return m->owner > 0;
|
return m->owner == winpid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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)
|
switch (what)
|
||||||
{
|
{
|
||||||
case MA_OWNED:
|
case MA_OWNED:
|
||||||
if (!mtx_owned (m))
|
if (!mtx_owned (m, winpid))
|
||||||
_panic (file, line, "Mutex %s not owned", m->name);
|
_panic (file, line, "Mutex %s not owned", m->name);
|
||||||
break;
|
break;
|
||||||
case MA_NOTOWNED:
|
case MA_NOTOWNED:
|
||||||
if (mtx_owned (m))
|
if (mtx_owned (m, winpid))
|
||||||
_panic (file, line, "Mutex %s is owned", m->name);
|
_panic (file, line, "Mutex %s is owned", m->name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -70,6 +76,8 @@ _mtx_assert (mtx *m, int what, const char *file, int line)
|
|||||||
void
|
void
|
||||||
_mtx_unlock (mtx *m, const char *file, int line)
|
_mtx_unlock (mtx *m, const char *file, int line)
|
||||||
{
|
{
|
||||||
|
DWORD owner = m->owner;
|
||||||
|
unsigned long cnt = m->cnt;
|
||||||
m->owner = 0;
|
m->owner = 0;
|
||||||
/* Cautiously check if mtx_destroy has been called (shutdown).
|
/* Cautiously check if mtx_destroy has been called (shutdown).
|
||||||
In that case, m->h is NULL. */
|
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))
|
|| (wincap.is_winnt () && GetLastError () != ERROR_TOO_MANY_POSTS))
|
||||||
_panic (file, line, "release of mutex %s failed, %E", m->name);
|
_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
|
void
|
||||||
@ -98,22 +107,6 @@ mtx_destroy (mtx *m)
|
|||||||
* Helper functions for msleep/wakeup.
|
* 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
|
static int
|
||||||
win_priority (int priority)
|
win_priority (int priority)
|
||||||
{
|
{
|
||||||
@ -172,13 +165,36 @@ set_priority (int priority)
|
|||||||
* flag the mutex is not entered before returning.
|
* flag the mutex is not entered before returning.
|
||||||
*/
|
*/
|
||||||
static HANDLE msleep_glob_evt;
|
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
|
void
|
||||||
msleep_init (void)
|
msleep_init (void)
|
||||||
{
|
{
|
||||||
|
extern struct msginfo msginfo;
|
||||||
|
extern struct seminfo seminfo;
|
||||||
|
|
||||||
msleep_glob_evt = CreateEvent (NULL, TRUE, FALSE, NULL);
|
msleep_glob_evt = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||||
if (!msleep_glob_evt)
|
if (!msleep_glob_evt)
|
||||||
panic ("CreateEvent in msleep_init failed: %E");
|
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
|
int
|
||||||
@ -186,46 +202,47 @@ _msleep (void *ident, struct mtx *mtx, int priority,
|
|||||||
const char *wmesg, int timo, struct thread *td)
|
const char *wmesg, int timo, struct thread *td)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
char name[64];
|
int i;
|
||||||
|
|
||||||
/* The mutex is used to indicate an ident specific critical section.
|
while (1)
|
||||||
The critical section is needed to synchronize access to the
|
{
|
||||||
semaphore and eventually the event object. The whole idea is
|
EnterCriticalSection (&msleep_cs);
|
||||||
that a wakeup is *guaranteed* to wakeup *all* threads. If that's
|
for (i = 0; i < msleep_cnt; ++i)
|
||||||
not synchronized, sleeping threads could return into the msleep
|
if (msleep_arr[i].ident == ident)
|
||||||
function before all other threads have called CloseHandle(evt).
|
break;
|
||||||
That's bad, since the event still exists and is signalled! */
|
if (!msleep_arr[i].ident)
|
||||||
HANDLE mutex = CreateMutex (NULL, FALSE,
|
{
|
||||||
msleep_event_name (ident, name, MSLEEP_MUTEX));
|
debug ("New ident %x, index %d", ident, i);
|
||||||
if (!mutex)
|
if (i >= msleep_max_cnt)
|
||||||
panic ("CreateMutex in msleep (%s) failed: %E", wmesg);
|
panic ("Too many idents to wait for.\n");
|
||||||
WaitForSingleObject (mutex, INFINITE);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
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)
|
if (mtx)
|
||||||
mtx_unlock (mtx);
|
mtx_unlock (mtx);
|
||||||
int old_priority = set_priority (priority);
|
int old_priority = set_priority (priority);
|
||||||
HANDLE obj[4] =
|
HANDLE obj[4] =
|
||||||
{
|
{
|
||||||
evt,
|
msleep_arr[i].wakeup_evt,
|
||||||
msleep_glob_evt,
|
msleep_glob_evt,
|
||||||
td->client->handle (),
|
td->client->handle (),
|
||||||
td->client->signal_arrived ()
|
td->client->signal_arrived ()
|
||||||
@ -241,37 +258,45 @@ _msleep (void *ident, struct mtx *mtx, int priority,
|
|||||||
{
|
{
|
||||||
case WAIT_OBJECT_0: /* wakeup() has been called. */
|
case WAIT_OBJECT_0: /* wakeup() has been called. */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
debug ("msleep wakeup called");
|
||||||
break;
|
break;
|
||||||
case WAIT_OBJECT_0 + 1: /* Shutdown event (triggered by wakeup_all). */
|
case WAIT_OBJECT_0 + 1: /* Shutdown event (triggered by wakeup_all). */
|
||||||
priority |= PDROP;
|
priority |= PDROP;
|
||||||
/*FALLTHRU*/
|
/*FALLTHRU*/
|
||||||
case WAIT_OBJECT_0 + 2: /* The dependent process has exited. */
|
case WAIT_OBJECT_0 + 2: /* The dependent process has exited. */
|
||||||
|
debug ("msleep process exit or shutdown");
|
||||||
ret = EIDRM;
|
ret = EIDRM;
|
||||||
break;
|
break;
|
||||||
case WAIT_OBJECT_0 + 3: /* Signal for calling process arrived. */
|
case WAIT_OBJECT_0 + 3: /* Signal for calling process arrived. */
|
||||||
|
debug ("msleep process got signal");
|
||||||
ret = EINTR;
|
ret = EINTR;
|
||||||
break;
|
break;
|
||||||
case WAIT_TIMEOUT:
|
case WAIT_TIMEOUT:
|
||||||
ret = EWOULDBLOCK;
|
ret = EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle (evt);
|
EnterCriticalSection (&msleep_cs);
|
||||||
/* wakeup has reset the semaphore to 0. Now indicate that this thread
|
if (--msleep_arr[i].threads == 0)
|
||||||
has called CloseHandle (evt) and enter the critical section. The
|
{
|
||||||
critical section is still hold by wakeup, until all formerly sleeping
|
CloseHandle (msleep_arr[i].wakeup_evt);
|
||||||
threads have indicated that the event has been dismissed. That's
|
msleep_arr[i].ident = NULL;
|
||||||
the signal for wakeup that it's the only thread still holding a
|
--msleep_cnt;
|
||||||
handle to the event object. wakeup will then close the last handle
|
if (i < msleep_cnt)
|
||||||
and leave the critical section. */
|
msleep_arr[i] = msleep_arr[msleep_cnt];
|
||||||
ReleaseSemaphore (sem, 1, NULL);
|
}
|
||||||
WaitForSingleObject (mutex, INFINITE);
|
LeaveCriticalSection (&msleep_cs);
|
||||||
CloseHandle (sem);
|
|
||||||
ReleaseMutex (mutex);
|
|
||||||
CloseHandle (mutex);
|
|
||||||
|
|
||||||
set_priority (old_priority);
|
set_priority (old_priority);
|
||||||
|
|
||||||
@ -286,70 +311,15 @@ _msleep (void *ident, struct mtx *mtx, int priority,
|
|||||||
int
|
int
|
||||||
wakeup (void *ident)
|
wakeup (void *ident)
|
||||||
{
|
{
|
||||||
char name[64];
|
int i;
|
||||||
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);
|
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* bsd_mutex.h: BSD Mutex helper
|
/* bsd_mutex.h: BSD Mutex helper
|
||||||
|
|
||||||
Copyright 2003 Red Hat, Inc.
|
Copyright 2003, 2005 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -25,6 +25,7 @@ struct mtx {
|
|||||||
HANDLE h;
|
HANDLE h;
|
||||||
const char *name;
|
const char *name;
|
||||||
DWORD owner;
|
DWORD owner;
|
||||||
|
unsigned long cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Some BSD kernel global mutex. */
|
/* Some BSD kernel global mutex. */
|
||||||
@ -33,9 +34,9 @@ extern struct mtx Giant;
|
|||||||
void mtx_init (mtx *, const char *, const void *, int);
|
void mtx_init (mtx *, const char *, const void *, int);
|
||||||
void _mtx_lock (mtx *, DWORD winpid, const char *, int);
|
void _mtx_lock (mtx *, DWORD winpid, const char *, int);
|
||||||
#define mtx_lock(m) _mtx_lock((m), (td->ipcblk->winpid), __FILE__, __LINE__)
|
#define mtx_lock(m) _mtx_lock((m), (td->ipcblk->winpid), __FILE__, __LINE__)
|
||||||
int mtx_owned (mtx *);
|
int mtx_owned (mtx *, DWORD);
|
||||||
void _mtx_assert(mtx *, int, const char *, int);
|
void _mtx_assert(mtx *, int, DWORD winpid, const char *, int);
|
||||||
#define mtx_assert(m,w) _mtx_assert((m),(w),__FILE__,__LINE__)
|
#define mtx_assert(m,w,p) _mtx_assert((m),(w),(p),__FILE__,__LINE__)
|
||||||
void _mtx_unlock (mtx *, const char *, int);
|
void _mtx_unlock (mtx *, const char *, int);
|
||||||
#define mtx_unlock(m) _mtx_unlock((m),__FILE__,__LINE__)
|
#define mtx_unlock(m) _mtx_unlock((m),__FILE__,__LINE__)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* cygserver.cc
|
/* cygserver.cc
|
||||||
|
|
||||||
Copyright 2001, 2002, 2003, 2004 Red Hat Inc.
|
Copyright 2001, 2002, 2003, 2004, 2005 Red Hat Inc.
|
||||||
|
|
||||||
Written by Egor Duda <deo@logos-m.ru>
|
Written by Egor Duda <deo@logos-m.ru>
|
||||||
|
|
||||||
@ -37,8 +37,7 @@ details. */
|
|||||||
|
|
||||||
#define DEF_CONFIG_FILE "" SYSCONFDIR "/cygserver.conf"
|
#define DEF_CONFIG_FILE "" SYSCONFDIR "/cygserver.conf"
|
||||||
|
|
||||||
// Version string.
|
#define SERVER_VERSION "1.12"
|
||||||
static const char version[] = "$Revision$";
|
|
||||||
|
|
||||||
GENERIC_MAPPING access_mapping;
|
GENERIC_MAPPING access_mapping;
|
||||||
|
|
||||||
@ -496,24 +495,6 @@ print_usage (const char *const pgm)
|
|||||||
static void
|
static void
|
||||||
print_version ()
|
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];
|
char buf[200];
|
||||||
snprintf (buf, sizeof (buf), "%d.%d.%d(%d.%d/%d/%d)-(%d.%d.%d.%d) %s",
|
snprintf (buf, sizeof (buf), "%d.%d.%d(%d.%d/%d/%d)-(%d.%d.%d.%d) %s",
|
||||||
cygwin_version.dll_major / 1000,
|
cygwin_version.dll_major / 1000,
|
||||||
@ -531,12 +512,10 @@ print_version ()
|
|||||||
|
|
||||||
log (LOG_INFO, "(cygwin) %s\n"
|
log (LOG_INFO, "(cygwin) %s\n"
|
||||||
"API version %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"
|
"Compiled on %s\n"
|
||||||
"Default configuration file is %s",
|
"Default configuration file is %s",
|
||||||
vn, buf, __DATE__, DEF_CONFIG_FILE);
|
SERVER_VERSION, buf, __DATE__, DEF_CONFIG_FILE);
|
||||||
|
|
||||||
free (vn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -68,9 +68,11 @@ process::process (const pid_t cygpid, const DWORD winpid, HANDLE signal_arrived)
|
|||||||
if (!DuplicateHandle (_hProcess, signal_arrived,
|
if (!DuplicateHandle (_hProcess, signal_arrived,
|
||||||
GetCurrentProcess (), &_signal_arrived,
|
GetCurrentProcess (), &_signal_arrived,
|
||||||
0, FALSE, DUPLICATE_SAME_ACCESS))
|
0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
system_printf ("error getting signal_arrived to server (%lu)",
|
{
|
||||||
GetLastError ());
|
system_printf ("error getting signal_arrived to server (%lu)",
|
||||||
_signal_arrived = INVALID_HANDLE_VALUE;
|
GetLastError ());
|
||||||
|
_signal_arrived = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
InitializeCriticalSection (&_access);
|
InitializeCriticalSection (&_access);
|
||||||
debug ("initialized (%lu)", _cygpid);
|
debug ("initialized (%lu)", _cygpid);
|
||||||
@ -80,7 +82,8 @@ process::~process ()
|
|||||||
{
|
{
|
||||||
debug ("deleting (%lu)", _cygpid);
|
debug ("deleting (%lu)", _cygpid);
|
||||||
DeleteCriticalSection (&_access);
|
DeleteCriticalSection (&_access);
|
||||||
CloseHandle (_signal_arrived);
|
if (_signal_arrived && _signal_arrived != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle (_signal_arrived);
|
||||||
CloseHandle (_hProcess);
|
CloseHandle (_hProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 "cygserver.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "cygserver_ipc.h"
|
#include "cygserver_ipc.h"
|
||||||
|
#include <sys/smallprint.h>
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
#define __semctl semctl
|
#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 struct sem_undo *semu_alloc(struct thread *td);
|
||||||
static int semundo_adjust(struct thread *td, struct sem_undo **supptr,
|
static int semundo_adjust(struct thread *td, struct sem_undo **supptr,
|
||||||
int semid, int semnum, int adjval);
|
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_
|
#ifndef _SYS_SYSPROTO_H_
|
||||||
struct __semctl_args;
|
struct __semctl_args;
|
||||||
@ -88,7 +89,7 @@ static eventhandler_tag semexit_tag;
|
|||||||
#define SEMUNDO_LOCK() mtx_lock(&SEMUNDO_MTX);
|
#define SEMUNDO_LOCK() mtx_lock(&SEMUNDO_MTX);
|
||||||
#define SEMUNDO_HOOKLOCK() _mtx_lock(&SEMUNDO_MTX, p->winpid, __FILE__, __LINE__);
|
#define SEMUNDO_HOOKLOCK() _mtx_lock(&SEMUNDO_MTX, p->winpid, __FILE__, __LINE__);
|
||||||
#define SEMUNDO_UNLOCK() mtx_unlock(&SEMUNDO_MTX);
|
#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 {
|
struct sem {
|
||||||
u_short semval; /* semaphore value */
|
u_short semval; /* semaphore value */
|
||||||
@ -108,7 +109,11 @@ struct undo {
|
|||||||
|
|
||||||
struct sem_undo {
|
struct sem_undo {
|
||||||
SLIST_ENTRY(sem_undo) un_next; /* ptr to next active undo structure */
|
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 */
|
struct proc *un_proc; /* owner of this structure */
|
||||||
|
#endif
|
||||||
short un_cnt; /* # of active entries */
|
short un_cnt; /* # of active entries */
|
||||||
struct undo un_ent[1]; /* undo entries */
|
struct undo un_ent[1]; /* undo entries */
|
||||||
};
|
};
|
||||||
@ -240,10 +245,18 @@ seminit(void)
|
|||||||
sema[i].sem_perm.seq = 0;
|
sema[i].sem_perm.seq = 0;
|
||||||
}
|
}
|
||||||
for (i = 0; i < seminfo.semmni; i++)
|
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++) {
|
for (i = 0; i < seminfo.semmnu; i++) {
|
||||||
struct sem_undo *suptr = SEMU(i);
|
struct sem_undo *suptr = SEMU(i);
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
suptr->un_proc = 0;
|
||||||
|
#else
|
||||||
suptr->un_proc = NULL;
|
suptr->un_proc = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
SLIST_INIT(&semu_list);
|
SLIST_INIT(&semu_list);
|
||||||
mtx_init(&sem_mtx, "sem", NULL, MTX_DEF);
|
mtx_init(&sem_mtx, "sem", NULL, MTX_DEF);
|
||||||
@ -351,7 +364,7 @@ semu_alloc(struct thread *td)
|
|||||||
struct sem_undo **supptr;
|
struct sem_undo **supptr;
|
||||||
int attempt;
|
int attempt;
|
||||||
|
|
||||||
SEMUNDO_LOCKASSERT(MA_OWNED);
|
SEMUNDO_LOCKASSERT(MA_OWNED, td->td_proc->winpid);
|
||||||
/*
|
/*
|
||||||
* Try twice to allocate something.
|
* Try twice to allocate something.
|
||||||
* (we'll purge an empty structure after the first pass so
|
* (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++) {
|
for (i = 0; i < seminfo.semmnu; i++) {
|
||||||
suptr = SEMU(i);
|
suptr = SEMU(i);
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
if (suptr->un_proc == 0) {
|
||||||
|
#else
|
||||||
if (suptr->un_proc == NULL) {
|
if (suptr->un_proc == NULL) {
|
||||||
|
#endif
|
||||||
SLIST_INSERT_HEAD(&semu_list, suptr, un_next);
|
SLIST_INSERT_HEAD(&semu_list, suptr, un_next);
|
||||||
suptr->un_cnt = 0;
|
suptr->un_cnt = 0;
|
||||||
suptr->un_proc = td->td_proc;
|
suptr->un_proc = td->td_proc->winpid;
|
||||||
return(suptr);
|
return(suptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,7 +403,11 @@ semu_alloc(struct thread *td)
|
|||||||
SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list,
|
SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list,
|
||||||
un_next) {
|
un_next) {
|
||||||
if (suptr->un_cnt == 0) {
|
if (suptr->un_cnt == 0) {
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
suptr->un_proc = 0;
|
||||||
|
#else
|
||||||
suptr->un_proc = NULL;
|
suptr->un_proc = NULL;
|
||||||
|
#endif
|
||||||
did_something = 1;
|
did_something = 1;
|
||||||
*supptr = SLIST_NEXT(suptr, un_next);
|
*supptr = SLIST_NEXT(suptr, un_next);
|
||||||
break;
|
break;
|
||||||
@ -421,7 +442,7 @@ semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid,
|
|||||||
struct undo *sunptr;
|
struct undo *sunptr;
|
||||||
int i;
|
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
|
/* Look for and remember the sem_undo if the caller doesn't provide
|
||||||
it */
|
it */
|
||||||
|
|
||||||
@ -429,7 +450,7 @@ semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid,
|
|||||||
if (suptr == NULL) {
|
if (suptr == NULL) {
|
||||||
SLIST_FOREACH(suptr, &semu_list, un_next) {
|
SLIST_FOREACH(suptr, &semu_list, un_next) {
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
if (suptr->un_proc->cygpid == p->cygpid) {
|
if (suptr->un_proc == p->winpid) {
|
||||||
#else
|
#else
|
||||||
if (suptr->un_proc == p) {
|
if (suptr->un_proc == p) {
|
||||||
#endif
|
#endif
|
||||||
@ -486,11 +507,11 @@ semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
semundo_clear(int semid, int semnum)
|
semundo_clear(int semid, int semnum, struct thread *td)
|
||||||
{
|
{
|
||||||
struct sem_undo *suptr;
|
struct sem_undo *suptr;
|
||||||
|
|
||||||
SEMUNDO_LOCKASSERT(MA_OWNED);
|
SEMUNDO_LOCKASSERT(MA_OWNED, td->td_proc->winpid);
|
||||||
SLIST_FOREACH(suptr, &semu_list, un_next) {
|
SLIST_FOREACH(suptr, &semu_list, un_next) {
|
||||||
struct undo *sunptr = &suptr->un_ent[0];
|
struct undo *sunptr = &suptr->un_ent[0];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -647,7 +668,7 @@ __semctl(struct thread *td, struct __semctl_args *uap)
|
|||||||
}
|
}
|
||||||
semaptr->sem_perm.mode = 0;
|
semaptr->sem_perm.mode = 0;
|
||||||
SEMUNDO_LOCK();
|
SEMUNDO_LOCK();
|
||||||
semundo_clear(semid, -1);
|
semundo_clear(semid, -1, td);
|
||||||
SEMUNDO_UNLOCK();
|
SEMUNDO_UNLOCK();
|
||||||
wakeup(semaptr);
|
wakeup(semaptr);
|
||||||
break;
|
break;
|
||||||
@ -770,7 +791,7 @@ __semctl(struct thread *td, struct __semctl_args *uap)
|
|||||||
}
|
}
|
||||||
semaptr->sem_base[semnum].semval = real_arg.val;
|
semaptr->sem_base[semnum].semval = real_arg.val;
|
||||||
SEMUNDO_LOCK();
|
SEMUNDO_LOCK();
|
||||||
semundo_clear(semid, semnum);
|
semundo_clear(semid, semnum, td);
|
||||||
SEMUNDO_UNLOCK();
|
SEMUNDO_UNLOCK();
|
||||||
wakeup(semaptr);
|
wakeup(semaptr);
|
||||||
break;
|
break;
|
||||||
@ -808,7 +829,7 @@ raced:
|
|||||||
semaptr->sem_base[i].semval = usval;
|
semaptr->sem_base[i].semval = usval;
|
||||||
}
|
}
|
||||||
SEMUNDO_LOCK();
|
SEMUNDO_LOCK();
|
||||||
semundo_clear(semid, -1);
|
semundo_clear(semid, -1, td);
|
||||||
SEMUNDO_UNLOCK();
|
SEMUNDO_UNLOCK();
|
||||||
wakeup(semaptr);
|
wakeup(semaptr);
|
||||||
break;
|
break;
|
||||||
@ -821,7 +842,7 @@ raced:
|
|||||||
if (error == 0)
|
if (error == 0)
|
||||||
td->td_retval[0] = rval;
|
td->td_retval[0] = rval;
|
||||||
done2:
|
done2:
|
||||||
if (mtx_owned(sema_mtxp))
|
if (mtx_owned(sema_mtxp, td->td_proc->winpid))
|
||||||
mtx_unlock(sema_mtxp);
|
mtx_unlock(sema_mtxp);
|
||||||
if (array != NULL)
|
if (array != NULL)
|
||||||
sys_free(array, M_TEMP);
|
sys_free(array, M_TEMP);
|
||||||
@ -850,7 +871,7 @@ semget(struct thread *td, struct semget_args *uap)
|
|||||||
struct ucred *cred = td->td_ucred;
|
struct ucred *cred = td->td_ucred;
|
||||||
#endif
|
#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))
|
if (!jail_sysvipc_allowed && jailed(td->td_ucred))
|
||||||
return (ENOSYS);
|
return (ENOSYS);
|
||||||
|
|
||||||
@ -1056,7 +1077,7 @@ semop(struct thread *td, struct semop_args *uap)
|
|||||||
semptr = &semaptr->sem_base[sopptr->sem_num];
|
semptr = &semaptr->sem_base[sopptr->sem_num];
|
||||||
|
|
||||||
DPRINTF((
|
DPRINTF((
|
||||||
"semop: semaptr=%x, sem_base=%x, "
|
"semop: semaptr=%x, sem_base=%x, "
|
||||||
"semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
|
"semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
|
||||||
semaptr, semaptr->sem_base, semptr,
|
semaptr, semaptr->sem_base, semptr,
|
||||||
sopptr->sem_num, semptr->semval, sopptr->sem_op,
|
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 *suptr;
|
||||||
struct sem_undo **supptr;
|
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
|
* Go through the chain of undo vectors looking for one
|
||||||
* associated with this process.
|
* associated with this process.
|
||||||
@ -1271,16 +1280,20 @@ semexit_myhook(void *arg, struct proc *p)
|
|||||||
SEMUNDO_HOOKLOCK();
|
SEMUNDO_HOOKLOCK();
|
||||||
SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, un_next) {
|
SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, un_next) {
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
if (suptr->un_proc->cygpid == p->cygpid)
|
if (suptr->un_proc == p->winpid)
|
||||||
#else
|
#else
|
||||||
if (suptr->un_proc == p)
|
if (suptr->un_proc == p)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifndef __CYGWIN__
|
||||||
SEMUNDO_UNLOCK();
|
SEMUNDO_UNLOCK();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (suptr == NULL)
|
if (suptr == NULL) {
|
||||||
|
SEMUNDO_UNLOCK();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
DPRINTF(("proc @%u(%u) has undo structure with %d entries\n",
|
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__);
|
_mtx_lock(sema_mtxp, p->winpid, __FILE__, __LINE__);
|
||||||
#else
|
#else
|
||||||
mtx_lock(sema_mtxp);
|
mtx_lock(sema_mtxp);
|
||||||
#endif
|
|
||||||
SEMUNDO_HOOKLOCK();
|
SEMUNDO_HOOKLOCK();
|
||||||
|
#endif
|
||||||
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0)
|
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0)
|
||||||
panic("semexit - semid not allocated");
|
panic("semexit - semid not allocated");
|
||||||
if (semnum >= semaptr->sem_nsems)
|
if (semnum >= semaptr->sem_nsems)
|
||||||
@ -1318,13 +1331,11 @@ semexit_myhook(void *arg, struct proc *p)
|
|||||||
|
|
||||||
DPRINTF((
|
DPRINTF((
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
"semexit: %u(%u) id=%d num=%d(adj=%d) ; sem=%d\n",
|
"semexit: %u id=%d num=%d(adj=%d) ; sem=%d\n",
|
||||||
suptr->un_proc->cygpid, suptr->un_proc->winpid,
|
|
||||||
suptr->un_ent[ix].un_id,
|
|
||||||
#else
|
#else
|
||||||
"semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n",
|
"semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n",
|
||||||
suptr->un_proc, suptr->un_ent[ix].un_id,
|
|
||||||
#endif
|
#endif
|
||||||
|
suptr->un_proc, suptr->un_ent[ix].un_id,
|
||||||
suptr->un_ent[ix].un_num,
|
suptr->un_ent[ix].un_num,
|
||||||
suptr->un_ent[ix].un_adjval,
|
suptr->un_ent[ix].un_adjval,
|
||||||
semaptr->sem_base[semnum].semval));
|
semaptr->sem_base[semnum].semval));
|
||||||
@ -1340,17 +1351,26 @@ semexit_myhook(void *arg, struct proc *p)
|
|||||||
|
|
||||||
wakeup(semaptr);
|
wakeup(semaptr);
|
||||||
DPRINTF(("semexit: back from wakeup\n"));
|
DPRINTF(("semexit: back from wakeup\n"));
|
||||||
mtx_unlock(sema_mtxp);
|
_mtx_unlock(sema_mtxp, __FILE__, __LINE__);
|
||||||
|
#ifndef __CYGWIN__
|
||||||
SEMUNDO_UNLOCK();
|
SEMUNDO_UNLOCK();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocate the undo vector.
|
* 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;
|
suptr->un_proc = NULL;
|
||||||
|
#endif
|
||||||
*supptr = SLIST_NEXT(suptr, un_next);
|
*supptr = SLIST_NEXT(suptr, un_next);
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
SEMUNDO_UNLOCK();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
|
@ -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 btoc(b) (((b) + PAGE_MASK) / PAGE_SIZE)
|
||||||
#define round_page(p) ((((unsigned long)(p)) + PAGE_MASK) & ~(PAGE_MASK))
|
#define round_page(p) ((((unsigned long)(p)) + PAGE_MASK) & ~(PAGE_MASK))
|
||||||
#define ACCESSPERMS (0777)
|
#define ACCESSPERMS (0777)
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#define GIANT_REQUIRED
|
||||||
|
#else
|
||||||
#define GIANT_REQUIRED mtx_assert(&Giant, MA_OWNED)
|
#define GIANT_REQUIRED mtx_assert(&Giant, MA_OWNED)
|
||||||
|
#endif
|
||||||
#define KERN_SUCCESS 0
|
#define KERN_SUCCESS 0
|
||||||
#define VM_PROT_READ PROT_READ
|
#define VM_PROT_READ PROT_READ
|
||||||
#define VM_PROT_WRITE PROT_WRITE
|
#define VM_PROT_WRITE PROT_WRITE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user