* cygerrno.h (geterrno_from_nt_status): Declare.
* errno.cc (geterrno_from_nt_status): Define. * flock.cc: Fix copyright dates. * ntdll.h (enum _TIMER_TYPE): Define. (PTIMER_APC_ROUTINE): Define. (NtCancelTimer): Declare. (NtCreateTimer): Declare. (NtSetTimer): Declare. * posix_ipc.cc (ipc_cond_timedwait): Rewrite to make interruptible and restartable. Call pthread_testcancel in case of timeout to enable pthread_cancel on waiting thread. Replace WFMO timeout with waiting for a waitable timer. Explain why. Replace single call to WFMO with two calls, one for the event, one for the mutex. Don't lock mutex in case of error. (ipc_cond_signal): Make void function. (ipc_cond_close): Ditto. (_mq_send): Immediately return -1 in case of error from ipc_cond_timedwait. (_mq_receive): Ditto.
This commit is contained in:
parent
1838d97b0a
commit
86bf572ef0
|
@ -1,3 +1,25 @@
|
|||
2011-04-28 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* cygerrno.h (geterrno_from_nt_status): Declare.
|
||||
* errno.cc (geterrno_from_nt_status): Define.
|
||||
* flock.cc: Fix copyright dates.
|
||||
* ntdll.h (enum _TIMER_TYPE): Define.
|
||||
(PTIMER_APC_ROUTINE): Define.
|
||||
(NtCancelTimer): Declare.
|
||||
(NtCreateTimer): Declare.
|
||||
(NtSetTimer): Declare.
|
||||
* posix_ipc.cc (ipc_cond_timedwait): Rewrite to make interruptible and
|
||||
restartable. Call pthread_testcancel in case of timeout to enable
|
||||
pthread_cancel on waiting thread. Replace WFMO timeout with waiting
|
||||
for a waitable timer. Explain why. Replace single call to WFMO with
|
||||
two calls, one for the event, one for the mutex. Don't lock mutex in
|
||||
case of error.
|
||||
(ipc_cond_signal): Make void function.
|
||||
(ipc_cond_close): Ditto.
|
||||
(_mq_send): Immediately return -1 in case of error from
|
||||
ipc_cond_timedwait.
|
||||
(_mq_receive): Ditto.
|
||||
|
||||
2011-04-28 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* advapi32.cc (GetSecurityDescriptorDacl): Remove.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* cygerrno.h: main Cygwin header file.
|
||||
|
||||
Copyright 2000, 2001, 2002, 2003, 2004, 2010 Red Hat, Inc.
|
||||
Copyright 2000, 2001, 2002, 2003, 2004, 2010, 2011 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
@ -16,6 +16,7 @@ void __stdcall seterrno_from_win_error (const char *file, int line, DWORD code)
|
|||
void __stdcall seterrno_from_nt_status (const char *file, int line, NTSTATUS status) __attribute__ ((regparm(3)));
|
||||
void __stdcall seterrno (const char *, int line) __attribute__ ((regparm(2)));
|
||||
int __stdcall geterrno_from_win_error (DWORD code = GetLastError (), int deferrno = 13 /*EACCESS*/) __attribute__ ((regparm(2)));
|
||||
int __stdcall geterrno_from_nt_status (NTSTATUS status, int deferrno = 13 /*EACCESS*/) __attribute__ ((regparm(2)));
|
||||
|
||||
#define __seterrno() seterrno (__FILE__, __LINE__)
|
||||
#define __seterrno_from_win_error(val) seterrno_from_win_error (__FILE__, __LINE__, val)
|
||||
|
|
|
@ -327,6 +327,12 @@ seterrno_from_win_error (const char *file, int line, DWORD code)
|
|||
errno = _impure_ptr->_errno = geterrno_from_win_error (code, EACCES);
|
||||
}
|
||||
|
||||
int __stdcall
|
||||
geterrno_from_nt_status (NTSTATUS status, int deferrno)
|
||||
{
|
||||
return geterrno_from_win_error (RtlNtStatusToDosError (status));
|
||||
}
|
||||
|
||||
/* seterrno_from_nt_status: Given a NT status code, set errno
|
||||
as appropriate. */
|
||||
void __stdcall
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* flock.cc. NT specific implementation of advisory file locking.
|
||||
|
||||
Copyright 2003, 2008, 2009 Red Hat, Inc.
|
||||
Copyright 2003, 2008, 2009, 2010, 2011 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
|
|
@ -948,6 +948,14 @@ typedef struct _KEY_VALUE_PARTIAL_INFORMATION
|
|||
UCHAR Data[1];
|
||||
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
|
||||
|
||||
typedef enum _TIMER_TYPE
|
||||
{
|
||||
NotificationTimer,
|
||||
SynchronisationTimer
|
||||
} TIMER_TYPE, *PTIMER_TYPE;
|
||||
|
||||
typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG);
|
||||
|
||||
/* Function declarations for ntdll.dll. These don't appear in any
|
||||
standard Win32 header. */
|
||||
|
||||
|
@ -970,6 +978,7 @@ extern "C"
|
|||
ULONG, PTOKEN_PRIVILEGES, PULONG);
|
||||
NTSTATUS NTAPI NtAllocateLocallyUniqueId (PLUID);
|
||||
NTSTATUS NTAPI NtAllocateUuids (PLARGE_INTEGER, PULONG, PULONG, PUCHAR);
|
||||
NTSTATUS NTAPI NtCancelTimer (HANDLE, PBOOLEAN);
|
||||
NTSTATUS NTAPI NtClose (HANDLE);
|
||||
NTSTATUS NTAPI NtCommitTransaction (HANDLE, BOOLEAN);
|
||||
NTSTATUS NTAPI NtCreateDirectoryObject (PHANDLE, ACCESS_MASK,
|
||||
|
@ -990,6 +999,8 @@ extern "C"
|
|||
PLARGE_INTEGER, ULONG, ULONG, HANDLE);
|
||||
NTSTATUS NTAPI NtCreateSemaphore (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
|
||||
LONG, LONG);
|
||||
NTSTATUS NTAPI NtCreateTimer (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
|
||||
TIMER_TYPE);
|
||||
NTSTATUS NTAPI NtCreateToken (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
|
||||
TOKEN_TYPE, PLUID, PLARGE_INTEGER, PTOKEN_USER,
|
||||
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,
|
||||
|
@ -1081,6 +1092,8 @@ extern "C"
|
|||
ULONG);
|
||||
NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION,
|
||||
PSECURITY_DESCRIPTOR);
|
||||
NTSTATUS NTAPI NtSetTimer (HANDLE, PLARGE_INTEGER, PTIMER_APC_ROUTINE, PVOID,
|
||||
BOOLEAN, LONG, PBOOLEAN);
|
||||
NTSTATUS NTAPI NtSetTimerResolution (ULONG, BOOLEAN, PULONG);
|
||||
NTSTATUS NTAPI NtSetValueKey (HANDLE, PUNICODE_STRING, ULONG, ULONG, PVOID,
|
||||
ULONG);
|
||||
|
|
|
@ -174,55 +174,104 @@ ipc_cond_init (HANDLE *pevt, const char *name, char sr)
|
|||
static int
|
||||
ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
|
||||
{
|
||||
struct timeval tv;
|
||||
DWORD timeout;
|
||||
HANDLE h[2] = { mtx, evt };
|
||||
int err;
|
||||
HANDLE w4[3] = { evt, signal_arrived, NULL };
|
||||
DWORD cnt = 2;
|
||||
int ret = 0;
|
||||
|
||||
if (!abstime)
|
||||
timeout = INFINITE;
|
||||
else if (abstime->tv_sec < 0
|
||||
|| abstime->tv_nsec < 0
|
||||
|| abstime->tv_nsec > 999999999)
|
||||
return EINVAL;
|
||||
else
|
||||
if (abstime)
|
||||
{
|
||||
gettimeofday (&tv, NULL);
|
||||
/* Check for immediate timeout. */
|
||||
if (tv.tv_sec > abstime->tv_sec
|
||||
|| (tv.tv_sec == abstime->tv_sec
|
||||
&& tv.tv_usec > abstime->tv_nsec / 1000))
|
||||
return ETIMEDOUT;
|
||||
timeout = (abstime->tv_sec - tv.tv_sec) * 1000;
|
||||
timeout += (abstime->tv_nsec / 1000 - tv.tv_usec) / 1000;
|
||||
if (abstime->tv_sec < 0
|
||||
|| abstime->tv_nsec < 0
|
||||
|| abstime->tv_nsec > 999999999)
|
||||
return EINVAL;
|
||||
|
||||
/* If a timeout is set, we create a waitable timer to wait for.
|
||||
This is the easiest way to handle the absolute timeout value, given
|
||||
that NtSetTimer also takes absolute times and given the double
|
||||
dependency on evt *and* mtx, which requires to call WFMO twice. */
|
||||
NTSTATUS status;
|
||||
LARGE_INTEGER duetime;
|
||||
|
||||
status = NtCreateTimer (&w4[2], TIMER_ALL_ACCESS, NULL,
|
||||
NotificationTimer);
|
||||
if (!NT_SUCCESS (status))
|
||||
return geterrno_from_nt_status (status);
|
||||
timespec_to_filetime (abstime, (FILETIME *) &duetime);
|
||||
status = NtSetTimer (w4[2], &duetime, NULL, NULL, FALSE, 0, NULL);
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
NtClose (w4[2]);
|
||||
return geterrno_from_nt_status (status);
|
||||
}
|
||||
cnt = 3;
|
||||
}
|
||||
ResetEvent (evt);
|
||||
if ((err = ipc_mutex_unlock (mtx)) != 0)
|
||||
return err;
|
||||
switch (WaitForMultipleObjects (2, h, TRUE, timeout))
|
||||
if ((ret = ipc_mutex_unlock (mtx)) != 0)
|
||||
return ret;
|
||||
/* Everything's set up, so now wait for the event to be signalled. */
|
||||
restart1:
|
||||
switch (WaitForMultipleObjects (cnt, w4, FALSE, INFINITE))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_ABANDONED_0:
|
||||
return 0;
|
||||
case WAIT_TIMEOUT:
|
||||
ipc_mutex_lock (mtx);
|
||||
return ETIMEDOUT;
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
if (_my_tls.call_signal_handler ())
|
||||
goto restart1;
|
||||
ret = EINTR;
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
pthread_testcancel ();
|
||||
ret = ETIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
ret = geterrno_from_win_error ();
|
||||
break;
|
||||
}
|
||||
return geterrno_from_win_error ();
|
||||
if (ret == 0)
|
||||
{
|
||||
/* At this point we need to lock the mutex. The wait is practically
|
||||
the same as before, just that we now wait on the mutex instead of the
|
||||
event. */
|
||||
restart2:
|
||||
w4[0] = mtx;
|
||||
switch (WaitForMultipleObjects (cnt, w4, FALSE, INFINITE))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_ABANDONED_0:
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
if (_my_tls.call_signal_handler ())
|
||||
goto restart2;
|
||||
ret = EINTR;
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
pthread_testcancel ();
|
||||
ret = ETIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
ret = geterrno_from_win_error ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (w4[2])
|
||||
{
|
||||
if (ret != ETIMEDOUT)
|
||||
NtCancelTimer (w4[2], NULL);
|
||||
NtClose (w4[2]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline void
|
||||
ipc_cond_signal (HANDLE evt)
|
||||
{
|
||||
return SetEvent (evt) ? 0 : geterrno_from_win_error ();
|
||||
SetEvent (evt);
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline void
|
||||
ipc_cond_close (HANDLE evt)
|
||||
{
|
||||
return CloseHandle (evt) ? 0 : geterrno_from_win_error ();
|
||||
CloseHandle (evt);
|
||||
}
|
||||
|
||||
class ipc_flock
|
||||
|
@ -736,7 +785,7 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
|
|||
if (ret != 0)
|
||||
{
|
||||
set_errno (ret);
|
||||
goto err;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -851,7 +900,7 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
|
|||
if (ret != 0)
|
||||
{
|
||||
set_errno (ret);
|
||||
goto err;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
mqhdr->mqh_nwait--;
|
||||
|
|
Loading…
Reference in New Issue