htl: Make sem_wait/sem_timedwait interruptible

This commit is contained in:
Samuel Thibault 2020-02-10 00:52:50 +00:00
parent 1cec114b17
commit e9644c20ce
7 changed files with 47 additions and 9 deletions

View File

@ -108,6 +108,8 @@ libpthread-routines := pt-attr pt-attr-destroy pt-attr-getdetachstate \
\ \
pt-block \ pt-block \
pt-timedblock \ pt-timedblock \
pt-block-intr \
pt-timedblock-intr \
pt-wakeup \ pt-wakeup \
pt-docancel \ pt-docancel \
pt-sysdep \ pt-sysdep \

View File

@ -270,6 +270,14 @@ extern error_t __pthread_timedblock (struct __pthread *__restrict thread,
const struct timespec *__restrict abstime, const struct timespec *__restrict abstime,
clockid_t clock_id); clockid_t clock_id);
/* Block THREAD with interrupts. */
extern error_t __pthread_block_intr (struct __pthread *thread);
/* Block THREAD until *ABSTIME is reached, with interrupts. */
extern error_t __pthread_timedblock_intr (struct __pthread *__restrict thread,
const struct timespec *__restrict abstime,
clockid_t clock_id);
/* Wakeup THREAD. */ /* Wakeup THREAD. */
extern void __pthread_wakeup (struct __pthread *thread); extern void __pthread_wakeup (struct __pthread *thread);

View File

@ -30,6 +30,7 @@ __sem_timedwait_internal (sem_t *restrict sem,
error_t err; error_t err;
int drain; int drain;
struct __pthread *self; struct __pthread *self;
clockid_t clock_id = CLOCK_REALTIME;
__pthread_spin_lock (&sem->__lock); __pthread_spin_lock (&sem->__lock);
if (sem->__value > 0) if (sem->__value > 0)
@ -54,12 +55,9 @@ __sem_timedwait_internal (sem_t *restrict sem,
/* Block the thread. */ /* Block the thread. */
if (timeout != NULL) if (timeout != NULL)
err = __pthread_timedblock (self, timeout, CLOCK_REALTIME); err = __pthread_timedblock_intr (self, timeout, clock_id);
else else
{ err = __pthread_block_intr (self);
err = 0;
__pthread_block (self);
}
__pthread_spin_lock (&sem->__lock); __pthread_spin_lock (&sem->__lock);
if (self->prevp == NULL) if (self->prevp == NULL)
@ -82,7 +80,7 @@ __sem_timedwait_internal (sem_t *restrict sem,
if (err) if (err)
{ {
assert (err == ETIMEDOUT); assert (err == ETIMEDOUT || err == EINTR);
errno = err; errno = err;
return -1; return -1;
} }

View File

@ -0,0 +1,6 @@
#include <pt-internal.h>
#define RETTYPE error_t
#define RETURN(val) return val
#define __pthread_block __pthread_block_intr
#define MSG_OPTIONS MACH_RCV_INTERRUPT
#include "pt-block.c"

View File

@ -24,15 +24,30 @@
#include <pt-internal.h> #include <pt-internal.h>
#ifndef MSG_OPTIONS
# define MSG_OPTIONS 0
#endif
#ifndef RETTYPE
# define RETTYPE void
#endif
#ifndef RETURN
# define RETURN(val)
#endif
/* Block THREAD. */ /* Block THREAD. */
void RETTYPE
__pthread_block (struct __pthread *thread) __pthread_block (struct __pthread *thread)
{ {
mach_msg_header_t msg; mach_msg_header_t msg;
error_t err; error_t err;
err = __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg, err = __mach_msg (&msg, MACH_RCV_MSG | MSG_OPTIONS, 0, sizeof msg,
thread->wakeupmsg.msgh_remote_port, thread->wakeupmsg.msgh_remote_port,
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if ((MSG_OPTIONS & MACH_RCV_INTERRUPT) && err == MACH_RCV_INTERRUPTED)
RETURN(EINTR);
assert_perror (err); assert_perror (err);
RETURN(0);
} }

View File

@ -0,0 +1,3 @@
#define __pthread_timedblock __pthread_timedblock_intr
#define MSG_OPTIONS MACH_RCV_INTERRUPT
#include "pt-timedblock.c"

View File

@ -26,6 +26,10 @@
#include <pt-internal.h> #include <pt-internal.h>
#ifndef MSG_OPTIONS
# define MSG_OPTIONS 0
#endif
/* Block THREAD. */ /* Block THREAD. */
error_t error_t
__pthread_timedblock (struct __pthread *thread, __pthread_timedblock (struct __pthread *thread,
@ -54,11 +58,13 @@ __pthread_timedblock (struct __pthread *thread,
/* Need to do a carry. */ /* Need to do a carry. */
timeout -= (now.tv_nsec - abstime->tv_nsec + 999999) / 1000000; timeout -= (now.tv_nsec - abstime->tv_nsec + 999999) / 1000000;
err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT | MSG_OPTIONS, 0,
sizeof msg, thread->wakeupmsg.msgh_remote_port, sizeof msg, thread->wakeupmsg.msgh_remote_port,
timeout, MACH_PORT_NULL); timeout, MACH_PORT_NULL);
if (err == EMACH_RCV_TIMED_OUT) if (err == EMACH_RCV_TIMED_OUT)
return ETIMEDOUT; return ETIMEDOUT;
if ((MSG_OPTIONS & MACH_RCV_INTERRUPT) && err == MACH_RCV_INTERRUPTED)
return EINTR;
assert_perror (err); assert_perror (err);
return 0; return 0;