+1997-11-27 Mikael Djurfeldt <mdj@mdj.nada.kth.se>
+
+ * Makefile.am: Added iselect.c and iselect.h.
+
+ * coop.c (coop_qinit): Initialize fields used by
+ scm_internal_select.
+ (coop_qget, coop_qget, coop_tmp_queue): Made global.
+ (coop_next_runnable_thread): If GUILE_ISELECT enabled, use
+ replacement in iselect.c.
+ (coop_mutex_lock, coop_condition_variable_wait, coop_abort,
+ coop_join): If GUILE_ISELECT enabled, use
+ coop_wait_for_runnable_thread instead of
+ coop_next_runnable_thread.
+ (usleep, sleep): New replacements for system functions if
+ GUILE_ISELECT is enabled.
+
+ * coop-threads.h: Declare coop_wait_for_runnable_thread.
+
+ * coop-defs.h (coop_t): Added fields used by scm_internal_select.
+
+ * filesys.c: Added #include "iselect.h". Moved FD-macros to
+ iselect.h. Implement Scheme level `select' using
+ scm_internal_select. (See NEWS.)
+
+ * genio.c (scm_getc): Block with scm_internal_select. (See NEWS.)
+
+ * init.c: Call scm_init_iselect.
+
+ * iselect.h, iselect.c: New files. Implements
+ scm_internal_select. (See NEWS.)
+
1997-11-27 Tim Pierce <twp@skepsis.com>
Fix a memory leak in scm_read_line and a type cast bug in the ptob.
* If you do not wish that, delete this exception notice. */
\f
-/* $Id: coop.c,v 1.2 1997-05-26 22:31:48 jimb Exp $ */
+/* $Id: coop.c,v 1.3 1997-11-27 18:04:53 mdj Exp $ */
/* Cooperative thread library, based on QuickThreads */
q->t.all_prev = NULL;
q->t.all_next = NULL;
+#ifdef GUILE_ISELECT
+ q->t.nfds = 0;
+ q->t.readfds = NULL;
+ q->t.writefds = NULL;
+ q->t.exceptfds = NULL;
+ q->t.timeoutp = 0;
+#endif
}
#ifdef __STDC__
-static coop_t *
+coop_t *
coop_qget (coop_q_t *q)
#else
-static coop_t *
+coop_t *
coop_qget (q)
coop_q_t *q;
#endif
#ifdef __STDC__
-static void
+void
coop_qput (coop_q_t *q, coop_t *t)
#else
-static void
+void
coop_qput (q, t)
coop_q_t *q;
coop_t *t;
\f/* Thread routines. */
-coop_q_t coop_global_runq; /* A queue of runable threads. */
-coop_q_t coop_global_sleepq; /* A queue of sleeping threads. */
-static coop_q_t tmp_queue; /* A temp working queue */
-coop_q_t coop_global_allq; /* A queue of all threads. */
-static coop_t coop_global_main; /* Thread for the process. */
-coop_t *coop_global_curr; /* Currently-executing thread. */
+coop_q_t coop_global_runq; /* A queue of runable threads. */
+coop_q_t coop_global_sleepq; /* A queue of sleeping threads. */
+coop_q_t coop_tmp_queue; /* A temp working queue */
+coop_q_t coop_global_allq; /* A queue of all threads. */
+static coop_t coop_global_main; /* Thread for the process. */
+coop_t *coop_global_curr; /* Currently-executing thread. */
static void *coop_starthelp (qt_t *old, void *ignore0, void *ignore1);
static void coop_only (void *pu, void *pt, qt_userf_t *f);
{
coop_qinit (&coop_global_runq);
coop_qinit (&coop_global_sleepq);
- coop_qinit (&tmp_queue);
+ coop_qinit (&coop_tmp_queue);
coop_qinit (&coop_global_allq);
coop_global_curr = &coop_global_main;
}
and there are sleeping threads - wait until one wakes up. Otherwise,
return NULL. */
+#ifdef GUILE_ISELECT
+extern coop_t *coop_next_runnable_thread ();
+#else
#ifdef __STDC__
coop_t *
coop_next_runnable_thread()
if (t->wakeup_time <= now)
coop_qput(&coop_global_runq, t);
else
- coop_qput(&tmp_queue, t);
+ coop_qput(&coop_tmp_queue, t);
}
- while ((t = coop_qget(&tmp_queue)) != NULL)
+ while ((t = coop_qget(&coop_tmp_queue)) != NULL)
coop_qput(&coop_global_sleepq, t);
t = coop_qget (&coop_global_runq);
return t;
}
-
+#endif
#ifdef __STDC__
void
/* Record the current top-of-stack before going to sleep */
coop_global_curr->top = &old;
+#ifdef GUILE_ISELECT
+ newthread = coop_wait_for_runnable_thread();
+#else
newthread = coop_next_runnable_thread();
+#endif
old = coop_global_curr;
coop_global_curr = newthread;
QT_BLOCK (coop_yieldhelp, old, &(m->waiting), newthread->sp);
{
coop_t *old, *newthread;
+#ifdef GUILE_ISELECT
+ newthread = coop_wait_for_runnable_thread();
+#else
newthread = coop_next_runnable_thread();
+#endif
old = coop_global_curr;
coop_global_curr = newthread;
QT_BLOCK (coop_yieldhelp, old, &(c->waiting), newthread->sp);
free(coop_global_curr->joining);
}
+#ifdef GUILE_ISELECT
+ newthread = coop_wait_for_runnable_thread();
+#else
newthread = coop_next_runnable_thread();
+#endif
coop_all_qremove(&coop_global_allq, coop_global_curr);
old = coop_global_curr;
coop_global_curr = newthread;
coop_qinit((coop_q_t *) t->joining);
}
+#ifdef GUILE_ISELECT
+ newthread = coop_wait_for_runnable_thread();
+#else
newthread = coop_next_runnable_thread();
+#endif
old = coop_global_curr;
coop_global_curr = newthread;
QT_BLOCK (coop_yieldhelp, old, (coop_q_t *) t->joining, newthread->sp);
for the process - but not for the system (it busy-waits) */
#ifdef __STDC__
-static void *
+void *
coop_sleephelp (qt_t *sp, void *old, void *blockq)
#else
-static void *
+void *
coop_sleephelp (sp, old, bolckq)
qt_t *sp;
void *old;
return NULL;
}
+#ifdef GUILE_ISELECT
+
+void
+usleep (unsigned usec)
+{
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = usec;
+ scm_internal_select (0, NULL, NULL, NULL, &timeout);
+}
+
+unsigned
+sleep (unsigned sec)
+{
+ time_t now = time (NULL);
+ struct timeval timeout;
+ int slept;
+ timeout.tv_sec = sec;
+ timeout.tv_usec = 0;
+ scm_internal_select (0, NULL, NULL, NULL, &timeout);
+ slept = time (NULL) - now;
+ return slept > sec ? 0 : sec - slept;
+}
+
+#else /* GUILE_ISELECT */
+
#ifdef __STDC__
unsigned
sleep (unsigned s)
#endif
{
coop_t *newthread, *old;
- time_t now = time(NULL);
+ time_t now = time (NULL);
coop_global_curr->wakeup_time = now + s;
/* Put the current thread on the sleep queue */
return s;
}
+
+#endif /* GUILE_ISELECT */
#include "smob.h"
#include "feature.h"
#include "fports.h"
+#include "iselect.h"
#include "filesys.h"
\f
#include <pwd.h>
-#ifdef FD_SET
-
-#define SELECT_TYPE fd_set
-#define SELECT_SET_SIZE FD_SETSIZE
-
-#else /* no FD_SET */
-
-/* Define the macros to access a single-int bitmap of descriptors. */
-#define SELECT_SET_SIZE 32
-#define SELECT_TYPE int
-#define FD_SET(n, p) (*(p) |= (1 << (n)))
-#define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
-#define FD_ISSET(n, p) (*(p) & (1 << (n)))
-#define FD_ZERO(p) (*(p) = 0)
-
-#endif /* no FD_SET */
-
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
}
SCM_DEFER_INTS;
+#ifdef GUILE_ISELECT
+ sreturn = scm_internal_select (SELECT_SET_SIZE,
+ &read_set, &write_set, &except_set, time_p);
+#else
sreturn = select (SELECT_SET_SIZE,
&read_set, &write_set, &except_set, time_p);
+#endif
if (sreturn < 0)
scm_syserror (s_select);
SCM_ALLOW_INTS;