* 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

@@ -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);
}
}