On Sun, Apr 16, 2006 at 12:50:47AM +0200, Richard Braun wrote: > Hello, > > During my work on the BPF translator, I was told translators shouldn't > use pthreads for now. So I switched to cthreads and noticed there was > no condition_timedwait() function. Here is a patch that adds this > function to the Hurd. I wasn't brave enough to write > hurd_condition_timedwait() - a cancellable version of condition_timedwait(). > > Basically, condition_timedwait() is at the same time like condition_wait() > and pthread_cond_timedwait(). A third parameter of type struct timespec * > was added. If that parameter is NULL, condition_timedwait() acts the same > as condition_wait(). That function could be implemented as a macro, but > I let it in place so that the global symbol still exists (otherwise, I > guess many applications would break). > > condition_timedwait() returns TRUE if a timeout occurred, FALSE otherwise. > Here is the patch :
As there were no answer, though some people are interested in this, I resend the patch so that it can be reviewed. 2006-04-16 Richard Braun <[EMAIL PROTECTED]> * libthreads/cancel-cond.c: call to cproc_block() updated. * libthreads/cprocs.c: Implemented condition_timedwait(), modified cproc_block() to use a timeout. * libthreads/cthread_internals.h: Added CPROC_TIMEDOUT macro. * libthreads/cthreads.h: added the prototype for condition_timedwait(). diff -Nurp libthreads.orig/cancel-cond.c libthreads/cancel-cond.c --- libthreads.orig/cancel-cond.c 2006-04-16 16:32:53.000000000 +0000 +++ libthreads/cancel-cond.c 2006-04-16 16:50:01.000000000 +0000 @@ -83,7 +83,7 @@ hurd_condition_wait (condition_t c, mute spin_lock (&p->lock); if (p->state & CPROC_SWITCHING) - cproc_block (); + cproc_block (MACH_MSG_TIMEOUT_NONE); else { /* We were woken up someplace before reacquiring P->lock. diff -Nurp libthreads.orig/cprocs.c libthreads/cprocs.c --- libthreads.orig/cprocs.c 2006-04-16 16:32:53.000000000 +0000 +++ libthreads/cprocs.c 2006-04-16 16:53:30.000000000 +0000 @@ -239,6 +239,9 @@ #include <mach/message.h> #include <hurd/threadvar.h> /* GNU */ #include <assert.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> /* * Port_entry's are used by cthread_mach_msg to store information @@ -629,7 +632,7 @@ cproc_waiter(void) */ void -cproc_block(void) +cproc_block(mach_msg_timeout_t timeout) { extern unsigned int __hurd_threadvar_max; /* GNU */ register cproc_t waiter, new, p = cproc_self(); @@ -640,9 +643,22 @@ cproc_block(void) kern_return_t r; spin_unlock(&p->lock); - MACH_CALL(mach_msg(&msg, MACH_RCV_MSG, - 0, sizeof msg, p->wired, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL), r); + + if (timeout == MACH_MSG_TIMEOUT_NONE) + MACH_CALL(mach_msg(&msg, MACH_RCV_MSG, + 0, sizeof msg, p->wired, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL), r); + + else { + MACH_CALL(mach_msg(&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, + 0, sizeof msg, p->wired, + timeout, MACH_PORT_NULL), r); + + if (r == EMACH_RCV_TIMED_OUT) + p->state |= CPROC_TIMEDOUT; + } + return; } p->state = CPROC_SWITCHING; @@ -769,7 +785,44 @@ cproc_create(void) void condition_wait(condition_t c, mutex_t m) { + condition_timedwait(c, m, NULL); +} + +int +condition_timedwait(condition_t c, mutex_t m, const struct timespec *t) +{ register cproc_t p = cproc_self(); + mach_msg_timeout_t timeout; + boolean_t timedout; + + if (t == NULL) { + timeout = MACH_MSG_TIMEOUT_NONE; + timedout = FALSE; + } else { + struct timeval now; + error_t err; + + /* + * Taken from libpthread (sysdeps/mach/pt-timedblock.c). + */ + err = gettimeofday(&now, NULL); + assert(!err); + + if (now.tv_sec > t->tv_sec + || (now.tv_sec == t->tv_sec + && now.tv_usec > ((t->tv_nsec + 999) / 1000))) + return TRUE; + + timeout = (t->tv_sec - now.tv_sec) * 1000; + + if (((t->tv_nsec + 999) / 1000) >= now.tv_usec) + timeout -= (((t->tv_nsec + 999) / 1000) + - now.tv_usec + 999) / 1000; + + else + timeout -= 1000 + ((t->tv_nsec + 999999) / 1000000) + - (now.tv_usec + 999) / 1000; + } p->state = CPROC_CONDWAIT | CPROC_SWITCHING; @@ -784,13 +837,16 @@ condition_wait(condition_t c, mutex_t m) spin_lock(&p->lock); if (p->state & CPROC_SWITCHING) { - cproc_block(); + cproc_block(timeout); + timedout = (p->state & CPROC_TIMEDOUT) ? TRUE : FALSE; + + if (timedout) + p->state &= ~CPROC_TIMEDOUT; } else { p->state = CPROC_RUNNING; spin_unlock(&p->lock); } - #ifdef WAIT_DEBUG p->waiting_for = (char *)0; #endif /* WAIT_DEBUG */ @@ -799,6 +855,8 @@ condition_wait(condition_t c, mutex_t m) * Re-acquire the mutex and return. */ mutex_lock(m); + + return timedout; } /* Declare that IMPLICATOR should consider IMPLICATAND's waiter queue @@ -951,7 +1009,7 @@ __mutex_lock_solid(void *ptr) if (!queued) cthread_queue_enq(&m->queue, p); spin_lock(&p->lock); spin_unlock(&m->lock); - cproc_block(); + cproc_block(MACH_MSG_TIMEOUT_NONE); if (spin_try_lock(&m->held)) { #ifdef WAIT_DEBUG p->waiting_for = (char *)0; @@ -1108,7 +1166,7 @@ cthread_mach_msg(register mach_msg_heade #ifdef WAIT_DEBUG p->waiting_for = (char *)port_entry; #endif /* WAIT_DEBUG */ - cproc_block(); + cproc_block(MACH_MSG_TIMEOUT_NONE); } else { port_entry->held++; spin_unlock(&port_entry->lock); diff -Nurp libthreads.orig/cthread_internals.h libthreads/cthread_internals.h --- libthreads.orig/cthread_internals.h 2006-04-16 16:32:53.000000000 +0000 +++ libthreads/cthread_internals.h 2006-04-16 16:49:24.000000000 +0000 @@ -186,6 +186,7 @@ typedef struct cproc { #define CPROC_SWITCHING 1 #define CPROC_BLOCKED 2 #define CPROC_CONDWAIT 4 +#define CPROC_TIMEDOUT 8 mach_port_t wired; /* is cthread wired to kernel thread */ void *busy; /* used with cthread_msg calls */ diff -Nurp libthreads.orig/cthreads.h libthreads/cthreads.h --- libthreads.orig/cthreads.h 2006-04-16 16:32:53.000000000 +0000 +++ libthreads/cthreads.h 2006-04-16 16:49:24.000000000 +0000 @@ -497,6 +497,12 @@ extern void cond_broadcast(condition_t _ extern void condition_wait(condition_t _cond, mutex_t _mutex); extern int hurd_condition_wait(condition_t _cond, mutex_t _mutex); +/* + * Return TRUE if no signal was received before timeout. + */ +extern int condition_timedwait(condition_t _cond, mutex_t _mutex, + const struct timespec *_abstime); + extern void condition_implies(condition_t _implicator, condition_t _implicatand); extern void condition_unimplies(condition_t _implicator, -- Richard Braun
signature.asc
Description: Digital signature
_______________________________________________ Bug-hurd mailing list Bug-hurd@gnu.org http://lists.gnu.org/mailman/listinfo/bug-hurd