cygwin: simplify pthread timedwait handling
- Introduce inline helper pthread_convert_abstime. It converts an absolute timespec to a Windows LARGE_INTEGER timestamp, depending on the used clock. - Use this function from pthread_cond_timedwait and semaphore::timedwait - Merge semaphore::_wait and semaphore::_timedwait into single _wait method, taking a LARGER_INTEGER timestamp. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
a346a26790
commit
68217c3178
|
@ -2515,6 +2515,41 @@ pthread::resume (pthread_t *thread)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
pthread_convert_abstime (clockid_t clock_id, const struct timespec *abstime,
|
||||
PLARGE_INTEGER timeout)
|
||||
{
|
||||
struct timespec tp;
|
||||
|
||||
/* According to SUSv3, the abstime value must be checked for validity. */
|
||||
if (abstime->tv_sec < 0
|
||||
|| abstime->tv_nsec < 0
|
||||
|| abstime->tv_nsec > 999999999)
|
||||
return EINVAL;
|
||||
|
||||
/* Check for immediate timeout before converting */
|
||||
clock_gettime (clock_id, &tp);
|
||||
if (tp.tv_sec > abstime->tv_sec
|
||||
|| (tp.tv_sec == abstime->tv_sec
|
||||
&& tp.tv_nsec > abstime->tv_nsec))
|
||||
return ETIMEDOUT;
|
||||
|
||||
timeout->QuadPart = abstime->tv_sec * NSPERSEC
|
||||
+ (abstime->tv_nsec + 99LL) / 100LL;
|
||||
switch (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 0;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
|
||||
{
|
||||
|
@ -2841,7 +2876,6 @@ extern "C" int
|
|||
pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
struct timespec tp;
|
||||
LARGE_INTEGER timeout;
|
||||
|
||||
pthread_testcancel ();
|
||||
|
@ -2852,34 +2886,10 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* According to SUSv3, the abstime value must be checked for validity. */
|
||||
if (abstime->tv_sec < 0
|
||||
|| abstime->tv_nsec < 0
|
||||
|| abstime->tv_nsec > 999999999)
|
||||
__leave;
|
||||
err = pthread_convert_abstime ((*cond)->clock_id, abstime, &timeout);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
clock_gettime ((*cond)->clock_id, &tp);
|
||||
|
||||
/* Check for immediate timeout before converting */
|
||||
if (tp.tv_sec > abstime->tv_sec
|
||||
|| (tp.tv_sec == abstime->tv_sec
|
||||
&& tp.tv_nsec > abstime->tv_nsec))
|
||||
return ETIMEDOUT;
|
||||
|
||||
timeout.QuadPart = abstime->tv_sec * NSPERSEC
|
||||
+ (abstime->tv_nsec + 99LL) / 100LL;
|
||||
|
||||
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 (*cond)->wait (*mutex, &timeout);
|
||||
}
|
||||
__except (NO_ERROR) {}
|
||||
|
@ -3597,16 +3607,11 @@ semaphore::_trywait ()
|
|||
}
|
||||
|
||||
int
|
||||
semaphore::_timedwait (const struct timespec *abstime)
|
||||
semaphore::_wait (PLARGE_INTEGER timeout)
|
||||
{
|
||||
LARGE_INTEGER timeout;
|
||||
|
||||
__try
|
||||
{
|
||||
timeout.QuadPart = abstime->tv_sec * NSPERSEC
|
||||
+ (abstime->tv_nsec + 99) / 100 + FACTOR;
|
||||
|
||||
switch (cygwait (win32_obj_id, &timeout,
|
||||
switch (cygwait (win32_obj_id, timeout,
|
||||
cw_cancel | cw_cancel_self | cw_sig_eintr))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
|
@ -3623,38 +3628,11 @@ semaphore::_timedwait (const struct timespec *abstime)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
__except (NO_ERROR)
|
||||
{
|
||||
/* According to SUSv3, abstime need not be checked for validity,
|
||||
if the semaphore can be locked immediately. */
|
||||
if (_trywait ())
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
__except (NO_ERROR) {}
|
||||
__endtry
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
semaphore::_wait ()
|
||||
{
|
||||
switch (cygwait (win32_obj_id, cw_infinite,
|
||||
cw_cancel | cw_cancel_self | cw_sig_eintr))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_SIGNALED:
|
||||
set_errno (EINTR);
|
||||
return -1;
|
||||
default:
|
||||
pthread_printf ("cygwait failed. %E");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
semaphore::_fixup_before_fork ()
|
||||
{
|
||||
|
@ -3840,13 +3818,30 @@ semaphore::trywait (sem_t *sem)
|
|||
int
|
||||
semaphore::timedwait (sem_t *sem, const struct timespec *abstime)
|
||||
{
|
||||
LARGE_INTEGER timeout;
|
||||
|
||||
if (!is_good_object (sem))
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (*sem)->_timedwait (abstime);
|
||||
/* According to SUSv3, abstime need not be checked for validity,
|
||||
if the semaphore can be locked immediately. */
|
||||
if (!(*sem)->_trywait ())
|
||||
return 0;
|
||||
|
||||
__try
|
||||
{
|
||||
int err = pthread_convert_abstime (CLOCK_REALTIME, abstime, &timeout);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return (*sem)->_wait (&timeout);
|
||||
}
|
||||
__except (NO_ERROR) {}
|
||||
__endtry
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -693,11 +693,10 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
int _wait ();
|
||||
void _post ();
|
||||
int _getvalue (int *sval);
|
||||
int _trywait ();
|
||||
int _timedwait (const struct timespec *abstime);
|
||||
int _wait (PLARGE_INTEGER timeout = NULL);
|
||||
|
||||
void _fixup_before_fork ();
|
||||
void _fixup_after_fork ();
|
||||
|
|
Loading…
Reference in New Issue