* 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:
@@ -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, ¤tvalue))
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user