* 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:
Corinna Vinschen 2011-04-28 12:13:41 +00:00
parent 1838d97b0a
commit 86bf572ef0
6 changed files with 127 additions and 36 deletions

View File

@ -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.

View File

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

View File

@ -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

View File

@ -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.

View File

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

View File

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