[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Implementation of condition_timedwait() in libthreads
From: |
Richard Braun |
Subject: |
Re: Implementation of condition_timedwait() in libthreads |
Date: |
Mon, 7 Aug 2006 17:26:32 +0200 |
User-agent: |
Mutt/1.5.9i |
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 <syn@hurdfr.org>
* 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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: Implementation of condition_timedwait() in libthreads,
Richard Braun <=