* Makefile.am: Added iselect.c and iselect.h.
authorMikael Djurfeldt <djurfeldt@nada.kth.se>
Thu, 27 Nov 1997 18:04:56 +0000 (18:04 +0000)
committerMikael Djurfeldt <djurfeldt@nada.kth.se>
Thu, 27 Nov 1997 18:04:56 +0000 (18:04 +0000)
* 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.

libguile/ChangeLog
libguile/Makefile.am
libguile/coop-defs.h
libguile/coop-threads.h
libguile/coop.c
libguile/filesys.c
libguile/genio.c
libguile/init.c

index d0e89cb..4798afd 100644 (file)
@@ -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.
index 4e0231c..a482789 100644 (file)
@@ -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.
index 79c48b5..d39894f 100644 (file)
 #  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;
 
index f671608..b57dbbf 100644 (file)
@@ -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. */
 
index a03ba08..81f0e3d 100644 (file)
@@ -40,7 +40,7 @@
  * 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 */
 
@@ -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)
 
 \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);
@@ -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 */
index 25e28ce..4bcc7e4 100644 (file)
@@ -45,6 +45,7 @@
 #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)
@@ -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;
index 328b9ed..1c24573 100644 (file)
@@ -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));
     }
 
index 54aec9e..06594b1 100644 (file)
@@ -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 ();