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.
*/
/*
* 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.
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);
void
empth_wakeup(empth_t *a)
{
- lwpWakeupFd(a);
+ lwpWakeup(a);
}
-void
+int
empth_sleep(time_t until)
{
- lwpSleepUntil(until);
+ return lwpSleepUntil(until);
}
int
*
* 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;
}
/************************
#include "prototypes.h"
#define EMPTH_KILLED 1
+#define EMPTH_INTR 2
struct empth_t {
char *name; /* thread name */
empth_status("i am dead");
empth_exit();
}
+ ctx_ptr->state = 0;
empth_status("context restored");
}
{
/*
* 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
* lwp.c: lightweight process creation, destruction and manipulation
*
* Known contributors to this file:
- * Markus Armbruster, 2004-2006
+ * Markus Armbruster, 2004-2007
*/
#include <config.h>
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;
return newp;
}
-void
+static void
lwpDestroy(struct lwpProc *proc)
{
if (proc->flags & LWP_STACKCHECK) {
{
lwpStatus(p, "terminating process");
p->dead = 1;
- if (p->fd >= 0)
- lwpWakeupFd(p);
+ lwpWakeup(p);
}
/*
*
* Known contributors to this file:
* Dave Pare, 1994
+ * Markus Armbruster, 2007
*/
#include <config.h>
lwpReschedule();
}
-void
+static void
lwpWakeupFd(struct lwpProc *proc)
{
if (proc->fd < 0)
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;
}
lwpAddTail(&LwpDelayq, LwpCurrent);
lwpReschedule();
+ res = LwpCurrent->runtime ? 0 : -1;
+ LwpCurrent->runtime = (time_t)-1;
+ return res;
}
/*ARGSUSED*/
time_t delta;
struct lwpProc *proc;
struct timeval tv;
- struct lwpQueue save;
lwpStatus(us, "starting select loop");
FD_ZERO(&readmask);
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++) {