From cea39829af96700dd083bf6e17593c2b6fce1685 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 8 Feb 2007 11:26:43 +0000 Subject: [PATCH] Make empth_wakeup() and empth_terminate() wake up empth_sleep(), and empth_sleep() return whether that happened: [EMPTH_LWP] (lwpWakeupSleep): New, factored out of lwpSelect(). [EMPTH_LWP] (lwpSelect): Use it. [EMPTH_LWP] (lwpWakeup): New. Call lwpWakeupFd() if sleeping in lwpSleepFd(), lwpWakeupSleep() if sleeping in lwpSleepUntil(). [EMPTH_LWP] (lwpTerminate, empth_wakeup): Use it rather than lwpWakeupFd(). [EMPTH_LWP] (lwpWakeupFd): Internal linkage. [EMPTH_LWP] (lwpSleepUntil): Reset member runtime, so that lwpWakeup() can test it reliably. Return how sleep woke up. [EMPTH_LWP] (empth_sleep): Return value of lwpSleepUntil(). [EMPTH_POSIX] (EMPTH_INTR): New. [EMPTH_POSIX] (empth_wakeup): Set state to it. [EMPTH_POSIX] (empth_restorectx): Clear state. [EMPTH_POSIX] (empth_sleep): Don't re-seleep when state is not clear, i.e. thread was woken up prematurely. Return how sleep woke up. [EMPTH_W32] (empth_sleep): Implement by waiting on hThreadEvent with a timeout rather than a straight Sleep(). Return how sleep woke up. --- include/empthread.h | 7 +++-- include/lwp.h | 4 +-- src/lib/empthread/lwp.c | 6 ++-- src/lib/empthread/ntthread.c | 22 ++++++++------ src/lib/empthread/pthread.c | 20 ++++++++----- src/lib/lwp/lwp.c | 9 +++--- src/lib/lwp/sel.c | 57 ++++++++++++++++++++++++++---------- 7 files changed, 80 insertions(+), 45 deletions(-) diff --git a/include/empthread.h b/include/empthread.h index ee9ce7dec..ea8ab88bc 100644 --- a/include/empthread.h +++ b/include/empthread.h @@ -181,7 +181,7 @@ void empth_terminate(empth_t *thread); void empth_select(int fd, int flags); /* - * Awaken THREAD if it is sleeping in empth_select(). + * Awaken THREAD if it is sleeping in empth_select() or empth_sleep(). * Note: This must not awaken threads sleeping in other functions. * Does not yield the processor. */ @@ -189,9 +189,10 @@ void empth_wakeup(empth_t *thread); /* * Put current thread to sleep until the time is UNTIL. - * May sleep somehwat longer, but never shorter. + * Return 0 if it slept until that time. + * Return -1 if woken up early, by empth_wakeup(). */ -void empth_sleep(time_t until); +int empth_sleep(time_t until); /* * Wait for signal, return the signal number. diff --git a/include/lwp.h b/include/lwp.h index 54a586ebb..954ed689f 100644 --- a/include/lwp.h +++ b/include/lwp.h @@ -47,8 +47,8 @@ void lwpExit(void); void lwpTerminate(struct lwpProc * p); void lwpYield(void); void lwpSleepFd(int fd, int flags); -void lwpSleepUntil(time_t until); -void lwpWakeupFd(struct lwpProc * p); +int lwpSleepUntil(time_t until); +void lwpWakeup(struct lwpProc *); int lwpSigWait(sigset_t *set, int *sig); void *lwpGetUD(struct lwpProc * p); void lwpSetUD(struct lwpProc * p, char *ud); diff --git a/src/lib/empthread/lwp.c b/src/lib/empthread/lwp.c index 41432cae8..bfafbbe45 100644 --- a/src/lib/empthread/lwp.c +++ b/src/lib/empthread/lwp.c @@ -101,13 +101,13 @@ empth_select(int fd, int flags) void empth_wakeup(empth_t *a) { - lwpWakeupFd(a); + lwpWakeup(a); } -void +int empth_sleep(time_t until) { - lwpSleepUntil(until); + return lwpSleepUntil(until); } int diff --git a/src/lib/empthread/ntthread.c b/src/lib/empthread/ntthread.c index cd51c3ba9..0073cd283 100644 --- a/src/lib/empthread/ntthread.c +++ b/src/lib/empthread/ntthread.c @@ -599,21 +599,25 @@ empth_wakeup(empth_t *pThread) * * Put the given thread to sleep... */ -void +int empth_sleep(time_t until) { long lSec; + empth_t *pThread = TlsGetValue(dwTLSIndex); + int iReturn = 0; - loc_BlockThisThread(); - - while ((lSec = until - time(0)) > 0) { - loc_debug("going to sleep %ld sec", lSec); - Sleep(lSec * 1000L); - } + if ((lSec = until - time(0)) > 0) { + loc_BlockThisThread(); + loc_debug("going to sleep %ld sec", lSec); - loc_debug("sleep done. Waiting to run."); + if (WaitForSingleObject(pThread->hThreadEvent, lSec * 1000L) != + WAIT_TIMEOUT) + iReturn = -1; - loc_RunThisThread(NULL); + loc_debug("sleep done. Waiting to run."); + loc_RunThisThread(NULL); + } + return iReturn; } /************************ diff --git a/src/lib/empthread/pthread.c b/src/lib/empthread/pthread.c index b0e8dc727..201f31085 100644 --- a/src/lib/empthread/pthread.c +++ b/src/lib/empthread/pthread.c @@ -58,6 +58,7 @@ #include "prototypes.h" #define EMPTH_KILLED 1 +#define EMPTH_INTR 2 struct empth_t { char *name; /* thread name */ @@ -252,6 +253,7 @@ empth_restorectx(void) empth_status("i am dead"); empth_exit(); } + ctx_ptr->state = 0; empth_status("context restored"); } @@ -355,33 +357,37 @@ empth_alarm(int sig) { /* * Nothing to do --- we handle this signal just to let - * empth_wakeup() interrupt system calls. + * empth_wakeup() and empth_terminate() interrupt system calls. */ - empth_status("got alarm signal"); } void empth_wakeup(empth_t *a) { empth_status("waking up thread %s", a->name); + if (a->state == 0) + a->state = EMPTH_INTR; pthread_kill(a->id, SIGALRM); } -void +int empth_sleep(time_t until) { + empth_t *ctx = pthread_getspecific(ctx_key); struct timeval tv; + int res; empth_status("going to sleep %ld sec", until - time(0)); pthread_mutex_unlock(&mtx_ctxsw); - tv.tv_sec = until - time(NULL); - tv.tv_usec = 0; do { - select(0, NULL, NULL, NULL, &tv); - } while ((tv.tv_sec = until - time(NULL)) > 0); + tv.tv_sec = until - time(NULL); + tv.tv_usec = 0; + res = select(0, NULL, NULL, NULL, &tv); + } while (res < 0 && ctx->state == 0); empth_status("sleep done. Waiting for lock"); pthread_mutex_lock(&mtx_ctxsw); empth_restorectx(); + return res; } int diff --git a/src/lib/lwp/lwp.c b/src/lib/lwp/lwp.c index 2cf1a4c70..a3bb2423e 100644 --- a/src/lib/lwp/lwp.c +++ b/src/lib/lwp/lwp.c @@ -29,7 +29,7 @@ * lwp.c: lightweight process creation, destruction and manipulation * * Known contributors to this file: - * Markus Armbruster, 2004-2006 + * Markus Armbruster, 2004-2007 */ #include @@ -145,7 +145,7 @@ lwpCreate(int priority, void (*entry)(void *), int stacksz, newp->argv = argv; newp->ud = ud; newp->dead = 0; - newp->runtime = -1; + newp->runtime = (time_t)-1; newp->fd = -1; if (LWP_MAX_PRIO <= priority) priority = LWP_MAX_PRIO - 1; @@ -166,7 +166,7 @@ lwpCreate(int priority, void (*entry)(void *), int stacksz, return newp; } -void +static void lwpDestroy(struct lwpProc *proc) { if (proc->flags & LWP_STACKCHECK) { @@ -244,8 +244,7 @@ lwpTerminate(struct lwpProc *p) { lwpStatus(p, "terminating process"); p->dead = 1; - if (p->fd >= 0) - lwpWakeupFd(p); + lwpWakeup(p); } /* diff --git a/src/lib/lwp/sel.c b/src/lib/lwp/sel.c index 77dea0386..cb360eed0 100644 --- a/src/lib/lwp/sel.c +++ b/src/lib/lwp/sel.c @@ -30,6 +30,7 @@ * * Known contributors to this file: * Dave Pare, 1994 + * Markus Armbruster, 2007 */ #include @@ -107,7 +108,7 @@ lwpSleepFd(int fd, int mask) lwpReschedule(); } -void +static void lwpWakeupFd(struct lwpProc *proc) { if (proc->fd < 0) @@ -122,9 +123,44 @@ lwpWakeupFd(struct lwpProc *proc) lwpReady(proc); } +static void +lwpWakeupSleep(void) +{ + time_t now; + struct lwpQueue save; + struct lwpProc *proc; + + if (LwpDelayq.head) { + now = time(NULL); + save.tail = save.head = 0; + while (NULL != (proc = lwpGetFirst(&LwpDelayq))) { + if (now >= proc->runtime) { + lwpStatus(proc, "sleep done"); + lwpReady(proc); + } else { + lwpAddTail(&save, proc); + } + } + LwpDelayq = save; + } +} + void +lwpWakeup(struct lwpProc *proc) +{ + if (proc->fd >= 0) + lwpWakeupFd(proc); + else if (proc->runtime != (time_t)-1) { + proc->runtime = 0; + lwpWakeupSleep(); + } +} + +int lwpSleepUntil(time_t until) { + int res; + lwpStatus(LwpCurrent, "sleeping for %ld sec", (long)(until - time(NULL))); LwpCurrent->runtime = until; @@ -134,6 +170,9 @@ lwpSleepUntil(time_t until) } lwpAddTail(&LwpDelayq, LwpCurrent); lwpReschedule(); + res = LwpCurrent->runtime ? 0 : -1; + LwpCurrent->runtime = (time_t)-1; + return res; } /*ARGSUSED*/ @@ -149,7 +188,6 @@ lwpSelect(void *arg) time_t delta; struct lwpProc *proc; struct timeval tv; - struct lwpQueue save; lwpStatus(us, "starting select loop"); FD_ZERO(&readmask); @@ -194,20 +232,7 @@ lwpSelect(void *arg) continue; } - if (LwpDelayq.head) { - /* sleeping proecss activity */ - time(&now); - save.tail = save.head = 0; - while (NULL != (proc = lwpGetFirst(&LwpDelayq))) { - if (now >= proc->runtime) { - lwpStatus(proc, "sleep done"); - lwpReady(proc); - } else { - lwpAddTail(&save, proc); - } - } - LwpDelayq = save; - } + lwpWakeupSleep(); if (n > 0) { /* file descriptor activity */ for (fd = 0; fd <= LwpMaxfd; fd++) { -- 2.43.0