* cygtls.h (struct _local_storage): Add cw_timer member.
* cygtls.cc (_cygtls::init_thread): Initialize locals.cw_timer. (_cygtls::fixup_after_fork): Ditto. * tlsoffsets.h: Regenerate. * ntdll.h (enum _TIMER_INFORMATION_CLASS): Define. (struct _TIMER_BASIC_INFORMATION): Define. (NtQueryTimer): Declare function. * thread.h (cancelable_wait): Change timeout argument to PLARGE_INTEGER and provide NULL default. (fast_mutex::lock): Adjust accordingly. (pthread_cond::wait): Change timeout argument to PLARGE_INTEGER and default to NULL. * thread.cc (cancelable_wait): Change timeout argument to PLARGE_INTEGER. Initialize _cygtls.locals.cw_timer if needed. Use NT waitable timers for handling timeout. Return remaining time to timeout argument if timeout was relative. (pthread_cond::wait): Change timeout argument to PLARGE_INTEGER. Adjust to change in cancelable_wait. (pthread_mutex::lock): Adjust to change in cancelable_wait. (pthread_spinlock::lock): Ditto. (pthread::join): Ditto. (__pthread_cond_dowait): Change waitlength argument to PLARGE_INTEGER. Adjust to changes in cancelable_wait and pthread_cond::wait. (pthread_cond_timedwait): Adjust to change in __pthread_cond_dowait. (pthread_cond_wait): Ditto. (semaphore::_timedwait): Adjust to change in cancelable_wait. (semaphore::_wait): Ditto. * exceptions.cc (handle_sigsuspend): Ditto. * signal.cc (nanosleep): Ditto. * wait.cc (wait4): Ditto. Fix copyright dates. * times.cc (FACTOR, NSPERSEC): Move from here... * hires.h (FACTOR, NSPERSEC): ...to here.
This commit is contained in:
parent
529aa781b6
commit
f0968c1e7e
|
@ -1,3 +1,38 @@
|
||||||
|
2011-08-03 Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
|
||||||
|
|
||||||
|
* cygtls.h (struct _local_storage): Add cw_timer member.
|
||||||
|
* cygtls.cc (_cygtls::init_thread): Initialize locals.cw_timer.
|
||||||
|
(_cygtls::fixup_after_fork): Ditto.
|
||||||
|
* tlsoffsets.h: Regenerate.
|
||||||
|
* ntdll.h (enum _TIMER_INFORMATION_CLASS): Define.
|
||||||
|
(struct _TIMER_BASIC_INFORMATION): Define.
|
||||||
|
(NtQueryTimer): Declare function.
|
||||||
|
* thread.h (cancelable_wait): Change timeout argument to
|
||||||
|
PLARGE_INTEGER and provide NULL default.
|
||||||
|
(fast_mutex::lock): Adjust accordingly.
|
||||||
|
(pthread_cond::wait): Change timeout argument to PLARGE_INTEGER
|
||||||
|
and default to NULL.
|
||||||
|
* thread.cc (cancelable_wait): Change timeout argument to
|
||||||
|
PLARGE_INTEGER. Initialize _cygtls.locals.cw_timer if needed.
|
||||||
|
Use NT waitable timers for handling timeout. Return remaining time
|
||||||
|
to timeout argument if timeout was relative.
|
||||||
|
(pthread_cond::wait): Change timeout argument to PLARGE_INTEGER.
|
||||||
|
Adjust to change in cancelable_wait.
|
||||||
|
(pthread_mutex::lock): Adjust to change in cancelable_wait.
|
||||||
|
(pthread_spinlock::lock): Ditto.
|
||||||
|
(pthread::join): Ditto.
|
||||||
|
(__pthread_cond_dowait): Change waitlength argument to PLARGE_INTEGER.
|
||||||
|
Adjust to changes in cancelable_wait and pthread_cond::wait.
|
||||||
|
(pthread_cond_timedwait): Adjust to change in __pthread_cond_dowait.
|
||||||
|
(pthread_cond_wait): Ditto.
|
||||||
|
(semaphore::_timedwait): Adjust to change in cancelable_wait.
|
||||||
|
(semaphore::_wait): Ditto.
|
||||||
|
* exceptions.cc (handle_sigsuspend): Ditto.
|
||||||
|
* signal.cc (nanosleep): Ditto.
|
||||||
|
* wait.cc (wait4): Ditto. Fix copyright dates.
|
||||||
|
* times.cc (FACTOR, NSPERSEC): Move from here...
|
||||||
|
* hires.h (FACTOR, NSPERSEC): ...to here.
|
||||||
|
|
||||||
2011-08-01 Corinna Vinschen <corinna@vinschen.de>
|
2011-08-01 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* syscalls.cc (faccessat): Fix parens in flag expression when calling
|
* syscalls.cc (faccessat): Fix parens in flag expression when calling
|
||||||
|
|
|
@ -98,6 +98,7 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
|
||||||
thread_id = GetCurrentThreadId ();
|
thread_id = GetCurrentThreadId ();
|
||||||
initialized = CYGTLS_INITIALIZED;
|
initialized = CYGTLS_INITIALIZED;
|
||||||
errno_addr = &(local_clib._errno);
|
errno_addr = &(local_clib._errno);
|
||||||
|
locals.cw_timer = NULL;
|
||||||
|
|
||||||
if ((void *) func == (void *) cygthread::stub
|
if ((void *) func == (void *) cygthread::stub
|
||||||
|| (void *) func == (void *) cygthread::simplestub)
|
|| (void *) func == (void *) cygthread::simplestub)
|
||||||
|
@ -127,6 +128,7 @@ _cygtls::fixup_after_fork ()
|
||||||
}
|
}
|
||||||
stacklock = spinning = 0;
|
stacklock = spinning = 0;
|
||||||
locals.select.sockevt = NULL;
|
locals.select.sockevt = NULL;
|
||||||
|
locals.cw_timer = NULL;
|
||||||
wq.thread_ev = NULL;
|
wq.thread_ev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,9 @@ struct _local_storage
|
||||||
int setmode_file;
|
int setmode_file;
|
||||||
int setmode_mode;
|
int setmode_mode;
|
||||||
|
|
||||||
|
/* thread.cc */
|
||||||
|
HANDLE cw_timer;
|
||||||
|
|
||||||
/* All functions requiring temporary path buffers. */
|
/* All functions requiring temporary path buffers. */
|
||||||
tls_pathbuf pathbufs;
|
tls_pathbuf pathbufs;
|
||||||
char ttybuf[32];
|
char ttybuf[32];
|
||||||
|
|
|
@ -719,7 +719,7 @@ handle_sigsuspend (sigset_t tempmask)
|
||||||
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
|
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
|
||||||
|
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
cancelable_wait (signal_arrived, INFINITE);
|
cancelable_wait (signal_arrived);
|
||||||
|
|
||||||
set_sig_errno (EINTR); // Per POSIX
|
set_sig_errno (EINTR); // Per POSIX
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,11 @@ details. */
|
||||||
and rounding won't exceed HIRES_DELAY_MAX */
|
and rounding won't exceed HIRES_DELAY_MAX */
|
||||||
#define HIRES_DELAY_MAX ((((UINT_MAX - 10000) / 1000) * 1000) + 10)
|
#define HIRES_DELAY_MAX ((((UINT_MAX - 10000) / 1000) * 1000) + 10)
|
||||||
|
|
||||||
|
/* 100ns difference between Windows and UNIX timebase. */
|
||||||
|
#define FACTOR (0x19db1ded53e8000LL)
|
||||||
|
/* # of 100ns intervals per second. */
|
||||||
|
#define NSPERSEC 10000000LL
|
||||||
|
|
||||||
class hires_base
|
class hires_base
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -986,6 +986,15 @@ typedef struct _THREAD_BASIC_INFORMATION {
|
||||||
KPRIORITY BasePriority;
|
KPRIORITY BasePriority;
|
||||||
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
|
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
typedef enum _TIMER_INFORMATION_CLASS {
|
||||||
|
TimerBasicInformation = 0
|
||||||
|
} TIMER_INFORMATION_CLASS, *PTIMER_INFORMATION_CLASS;
|
||||||
|
|
||||||
|
typedef struct _TIMER_BASIC_INFORMATION {
|
||||||
|
LARGE_INTEGER TimeRemaining;
|
||||||
|
BOOLEAN SignalState;
|
||||||
|
} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION;
|
||||||
|
|
||||||
#define RTL_QUERY_REGISTRY_SUBKEY 0x01
|
#define RTL_QUERY_REGISTRY_SUBKEY 0x01
|
||||||
#define RTL_QUERY_REGISTRY_TOPKEY 0x02
|
#define RTL_QUERY_REGISTRY_TOPKEY 0x02
|
||||||
#define RTL_QUERY_REGISTRY_REQUIRED 0x04
|
#define RTL_QUERY_REGISTRY_REQUIRED 0x04
|
||||||
|
@ -1155,6 +1164,8 @@ extern "C"
|
||||||
NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION,
|
NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION,
|
||||||
PSECURITY_DESCRIPTOR, ULONG, PULONG);
|
PSECURITY_DESCRIPTOR, ULONG, PULONG);
|
||||||
NTSTATUS NTAPI NtQuerySymbolicLinkObject (HANDLE, PUNICODE_STRING, PULONG);
|
NTSTATUS NTAPI NtQuerySymbolicLinkObject (HANDLE, PUNICODE_STRING, PULONG);
|
||||||
|
NTSTATUS NTAPI NtQueryTimer (HANDLE, TIMER_INFORMATION_CLASS, PVOID,
|
||||||
|
ULONG, PULONG);
|
||||||
NTSTATUS NTAPI NtQueryTimerResolution (PULONG, PULONG, PULONG);
|
NTSTATUS NTAPI NtQueryTimerResolution (PULONG, PULONG, PULONG);
|
||||||
NTSTATUS NTAPI NtQueryValueKey (HANDLE, PUNICODE_STRING,
|
NTSTATUS NTAPI NtQueryValueKey (HANDLE, PUNICODE_STRING,
|
||||||
KEY_VALUE_INFORMATION_CLASS, PVOID, ULONG,
|
KEY_VALUE_INFORMATION_CLASS, PVOID, ULONG,
|
||||||
|
|
|
@ -92,61 +92,31 @@ nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
unsigned int sec = rqtp->tv_sec;
|
LARGE_INTEGER timeout;
|
||||||
DWORD resolution = gtod.resolution ();
|
|
||||||
bool done = false;
|
|
||||||
DWORD req;
|
|
||||||
DWORD rem;
|
|
||||||
|
|
||||||
while (!done)
|
timeout.QuadPart = (LONGLONG) rqtp->tv_sec * NSPERSEC
|
||||||
{
|
+ ((LONGLONG) rqtp->tv_nsec + 99LL) / 100LL;
|
||||||
/* Divide user's input into transactions no larger than 49.7
|
timeout.QuadPart *= -1LL;
|
||||||
days at a time. */
|
|
||||||
if (sec > HIRES_DELAY_MAX / 1000)
|
|
||||||
{
|
|
||||||
req = ((HIRES_DELAY_MAX + resolution - 1)
|
|
||||||
/ resolution * resolution);
|
|
||||||
sec -= HIRES_DELAY_MAX / 1000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
req = ((sec * 1000 + (rqtp->tv_nsec + 999999) / 1000000
|
|
||||||
+ resolution - 1) / resolution) * resolution;
|
|
||||||
sec = 0;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD end_time = gtod.dmsecs () + req;
|
syscall_printf ("nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec);
|
||||||
syscall_printf ("nanosleep (%ld)", req);
|
|
||||||
|
|
||||||
int rc = cancelable_wait (signal_arrived, req);
|
int rc = cancelable_wait (signal_arrived, &timeout);
|
||||||
if ((rem = end_time - gtod.dmsecs ()) > HIRES_DELAY_MAX)
|
|
||||||
rem = 0;
|
|
||||||
if (rc == WAIT_OBJECT_0)
|
if (rc == WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
_my_tls.call_signal_handler ();
|
_my_tls.call_signal_handler ();
|
||||||
set_errno (EINTR);
|
set_errno (EINTR);
|
||||||
res = -1;
|
res = -1;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rmtp)
|
if (rmtp)
|
||||||
{
|
{
|
||||||
rmtp->tv_sec = sec + rem / 1000;
|
rmtp->tv_sec = (time_t) (timeout.QuadPart / NSPERSEC);
|
||||||
rmtp->tv_nsec = (rem % 1000) * 1000000;
|
rmtp->tv_nsec = (long) ((timeout.QuadPart % NSPERSEC) * 100LL);
|
||||||
if (sec)
|
|
||||||
{
|
|
||||||
rmtp->tv_nsec += rqtp->tv_nsec;
|
|
||||||
if (rmtp->tv_nsec >= 1000000000)
|
|
||||||
{
|
|
||||||
rmtp->tv_nsec -= 1000000000;
|
|
||||||
rmtp->tv_sec++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
syscall_printf ("%d = nanosleep (%ld, %ld)", res, req, rem);
|
syscall_printf ("%d = nanosleep (%ld.%09ld, %ld.%09.ld)", res, rqtp->tv_sec,
|
||||||
|
rqtp->tv_nsec, rmtp ? rmtp->tv_sec : 0,
|
||||||
|
rmtp ? rmtp->tv_nsec : 0);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -906,13 +906,13 @@ pthread::static_cancel_self ()
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
cancelable_wait (HANDLE object, DWORD timeout,
|
cancelable_wait (HANDLE object, PLARGE_INTEGER timeout,
|
||||||
const cw_cancel_action cancel_action,
|
const cw_cancel_action cancel_action,
|
||||||
const enum cw_sig_wait sig_wait)
|
const enum cw_sig_wait sig_wait)
|
||||||
{
|
{
|
||||||
DWORD res;
|
DWORD res;
|
||||||
DWORD num = 0;
|
DWORD num = 0;
|
||||||
HANDLE wait_objects[3];
|
HANDLE wait_objects[4];
|
||||||
pthread_t thread = pthread::self ();
|
pthread_t thread = pthread::self ();
|
||||||
|
|
||||||
/* Do not change the wait order.
|
/* Do not change the wait order.
|
||||||
|
@ -939,15 +939,30 @@ cancelable_wait (HANDLE object, DWORD timeout,
|
||||||
wait_objects[sig_n] = signal_arrived;
|
wait_objects[sig_n] = signal_arrived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD timeout_n;
|
||||||
|
if (!timeout)
|
||||||
|
timeout_n = WAIT_TIMEOUT + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout_n = WAIT_OBJECT_0 + num++;
|
||||||
|
if (!_my_tls.locals.cw_timer)
|
||||||
|
NtCreateTimer (&_my_tls.locals.cw_timer, TIMER_ALL_ACCESS, NULL,
|
||||||
|
NotificationTimer);
|
||||||
|
NtSetTimer (_my_tls.locals.cw_timer, timeout, NULL, NULL, FALSE, 0, NULL);
|
||||||
|
wait_objects[timeout_n] = _my_tls.locals.cw_timer;
|
||||||
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
res = WaitForMultipleObjects (num, wait_objects, FALSE, timeout);
|
res = WaitForMultipleObjects (num, wait_objects, FALSE, INFINITE);
|
||||||
if (res == cancel_n)
|
if (res == cancel_n)
|
||||||
{
|
{
|
||||||
if (cancel_action == cw_cancel_self)
|
if (cancel_action == cw_cancel_self)
|
||||||
pthread::static_cancel_self ();
|
pthread::static_cancel_self ();
|
||||||
res = WAIT_CANCELED;
|
res = WAIT_CANCELED;
|
||||||
}
|
}
|
||||||
|
else if (res == timeout_n)
|
||||||
|
res = WAIT_TIMEOUT;
|
||||||
else if (res != sig_n)
|
else if (res != sig_n)
|
||||||
/* all set */;
|
/* all set */;
|
||||||
else if (sig_wait == cw_sig_eintr)
|
else if (sig_wait == cw_sig_eintr)
|
||||||
|
@ -959,6 +974,21 @@ cancelable_wait (HANDLE object, DWORD timeout,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
const size_t sizeof_tbi = sizeof (TIMER_BASIC_INFORMATION);
|
||||||
|
PTIMER_BASIC_INFORMATION tbi = (PTIMER_BASIC_INFORMATION) malloc (sizeof_tbi);
|
||||||
|
|
||||||
|
NtQueryTimer (_my_tls.locals.cw_timer, TimerBasicInformation, tbi,
|
||||||
|
sizeof_tbi, NULL);
|
||||||
|
/* if timer expired, TimeRemaining is negative and represents the
|
||||||
|
system uptime when signalled */
|
||||||
|
if (timeout->QuadPart < 0LL)
|
||||||
|
timeout->QuadPart = tbi->SignalState ? 0LL : tbi->TimeRemaining.QuadPart;
|
||||||
|
NtCancelTimer (_my_tls.locals.cw_timer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1228,7 +1258,7 @@ pthread_cond::unblock (const bool all)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pthread_cond::wait (pthread_mutex_t mutex, DWORD dwMilliseconds)
|
pthread_cond::wait (pthread_mutex_t mutex, PLARGE_INTEGER timeout)
|
||||||
{
|
{
|
||||||
DWORD rv;
|
DWORD rv;
|
||||||
|
|
||||||
|
@ -1249,7 +1279,7 @@ pthread_cond::wait (pthread_mutex_t mutex, DWORD dwMilliseconds)
|
||||||
++mutex->condwaits;
|
++mutex->condwaits;
|
||||||
mutex->unlock ();
|
mutex->unlock ();
|
||||||
|
|
||||||
rv = cancelable_wait (sem_wait, dwMilliseconds, cw_no_cancel_self, cw_sig_eintr);
|
rv = cancelable_wait (sem_wait, timeout, cw_no_cancel_self, cw_sig_eintr);
|
||||||
|
|
||||||
mtx_out.lock ();
|
mtx_out.lock ();
|
||||||
|
|
||||||
|
@ -1764,7 +1794,7 @@ pthread_mutex::lock ()
|
||||||
else if (type == PTHREAD_MUTEX_NORMAL /* potentially causes deadlock */
|
else if (type == PTHREAD_MUTEX_NORMAL /* potentially causes deadlock */
|
||||||
|| !pthread::equal (owner, self))
|
|| !pthread::equal (owner, self))
|
||||||
{
|
{
|
||||||
cancelable_wait (win32_obj_id, INFINITE, cw_no_cancel, cw_sig_resume);
|
cancelable_wait (win32_obj_id, NULL, cw_no_cancel, cw_sig_resume);
|
||||||
set_owner (self);
|
set_owner (self);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1899,8 +1929,13 @@ pthread_spinlock::lock ()
|
||||||
}
|
}
|
||||||
else if (pthread::equal (owner, self))
|
else if (pthread::equal (owner, self))
|
||||||
result = EDEADLK;
|
result = EDEADLK;
|
||||||
else /* Minimal timeout to minimize CPU usage while still spinning. */
|
else
|
||||||
cancelable_wait (win32_obj_id, 1L, cw_no_cancel, cw_sig_resume);
|
{
|
||||||
|
/* Minimal timeout to minimize CPU usage while still spinning. */
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
|
timeout.QuadPart = -10000LL;
|
||||||
|
cancelable_wait (win32_obj_id, &timeout, cw_no_cancel, cw_sig_resume);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (result == -1);
|
while (result == -1);
|
||||||
pthread_printf ("spinlock %p, self %p, owner %p", this, self, owner);
|
pthread_printf ("spinlock %p, self %p, owner %p", this, self, owner);
|
||||||
|
@ -2377,7 +2412,7 @@ pthread::join (pthread_t *thread, void **return_val)
|
||||||
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
|
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
|
||||||
(*thread)->mutex.unlock ();
|
(*thread)->mutex.unlock ();
|
||||||
|
|
||||||
switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, cw_no_cancel_self, cw_sig_resume))
|
switch (cancelable_wait ((*thread)->win32_obj_id, NULL, cw_no_cancel_self, cw_sig_resume))
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
if (return_val)
|
if (return_val)
|
||||||
|
@ -2702,7 +2737,7 @@ pthread_cond_signal (pthread_cond_t *cond)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
__pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||||
DWORD waitlength)
|
PLARGE_INTEGER waitlength)
|
||||||
{
|
{
|
||||||
if (!pthread_mutex::is_good_object (mutex))
|
if (!pthread_mutex::is_good_object (mutex))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -2722,7 +2757,7 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||||
const struct timespec *abstime)
|
const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
DWORD waitlength;
|
LARGE_INTEGER timeout;
|
||||||
|
|
||||||
myfault efault;
|
myfault efault;
|
||||||
if (efault.faulted ())
|
if (efault.faulted ())
|
||||||
|
@ -2738,17 +2773,27 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||||
|
|
||||||
clock_gettime ((*cond)->clock_id, &tp);
|
clock_gettime ((*cond)->clock_id, &tp);
|
||||||
|
|
||||||
/* Check for immediate timeout before converting to microseconds, since
|
/* Check for immediate timeout before converting */
|
||||||
the resulting value can easily overflow long. This also allows to
|
|
||||||
evaluate microseconds directly in DWORD. */
|
|
||||||
if (tp.tv_sec > abstime->tv_sec
|
if (tp.tv_sec > abstime->tv_sec
|
||||||
|| (tp.tv_sec == abstime->tv_sec
|
|| (tp.tv_sec == abstime->tv_sec
|
||||||
&& tp.tv_nsec > abstime->tv_nsec))
|
&& tp.tv_nsec > abstime->tv_nsec))
|
||||||
return ETIMEDOUT;
|
return ETIMEDOUT;
|
||||||
|
|
||||||
waitlength = (abstime->tv_sec - tp.tv_sec) * 1000;
|
timeout.QuadPart = abstime->tv_sec * NSPERSEC
|
||||||
waitlength += (abstime->tv_nsec - tp.tv_nsec) / 1000000;
|
+ (abstime->tv_nsec + 99LL) / 100LL;
|
||||||
return __pthread_cond_dowait (cond, mutex, waitlength);
|
|
||||||
|
switch ((*cond)->clock_id)
|
||||||
|
{
|
||||||
|
case CLOCK_REALTIME:
|
||||||
|
timeout.QuadPart += FACTOR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* other clocks must be handled as relative timeout */
|
||||||
|
timeout.QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL;
|
||||||
|
timeout.QuadPart *= -1LL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return __pthread_cond_dowait (cond, mutex, &timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
extern "C" int
|
||||||
|
@ -2756,7 +2801,7 @@ pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
|
|
||||||
return __pthread_cond_dowait (cond, mutex, INFINITE);
|
return __pthread_cond_dowait (cond, mutex, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
extern "C" int
|
||||||
|
@ -3439,8 +3484,7 @@ semaphore::_trywait ()
|
||||||
int
|
int
|
||||||
semaphore::_timedwait (const struct timespec *abstime)
|
semaphore::_timedwait (const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
LARGE_INTEGER timeout;
|
||||||
long waitlength;
|
|
||||||
|
|
||||||
myfault efault;
|
myfault efault;
|
||||||
if (efault.faulted ())
|
if (efault.faulted ())
|
||||||
|
@ -3453,12 +3497,10 @@ semaphore::_timedwait (const struct timespec *abstime)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gettimeofday (&tv, NULL);
|
timeout.QuadPart = abstime->tv_sec * NSPERSEC
|
||||||
waitlength = abstime->tv_sec * 1000 + abstime->tv_nsec / (1000 * 1000);
|
+ (abstime->tv_nsec + 99) / 100 + FACTOR;
|
||||||
waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
||||||
if (waitlength < 0)
|
switch (cancelable_wait (win32_obj_id, &timeout, cw_cancel_self, cw_sig_eintr))
|
||||||
waitlength = 0;
|
|
||||||
switch (cancelable_wait (win32_obj_id, waitlength, cw_cancel_self, cw_sig_eintr))
|
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
currentvalue--;
|
currentvalue--;
|
||||||
|
@ -3480,7 +3522,7 @@ semaphore::_timedwait (const struct timespec *abstime)
|
||||||
int
|
int
|
||||||
semaphore::_wait ()
|
semaphore::_wait ()
|
||||||
{
|
{
|
||||||
switch (cancelable_wait (win32_obj_id, INFINITE, cw_cancel_self, cw_sig_eintr))
|
switch (cancelable_wait (win32_obj_id, NULL, cw_cancel_self, cw_sig_eintr))
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
currentvalue--;
|
currentvalue--;
|
||||||
|
|
|
@ -37,7 +37,8 @@ enum cw_cancel_action
|
||||||
cw_no_cancel
|
cw_no_cancel
|
||||||
};
|
};
|
||||||
|
|
||||||
DWORD cancelable_wait (HANDLE, DWORD, const cw_cancel_action = cw_cancel_self,
|
DWORD cancelable_wait (HANDLE, PLARGE_INTEGER timeout = NULL,
|
||||||
|
const cw_cancel_action = cw_cancel_self,
|
||||||
const enum cw_sig_wait = cw_sig_nosig)
|
const enum cw_sig_wait = cw_sig_nosig)
|
||||||
__attribute__ ((regparm (3)));
|
__attribute__ ((regparm (3)));
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ public:
|
||||||
void lock ()
|
void lock ()
|
||||||
{
|
{
|
||||||
if (InterlockedIncrement ((long *) &lock_counter) != 1)
|
if (InterlockedIncrement ((long *) &lock_counter) != 1)
|
||||||
cancelable_wait (win32_obj_id, INFINITE, cw_no_cancel, cw_sig_resume);
|
cancelable_wait (win32_obj_id, NULL, cw_no_cancel, cw_sig_resume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock ()
|
void unlock ()
|
||||||
|
@ -517,7 +518,7 @@ public:
|
||||||
pthread_mutex_t mtx_cond;
|
pthread_mutex_t mtx_cond;
|
||||||
|
|
||||||
void unblock (const bool all);
|
void unblock (const bool all);
|
||||||
int wait (pthread_mutex_t mutex, DWORD dwMilliseconds = INFINITE);
|
int wait (pthread_mutex_t mutex, PLARGE_INTEGER timeout = NULL);
|
||||||
|
|
||||||
pthread_cond (pthread_condattr *);
|
pthread_cond (pthread_condattr *);
|
||||||
~pthread_cond ();
|
~pthread_cond ();
|
||||||
|
|
|
@ -27,10 +27,6 @@ details. */
|
||||||
#include "cygtls.h"
|
#include "cygtls.h"
|
||||||
#include "ntdll.h"
|
#include "ntdll.h"
|
||||||
|
|
||||||
/* 100ns difference between WIndows and UNIX timebase. */
|
|
||||||
#define FACTOR (0x19db1ded53e8000LL)
|
|
||||||
/* # of 100ns intervals per second. */
|
|
||||||
#define NSPERSEC 10000000LL
|
|
||||||
/* Max allowed diversion in 100ns of internal timer from system time. If
|
/* Max allowed diversion in 100ns of internal timer from system time. If
|
||||||
this difference is exceeded, the internal timer gets re-primed. */
|
this difference is exceeded, the internal timer gets re-primed. */
|
||||||
#define JITTER (40 * 10000LL)
|
#define JITTER (40 * 10000LL)
|
||||||
|
@ -737,7 +733,7 @@ hires_ms::resolution ()
|
||||||
|
|
||||||
status = NtQueryTimerResolution (&coarsest, &finest, &actual);
|
status = NtQueryTimerResolution (&coarsest, &finest, &actual);
|
||||||
if (NT_SUCCESS (status))
|
if (NT_SUCCESS (status))
|
||||||
minperiod = (DWORD) actual / 10000L;
|
minperiod = (DWORD) actual;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Try to empirically determine current timer resolution */
|
/* Try to empirically determine current timer resolution */
|
||||||
|
@ -757,13 +753,9 @@ hires_ms::resolution ()
|
||||||
period += now - then;
|
period += now - then;
|
||||||
}
|
}
|
||||||
SetThreadPriority (GetCurrentThread (), priority);
|
SetThreadPriority (GetCurrentThread (), priority);
|
||||||
period /= 40000L;
|
period /= 4L;
|
||||||
minperiod = (DWORD) period;
|
minperiod = (DWORD) period;
|
||||||
}
|
}
|
||||||
/* The resolution can be as low as 5000 100ns intervals on recent OSes.
|
|
||||||
We have to make sure that the resolution in ms is never 0. */
|
|
||||||
if (!minperiod)
|
|
||||||
minperiod = 1L;
|
|
||||||
}
|
}
|
||||||
return minperiod;
|
return minperiod;
|
||||||
}
|
}
|
||||||
|
@ -786,8 +778,8 @@ clock_getres (clockid_t clk_id, struct timespec *tp)
|
||||||
case CLOCK_REALTIME:
|
case CLOCK_REALTIME:
|
||||||
{
|
{
|
||||||
DWORD period = gtod.resolution ();
|
DWORD period = gtod.resolution ();
|
||||||
tp->tv_sec = period / 1000;
|
tp->tv_sec = period / NSPERSEC;
|
||||||
tp->tv_nsec = (period % 1000) * 1000000;
|
tp->tv_nsec = (period % NSPERSEC) * 100;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,7 +830,7 @@ clock_setres (clockid_t clk_id, struct timespec *tp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (period_set
|
if (period_set
|
||||||
&& NT_SUCCESS (NtSetTimerResolution (minperiod * 10000L, FALSE, &actual)))
|
&& NT_SUCCESS (NtSetTimerResolution (minperiod, FALSE, &actual)))
|
||||||
period_set = false;
|
period_set = false;
|
||||||
|
|
||||||
status = NtSetTimerResolution (period, TRUE, &actual);
|
status = NtSetTimerResolution (period, TRUE, &actual);
|
||||||
|
@ -847,11 +839,7 @@ clock_setres (clockid_t clk_id, struct timespec *tp)
|
||||||
__seterrno_from_nt_status (status);
|
__seterrno_from_nt_status (status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
minperiod = actual / 10000L;
|
minperiod = actual;
|
||||||
/* The resolution can be as low as 5000 100ns intervals on recent OSes.
|
|
||||||
We have to make sure that the resolution in ms is never 0. */
|
|
||||||
if (!minperiod)
|
|
||||||
minperiod = 1L;
|
|
||||||
period_set = true;
|
period_set = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//;# autogenerated: Do not edit.
|
//;# autogenerated: Do not edit.
|
||||||
|
|
||||||
//; $tls::sizeof__cygtls = 4044;
|
//; $tls::sizeof__cygtls = 4048;
|
||||||
//; $tls::func = -12700;
|
//; $tls::func = -12700;
|
||||||
//; $tls::pfunc = 0;
|
//; $tls::pfunc = 0;
|
||||||
//; $tls::saved_errno = -12696;
|
//; $tls::saved_errno = -12696;
|
||||||
|
@ -37,26 +37,26 @@
|
||||||
//; $tls::p__dontuse = 412;
|
//; $tls::p__dontuse = 412;
|
||||||
//; $tls::locals = -11200;
|
//; $tls::locals = -11200;
|
||||||
//; $tls::plocals = 1500;
|
//; $tls::plocals = 1500;
|
||||||
//; $tls::_ctinfo = -9740;
|
//; $tls::_ctinfo = -9736;
|
||||||
//; $tls::p_ctinfo = 2960;
|
//; $tls::p_ctinfo = 2964;
|
||||||
//; $tls::andreas = -9736;
|
//; $tls::andreas = -9732;
|
||||||
//; $tls::pandreas = 2964;
|
//; $tls::pandreas = 2968;
|
||||||
//; $tls::wq = -9732;
|
//; $tls::wq = -9728;
|
||||||
//; $tls::pwq = 2968;
|
//; $tls::pwq = 2972;
|
||||||
//; $tls::sig = -9704;
|
//; $tls::sig = -9700;
|
||||||
//; $tls::psig = 2996;
|
//; $tls::psig = 3000;
|
||||||
//; $tls::incyg = -9700;
|
//; $tls::incyg = -9696;
|
||||||
//; $tls::pincyg = 3000;
|
//; $tls::pincyg = 3004;
|
||||||
//; $tls::spinning = -9696;
|
//; $tls::spinning = -9692;
|
||||||
//; $tls::pspinning = 3004;
|
//; $tls::pspinning = 3008;
|
||||||
//; $tls::stacklock = -9692;
|
//; $tls::stacklock = -9688;
|
||||||
//; $tls::pstacklock = 3008;
|
//; $tls::pstacklock = 3012;
|
||||||
//; $tls::stackptr = -9688;
|
//; $tls::stackptr = -9684;
|
||||||
//; $tls::pstackptr = 3012;
|
//; $tls::pstackptr = 3016;
|
||||||
//; $tls::stack = -9684;
|
//; $tls::stack = -9680;
|
||||||
//; $tls::pstack = 3016;
|
//; $tls::pstack = 3020;
|
||||||
//; $tls::initialized = -8660;
|
//; $tls::initialized = -8656;
|
||||||
//; $tls::pinitialized = 4040;
|
//; $tls::pinitialized = 4044;
|
||||||
//; __DATA__
|
//; __DATA__
|
||||||
|
|
||||||
#define tls_func (-12700)
|
#define tls_func (-12700)
|
||||||
|
@ -95,23 +95,23 @@
|
||||||
#define tls_p__dontuse (412)
|
#define tls_p__dontuse (412)
|
||||||
#define tls_locals (-11200)
|
#define tls_locals (-11200)
|
||||||
#define tls_plocals (1500)
|
#define tls_plocals (1500)
|
||||||
#define tls__ctinfo (-9740)
|
#define tls__ctinfo (-9736)
|
||||||
#define tls_p_ctinfo (2960)
|
#define tls_p_ctinfo (2964)
|
||||||
#define tls_andreas (-9736)
|
#define tls_andreas (-9732)
|
||||||
#define tls_pandreas (2964)
|
#define tls_pandreas (2968)
|
||||||
#define tls_wq (-9732)
|
#define tls_wq (-9728)
|
||||||
#define tls_pwq (2968)
|
#define tls_pwq (2972)
|
||||||
#define tls_sig (-9704)
|
#define tls_sig (-9700)
|
||||||
#define tls_psig (2996)
|
#define tls_psig (3000)
|
||||||
#define tls_incyg (-9700)
|
#define tls_incyg (-9696)
|
||||||
#define tls_pincyg (3000)
|
#define tls_pincyg (3004)
|
||||||
#define tls_spinning (-9696)
|
#define tls_spinning (-9692)
|
||||||
#define tls_pspinning (3004)
|
#define tls_pspinning (3008)
|
||||||
#define tls_stacklock (-9692)
|
#define tls_stacklock (-9688)
|
||||||
#define tls_pstacklock (3008)
|
#define tls_pstacklock (3012)
|
||||||
#define tls_stackptr (-9688)
|
#define tls_stackptr (-9684)
|
||||||
#define tls_pstackptr (3012)
|
#define tls_pstackptr (3016)
|
||||||
#define tls_stack (-9684)
|
#define tls_stack (-9680)
|
||||||
#define tls_pstack (3016)
|
#define tls_pstack (3020)
|
||||||
#define tls_initialized (-8660)
|
#define tls_initialized (-8656)
|
||||||
#define tls_pinitialized (4040)
|
#define tls_pinitialized (4044)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* wait.cc: Posix wait routines.
|
/* wait.cc: Posix wait routines.
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||||
|
2005, 2009, 2011 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -78,7 +79,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
|
||||||
if ((waitfor = w->ev) == NULL)
|
if ((waitfor = w->ev) == NULL)
|
||||||
goto nochildren;
|
goto nochildren;
|
||||||
|
|
||||||
res = cancelable_wait (waitfor, INFINITE);
|
res = cancelable_wait (waitfor);
|
||||||
|
|
||||||
sigproc_printf ("%d = WaitForSingleObject (...)", res);
|
sigproc_printf ("%d = WaitForSingleObject (...)", res);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue