* ntdll.h (struct _SEMAPHORE_BASIC_INFORMATION): Define.

(enum _SEMAPHORE_INFORMATION_CLASS): Define.
	(NtQuerySemaphore): Declare.
	* thread.h (class semaphore): Add member startvalue.
	(semaphore::fixup_before_fork): New inline method.
	(semaphore::_fixup_before_fork): Declare.
	* thread.cc (MTinterface::fixup_before_fork): Additionally call
	semaphore::fixup_before_fork.
	(semaphore::semaphore): Set currentvalue to -1.  Set startvalue to
	incoming initializer value.
	(semaphore::_getvalue): Just query semaphore using NtQuerySemaphore
	rather then using WFSO/Release.
	(semaphore::_post): Drop setting currentvalue.  It's not thread-safe.
	(semaphore::_trywait): Ditto.
	(semaphore::_timedwait): Ditto.
	(semaphore::_wait): Ditto.
	(semaphore::_fixup_before_fork): New method, setting currentvalue from
	actual windows semaphore right before fork.
	(semaphore::_fixup_after_fork): Drop kludge from 2013-07-10.  Drop
	FIXME comment.
This commit is contained in:
Corinna Vinschen 2013-07-23 14:15:20 +00:00
parent 6c1f4d7d64
commit 16efa64721
4 changed files with 74 additions and 27 deletions

View File

@ -1,3 +1,26 @@
2013-07-23 Corinna Vinschen <corinna@vinschen.de>
* ntdll.h (struct _SEMAPHORE_BASIC_INFORMATION): Define.
(enum _SEMAPHORE_INFORMATION_CLASS): Define.
(NtQuerySemaphore): Declare.
* thread.h (class semaphore): Add member startvalue.
(semaphore::fixup_before_fork): New inline method.
(semaphore::_fixup_before_fork): Declare.
* thread.cc (MTinterface::fixup_before_fork): Additionally call
semaphore::fixup_before_fork.
(semaphore::semaphore): Set currentvalue to -1. Set startvalue to
incoming initializer value.
(semaphore::_getvalue): Just query semaphore using NtQuerySemaphore
rather then using WFSO/Release.
(semaphore::_post): Drop setting currentvalue. It's not thread-safe.
(semaphore::_trywait): Ditto.
(semaphore::_timedwait): Ditto.
(semaphore::_wait): Ditto.
(semaphore::_fixup_before_fork): New method, setting currentvalue from
actual windows semaphore right before fork.
(semaphore::_fixup_after_fork): Drop kludge from 2013-07-10. Drop
FIXME comment.
2013-07-23 Corinna Vinschen <corinna@vinschen.de>
* cygtls.cc (well_known_dlls): Add kernelbase.dll.

View File

@ -1102,6 +1102,18 @@ typedef enum _EVENT_INFORMATION_CLASS
EventBasicInformation = 0
} EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS;
/* Checked on 64 bit. */
typedef struct _SEMAPHORE_BASIC_INFORMATION
{
LONG CurrentCount;
LONG MaximumCount;
} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION;
typedef enum _SEMAPHORE_INFORMATION_CLASS
{
SemaphoreBasicInformation = 0
} SEMAPHORE_INFORMATION_CLASS, *PSEMAPHORE_INFORMATION_CLASS;
typedef enum _THREAD_INFORMATION_CLASS
{
ThreadBasicInformation = 0,
@ -1275,6 +1287,8 @@ extern "C"
PVOID, ULONG, PULONG);
NTSTATUS NTAPI NtQueryObject (HANDLE, OBJECT_INFORMATION_CLASS, VOID *,
ULONG, ULONG *);
NTSTATUS NTAPI NtQuerySemaphore (HANDLE, SEMAPHORE_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
NTSTATUS WINAPI NtQuerySystemTime (PLARGE_INTEGER);

View File

@ -316,6 +316,7 @@ void
MTinterface::fixup_before_fork ()
{
pthread_key::fixup_before_fork ();
semaphore::fixup_before_fork ();
}
/* This function is called from a single threaded process */
@ -3376,7 +3377,8 @@ List<semaphore> semaphore::semaphores;
semaphore::semaphore (int pshared, unsigned int value)
: verifyable_object (SEM_MAGIC),
shared (pshared),
currentvalue (value),
currentvalue (-1),
startvalue (value),
fd (-1),
hash (0ULL),
sem (NULL)
@ -3394,7 +3396,8 @@ semaphore::semaphore (unsigned long long shash, LUID sluid, int sfd,
sem_t *ssem, int oflag, mode_t mode, unsigned int value)
: verifyable_object (SEM_MAGIC),
shared (PTHREAD_PROCESS_SHARED),
currentvalue (value), /* Unused for named semaphores. */
currentvalue (-1), /* Unused for named semaphores. */
startvalue (value),
fd (sfd),
hash (shash),
luid (sluid),
@ -3428,29 +3431,21 @@ semaphore::~semaphore ()
void
semaphore::_post ()
{
if (ReleaseSemaphore (win32_obj_id, 1, &currentvalue))
currentvalue++;
LONG dummy;
ReleaseSemaphore (win32_obj_id, 1, &dummy);
}
int
semaphore::_getvalue (int *sval)
{
LONG val;
NTSTATUS status;
SEMAPHORE_BASIC_INFORMATION sbi;
switch (WaitForSingleObject (win32_obj_id, 0))
{
case WAIT_OBJECT_0:
ReleaseSemaphore (win32_obj_id, 1, &val);
*sval = val + 1;
break;
case WAIT_TIMEOUT:
*sval = 0;
break;
default:
set_errno (EAGAIN);
return -1;
}
return 0;
status = NtQuerySemaphore (win32_obj_id, SemaphoreBasicInformation, &sbi,
sizeof sbi, NULL);
if (NT_SUCCESS (status))
return sbi.CurrentCount;
return startvalue;
}
int
@ -3463,7 +3458,6 @@ semaphore::_trywait ()
set_errno (EAGAIN);
return -1;
}
currentvalue--;
return 0;
}
@ -3489,7 +3483,6 @@ semaphore::_timedwait (const struct timespec *abstime)
switch (cygwait (win32_obj_id, &timeout, cw_cancel | cw_cancel_self | cw_sig_eintr))
{
case WAIT_OBJECT_0:
currentvalue--;
break;
case WAIT_SIGNALED:
set_errno (EINTR);
@ -3511,7 +3504,6 @@ semaphore::_wait ()
switch (cygwait (win32_obj_id, cw_infinite, cw_cancel | cw_cancel_self | cw_sig_eintr))
{
case WAIT_OBJECT_0:
currentvalue--;
break;
case WAIT_SIGNALED:
set_errno (EINTR);
@ -3523,19 +3515,31 @@ semaphore::_wait ()
return 0;
}
void
semaphore::_fixup_before_fork ()
{
NTSTATUS status;
SEMAPHORE_BASIC_INFORMATION sbi;
status = NtQuerySemaphore (win32_obj_id, SemaphoreBasicInformation, &sbi,
sizeof sbi, NULL);
if (NT_SUCCESS (status))
currentvalue = sbi.CurrentCount;
else
currentvalue = startvalue;
}
void
semaphore::_fixup_after_fork ()
{
if (shared == PTHREAD_PROCESS_PRIVATE)
{
pthread_printf ("sem %p", this);
if (!currentvalue)
currentvalue = 1;
/* FIXME: duplicate code here and in the constructor. */
win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue,
INT32_MAX, NULL);
INT32_MAX, NULL);
if (!win32_obj_id)
api_fatal ("failed to create new win32 semaphore, currentvalue %ld, %E", currentvalue);
api_fatal ("failed to create new win32 semaphore, "
"currentvalue %ld, %E", currentvalue);
}
}

View File

@ -638,6 +638,7 @@ public:
HANDLE win32_obj_id;
int shared;
LONG currentvalue;
LONG startvalue;
int fd;
unsigned long long hash;
LUID luid;
@ -648,6 +649,10 @@ public:
~semaphore ();
class semaphore * next;
static void fixup_before_fork ()
{
semaphores.for_each (&semaphore::_fixup_before_fork);
}
static void fixup_after_fork ()
{
semaphores.fixup_after_fork ();
@ -666,6 +671,7 @@ private:
int _trywait ();
int _timedwait (const struct timespec *abstime);
void _fixup_before_fork ();
void _fixup_after_fork ();
void _terminate ();