+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.
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,
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);
MTinterface::fixup_before_fork ()
{
pthread_key::fixup_before_fork ();
+ semaphore::fixup_before_fork ();
}
/* This function is called from a single threaded process */
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)
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),
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
set_errno (EAGAIN);
return -1;
}
- currentvalue--;
return 0;
}
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);
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);
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);
}
}