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;
|
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
|
extern "C" int
|
||||||
pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
|
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,
|
pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||||
const struct timespec *abstime)
|
const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
struct timespec tp;
|
|
||||||
LARGE_INTEGER timeout;
|
LARGE_INTEGER timeout;
|
||||||
|
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
@ -2852,34 +2886,10 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* According to SUSv3, the abstime value must be checked for validity. */
|
err = pthread_convert_abstime ((*cond)->clock_id, abstime, &timeout);
|
||||||
if (abstime->tv_sec < 0
|
if (err)
|
||||||
|| abstime->tv_nsec < 0
|
return err;
|
||||||
|| abstime->tv_nsec > 999999999)
|
|
||||||
__leave;
|
|
||||||
|
|
||||||
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);
|
return (*cond)->wait (*mutex, &timeout);
|
||||||
}
|
}
|
||||||
__except (NO_ERROR) {}
|
__except (NO_ERROR) {}
|
||||||
@ -3597,16 +3607,11 @@ semaphore::_trywait ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
semaphore::_timedwait (const struct timespec *abstime)
|
semaphore::_wait (PLARGE_INTEGER timeout)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER timeout;
|
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
timeout.QuadPart = abstime->tv_sec * NSPERSEC
|
switch (cygwait (win32_obj_id, timeout,
|
||||||
+ (abstime->tv_nsec + 99) / 100 + FACTOR;
|
|
||||||
|
|
||||||
switch (cygwait (win32_obj_id, &timeout,
|
|
||||||
cw_cancel | cw_cancel_self | cw_sig_eintr))
|
cw_cancel | cw_cancel_self | cw_sig_eintr))
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
@ -3623,38 +3628,11 @@ semaphore::_timedwait (const struct timespec *abstime)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__except (NO_ERROR)
|
__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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__endtry
|
__endtry
|
||||||
return 0;
|
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
|
void
|
||||||
semaphore::_fixup_before_fork ()
|
semaphore::_fixup_before_fork ()
|
||||||
{
|
{
|
||||||
@ -3840,13 +3818,30 @@ semaphore::trywait (sem_t *sem)
|
|||||||
int
|
int
|
||||||
semaphore::timedwait (sem_t *sem, const struct timespec *abstime)
|
semaphore::timedwait (sem_t *sem, const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
|
|
||||||
if (!is_good_object (sem))
|
if (!is_good_object (sem))
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return -1;
|
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
|
int
|
||||||
|
@ -693,11 +693,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _wait ();
|
|
||||||
void _post ();
|
void _post ();
|
||||||
int _getvalue (int *sval);
|
int _getvalue (int *sval);
|
||||||
int _trywait ();
|
int _trywait ();
|
||||||
int _timedwait (const struct timespec *abstime);
|
int _wait (PLARGE_INTEGER timeout = NULL);
|
||||||
|
|
||||||
void _fixup_before_fork ();
|
void _fixup_before_fork ();
|
||||||
void _fixup_after_fork ();
|
void _fixup_after_fork ();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user