-/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* If you do not wish that, delete this exception notice. */
\f
-/* $Id: coop.c,v 1.21 2000-03-29 10:43:18 mdj Exp $ */
+/* $Id: coop.c,v 1.29 2001-11-04 15:52:29 ela Exp $ */
/* Cooperative thread library, based on QuickThreads */
+#include <stdio.h>
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
-#include <qt.h>
-#include "eval.h"
+#include "qt/qt.h"
+#include "libguile/eval.h"
\f/* #define COOP_STKSIZE (0x10000) */
#define COOP_STKSIZE (scm_eval_stack)
#ifdef GUILE_PTHREAD_COMPAT
static coop_q_t coop_deadq;
-pthread_cond_t coop_cond_quit;
+static int coop_quitting_p = -1;
+static pthread_cond_t coop_cond_quit;
+static pthread_cond_t coop_cond_create;
+static pthread_mutex_t coop_mutex_create;
+static pthread_t coop_mother;
+static int mother_awake_p = 0;
+static coop_t *coop_child;
#endif
static void *coop_starthelp (qt_t *old, void *ignore0, void *ignore1);
#endif
{
#ifdef GUILE_PTHREAD_COMPAT
+ coop_quitting_p = 1;
+ pthread_cond_signal (&coop_cond_create);
pthread_cond_broadcast (&coop_cond_quit);
#endif
}
#ifdef GUILE_PTHREAD_COMPAT
coop_qinit (&coop_deadq);
pthread_cond_init (&coop_cond_quit, NULL);
+ pthread_cond_init (&coop_cond_create, NULL);
+ pthread_mutex_init (&coop_mutex_create, NULL);
#endif
#ifdef HAVE_ATEXIT
atexit (coop_finish);
const struct timespec *abstime)
{
coop_t *old, *t;
+#ifdef ETIMEDOUT
int res = ETIMEDOUT;
+#elif defined (WSAETIMEDOUT)
+ int res = WSAETIMEDOUT;
+#else
+ int res = 0;
+#endif
/* coop_mutex_unlock (m); */
t = coop_qget (&(m->waiting));
dummy_start (void *coop_thread)
{
coop_t *t = (coop_t *) coop_thread;
+ int res;
t->sp = (qt_t *) (&t + COOP_STACK_ROOM);
+ pthread_mutex_init (&t->dummy_mutex, NULL);
pthread_mutex_lock (&t->dummy_mutex);
- pthread_cond_signal (&t->dummy_cond);
- pthread_cond_wait (&coop_cond_quit, &t->dummy_mutex);
+ coop_child = 0;
+ do
+ res = pthread_cond_wait (&coop_cond_quit, &t->dummy_mutex);
+ while (res == EINTR);
+ return 0;
+}
+
+static void *
+mother (void *dummy)
+{
+ pthread_mutex_lock (&coop_mutex_create);
+ while (!coop_quitting_p)
+ {
+ int res;
+ pthread_create (&coop_child->dummy_thread,
+ NULL,
+ dummy_start,
+ coop_child);
+ mother_awake_p = 0;
+ do
+ res = pthread_cond_wait (&coop_cond_create, &coop_mutex_create);
+ while (res == EINTR);
+ }
return 0;
}
+
#endif
coop_t *
t->specific = NULL;
t->n_keys = 0;
#ifdef GUILE_PTHREAD_COMPAT
- pthread_cond_init (&t->dummy_cond, NULL);
- pthread_mutex_init (&t->dummy_mutex, NULL);
- pthread_mutex_lock (&t->dummy_mutex);
- pthread_create (&t->dummy_thread, NULL, dummy_start, t);
- pthread_cond_wait (&t->dummy_cond, &t->dummy_mutex);
- pthread_mutex_unlock (&t->dummy_mutex);
+ coop_child = t;
+ mother_awake_p = 1;
+ if (coop_quitting_p < 0)
+ {
+ coop_quitting_p = 0;
+ /* We can't create threads ourselves since the pthread
+ * corresponding to this stack might be sleeping.
+ */
+ pthread_create (&coop_mother, NULL, mother, NULL);
+ }
+ else
+ {
+ pthread_cond_signal (&coop_cond_create);
+ }
+ /* We can't use a pthreads condition variable since "this"
+ * pthread could already be asleep. We can't use a COOP
+ * condition variable because they are not safe against
+ * pre-emptive switching.
+ */
+ while (coop_child || mother_awake_p)
+ usleep (0);
#else
t->sto = malloc (COOP_STKSIZE);
sto = COOP_STKALIGN (t->sto, QT_STKALIGN);
{
coop_t *oldthread = (coop_t *) old;
-#if 0
- /* Marking old->base NULL indicates that this thread is dead */
- oldthread->base = NULL;
-#endif
-
if (oldthread->specific)
free (oldthread->specific);
#ifndef GUILE_PTHREAD_COMPAT
{
coop_t *old, *newthread;
- /* Check if t is already finished */
- if (t->base == NULL)
- return;
-
/* Create a join list if necessary */
if (t->joining == NULL)
{
{
/* We're so cheap. */
scm_thread_sleep (usec / 1000000);
- struct timeval timeout;
return 0; /* Maybe we should calculate actual time slept,
but this is faster... :) */
}