* 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.
This commit is contained in:
parent
86c5044a29
commit
44e8413c73
8 changed files with 162 additions and 38 deletions
|
|
@ -1,3 +1,34 @@
|
|||
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.
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ EXTRA_libguile_la_SOURCES = _scm.h \
|
|||
backtrace.c stacks.c debug.c srcprop.c \
|
||||
strerror.c inet_aton.c putenv.c \
|
||||
threads.c alloca.c \
|
||||
regex-posix.c
|
||||
regex-posix.c iselect.c
|
||||
|
||||
## This is kind of nasty... there are ".c" files that we don't want to
|
||||
## compile, since they are #included in threads.c. So instead we list
|
||||
|
|
@ -62,7 +62,7 @@ modinclude_HEADERS = \
|
|||
simpos.h smob.h socket.h srcprop.h stackchk.h stacks.h stime.h \
|
||||
strings.h strop.h strorder.h strports.h struct.h symbols.h tag.h \
|
||||
tags.h throw.h unif.h variable.h vectors.h version.h vports.h \
|
||||
weaks.h snarf.h threads.h coop-defs.h fluids.h
|
||||
weaks.h snarf.h threads.h coop-defs.h fluids.h iselect.h
|
||||
|
||||
## This file is generated at configure time. That is why it is DATA
|
||||
## and not a header -- headers are included in the distribution.
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@
|
|||
# endif
|
||||
# endif
|
||||
|
||||
#ifdef GUILE_ISELECT
|
||||
#include "iselect.h"
|
||||
#endif
|
||||
|
||||
/* This file is included by threads.h, which, in turn, is included by
|
||||
libguile.h while coop-threads.h only is included by
|
||||
coop-threads.c. */
|
||||
|
|
@ -89,7 +93,18 @@ typedef struct coop_t {
|
|||
void *joining; /* A queue of threads waiting to join this
|
||||
thread */
|
||||
|
||||
#ifdef GUILE_ISELECT
|
||||
int nfds;
|
||||
SELECT_TYPE *readfds;
|
||||
SELECT_TYPE *writefds;
|
||||
SELECT_TYPE *exceptfds;
|
||||
int timeoutp;
|
||||
struct timeval wakeup_time; /* Time to stop sleeping */
|
||||
int errno;
|
||||
int retval;
|
||||
#else
|
||||
time_t wakeup_time; /* Time to stop sleeping */
|
||||
#endif
|
||||
|
||||
} coop_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -132,8 +132,19 @@ extern void coop_yield (void);
|
|||
|
||||
extern void coop_abort (void);
|
||||
|
||||
/* The following are needed in iselect.c */
|
||||
|
||||
extern coop_t *coop_qget (coop_q_t *);
|
||||
extern void coop_qput (coop_q_t *, coop_t *);
|
||||
extern void *coop_sleephelp (qt_t *, void *, void *);
|
||||
|
||||
#ifdef GUILE_ISELECT
|
||||
extern coop_t *coop_wait_for_runnable_thread ();
|
||||
#endif
|
||||
|
||||
extern coop_q_t coop_global_runq; /* A queue of runable threads. */
|
||||
extern coop_q_t coop_global_sleepq;
|
||||
extern coop_q_t coop_global_sleepq;
|
||||
extern coop_q_t coop_tmp_queue;
|
||||
extern coop_q_t coop_global_allq; /* A queue of all threads. */
|
||||
extern coop_t *coop_global_curr; /* Currently-executing thread. */
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
* If you do not wish that, delete this exception notice. */
|
||||
|
||||
|
||||
/* $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 */
|
||||
|
||||
|
|
@ -69,14 +69,21 @@ coop_qinit (q)
|
|||
|
||||
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
|
||||
|
|
@ -96,10 +103,10 @@ coop_qget (q)
|
|||
|
||||
|
||||
#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;
|
||||
|
|
@ -148,12 +155,12 @@ coop_all_qremove (q, t)
|
|||
|
||||
/* 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);
|
||||
|
|
@ -171,7 +178,7 @@ coop_init()
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -181,6 +188,9 @@ coop_init()
|
|||
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()
|
||||
|
|
@ -204,9 +214,9 @@ 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);
|
||||
|
|
@ -215,7 +225,7 @@ coop_next_runnable_thread()
|
|||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
|
|
@ -284,7 +294,11 @@ coop_mutex_lock ()
|
|||
/* 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);
|
||||
|
|
@ -344,7 +358,11 @@ coop_condition_variable_wait (c)
|
|||
{
|
||||
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);
|
||||
|
|
@ -436,7 +454,11 @@ coop_abort ()
|
|||
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;
|
||||
|
|
@ -490,7 +512,11 @@ coop_join()
|
|||
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);
|
||||
|
|
@ -541,10 +567,10 @@ coop_yieldhelp (sp, old, blockq)
|
|||
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;
|
||||
|
|
@ -557,6 +583,32 @@ coop_sleephelp (sp, old, bolckq)
|
|||
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)
|
||||
|
|
@ -567,7 +619,7 @@ sleep (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 */
|
||||
|
|
@ -586,3 +638,5 @@ sleep (s)
|
|||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif /* GUILE_ISELECT */
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "smob.h"
|
||||
#include "feature.h"
|
||||
#include "fports.h"
|
||||
#include "iselect.h"
|
||||
|
||||
#include "filesys.h"
|
||||
|
||||
|
|
@ -82,23 +83,6 @@
|
|||
#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)
|
||||
|
|
@ -987,8 +971,13 @@ scm_select (reads, writes, excepts, secs, usecs)
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@
|
|||
#include <stdio.h>
|
||||
#include "_scm.h"
|
||||
#include "chars.h"
|
||||
#ifdef GUILE_ISELECT
|
||||
#include "filesys.h"
|
||||
#endif
|
||||
|
||||
#include "genio.h"
|
||||
|
||||
|
|
@ -107,6 +110,21 @@ scm_getc (port)
|
|||
{
|
||||
f = SCM_STREAM (port);
|
||||
i = SCM_PTOBNUM (port);
|
||||
#ifdef GUILE_ISELECT
|
||||
if (SCM_FPORTP (port) && !scm_input_waiting_p ((FILE *) f, "scm_getc"))
|
||||
{
|
||||
int n;
|
||||
SELECT_TYPE readfds;
|
||||
int fd = fileno ((FILE *) f);
|
||||
FD_ZERO (&readfds);
|
||||
do
|
||||
{
|
||||
FD_SET (fd, &readfds);
|
||||
n = scm_internal_select (fd + 1, &readfds, NULL, NULL, NULL);
|
||||
}
|
||||
while (n == -1 && errno == EINTR);
|
||||
}
|
||||
#endif
|
||||
SCM_SYSCALL (c = (scm_ptobs[i].fgetc) (f));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@
|
|||
#include "gsubr.h"
|
||||
#include "hash.h"
|
||||
#include "hashtab.h"
|
||||
#ifdef GUILE_ISELECT
|
||||
#include "iselect.h"
|
||||
#endif
|
||||
#include "ioext.h"
|
||||
#include "kw.h"
|
||||
#include "list.h"
|
||||
|
|
@ -405,6 +408,9 @@ scm_boot_guile_1 (base, closure)
|
|||
scm_init_gdbint ();
|
||||
scm_init_hash ();
|
||||
scm_init_hashtab ();
|
||||
#ifdef GUILE_ISELECT
|
||||
scm_init_iselect ();
|
||||
#endif
|
||||
scm_init_ioext ();
|
||||
scm_init_kw ();
|
||||
scm_init_list ();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue