Rewrite Win32 (as opposed to Win32s) DLL to use auxiliary thread and
authorChris Hanson <org/chris-hanson/cph>
Wed, 2 Apr 1997 07:44:09 +0000 (07:44 +0000)
committerChris Hanson <org/chris-hanson/cph>
Wed, 2 Apr 1997 07:44:09 +0000 (07:44 +0000)
Sleep() API call to generate async timer interrupts.  Use a critical
section to synchronize the two threads' access to the interrupt
registers.  These changes should eliminate the "spurious interrupt"
error messages that have been showing up from time to time.

v7/src/microcode/intrpt.h
v7/src/microcode/ntscmlib.h
v7/src/microcode/ntsig.c
v7/src/microcode/nttop.c
v7/src/microcode/ntutl/scheme31.c
v7/src/microcode/ntutl/scheme32.c

index 0b7b14b2e5d2db973b98022f85642313d32c5555..e211c8a5d75656b58a61801746b8f67ed4ed1e5b 100644 (file)
@@ -1,8 +1,8 @@
 /* -*-C-*-
 
-$Id: intrpt.h,v 1.18 1994/11/14 05:04:05 cph Exp $
+$Id: intrpt.h,v 1.19 1997/04/02 07:43:58 cph Exp $
 
-Copyright (c) 1987-94 Massachusetts Institute of Technology
+Copyright (c) 1987-97 Massachusetts Institute of Technology
 
 This material was developed by the Scheme project at the Massachusetts
 Institute of Technology, Department of Electrical Engineering and
@@ -135,7 +135,7 @@ MIT in each case. */
   RELEASE_INTERRUPT_REGISTERS ();                                      \
 }
 
-#if defined(_OS2)
+#if defined(_OS2) || defined(WINNT)
 
 #define GRAB_INTERRUPT_REGISTERS() OS_grab_interrupt_registers ()
 #define RELEASE_INTERRUPT_REGISTERS() OS_release_interrupt_registers ()
@@ -143,9 +143,9 @@ MIT in each case. */
 extern void OS_grab_interrupt_registers (void);
 extern void OS_release_interrupt_registers (void);
 
-#else /* not _OS2 */
+#else /* not (_OS2 or WINNT) */
 
 #define GRAB_INTERRUPT_REGISTERS()
 #define RELEASE_INTERRUPT_REGISTERS()
 
-#endif /* _OS2 */
+#endif /* not (_OS2 or WINNT) */
index 6e741e5d967642c28ba9d420c43c92c4a9c6778e..e3c1c49d3534957cce10882c45b1404f3bc2f713 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: ntscmlib.h,v 1.7 1997/01/01 22:57:29 cph Exp $
+$Id: ntscmlib.h,v 1.8 1997/04/02 07:44:04 cph Exp $
 
 Copyright (c) 1993-97 Massachusetts Institute of Technology
 
@@ -71,16 +71,20 @@ typedef struct {
                                   unsigned long);      /* size */
 
   UINT
-    (__cdecl *install_async_timer) (void **,           /* timer state */
-                                   unsigned long *,    /* regs */
-                                   long,               /* memtop_off */
-                                   long,               /* int_code_off */
-                                   long,               /* int_mask_off */
-                                   unsigned long,      /* mask */
-                                   long,               /* ctr_off */
-                                   unsigned long,      /* catatonia_message */
-                                   unsigned long,      /* interrupt_message */
-                                   HWND);              /* window */
+    (__cdecl *install_async_timer)
+      (void **,                        /* timer state */
+       unsigned long *,                /* regs */
+       long,                   /* memtop_off */
+       long,                   /* int_code_off */
+       long,                   /* int_mask_off */
+       unsigned long,          /* mask */
+       long,                   /* ctr_off */
+       unsigned long,          /* catatonia_message */
+       unsigned long,          /* interrupt_message */
+       HWND,                   /* window */
+       void (*) (void),                /* procedure to grab int regs */
+       void (*) (void)         /* procedure to release int regs */
+       );
 
   void
     (__cdecl *flush_async_timer) (void *);
index 80e51ef1cc80238d7fd4079795c513ae9c165abe..31d36e3b03c87d6a64bb435b3b6d6115d6a36fc0 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: ntsig.c,v 1.19 1997/01/01 22:57:30 cph Exp $
+$Id: ntsig.c,v 1.20 1997/04/02 07:43:44 cph Exp $
 
 Copyright (c) 1992-97 Massachusetts Institute of Technology
 
@@ -438,7 +438,9 @@ DEFUN_VOID (install_timer)
           catatonia_offset,
           WM_CATATONIC,
           WM_SCHEME_INTERRUPT,
-          master_tty_window))
+          master_tty_window,
+          OS_grab_interrupt_registers,
+          OS_release_interrupt_registers))
   {
     case WIN32_ASYNC_TIMER_OK:
       return (NULL);
index a8ea3e02672b33f529d1db97767098b1992053b4..a7f22cb4e2f61d042069787afb2dfc00fc1b6251 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: nttop.c,v 1.19 1997/01/01 22:57:32 cph Exp $
+$Id: nttop.c,v 1.20 1997/04/02 07:43:51 cph Exp $
 
 Copyright (c) 1993-97 Massachusetts Institute of Technology
 
@@ -64,6 +64,7 @@ extern CONST char * OS_Variant;
 
 static const char * w32_error_message (DWORD);
 static int syserr_to_unix_error_code (enum syserr_names);
+static void initialize_locks (void);
 static DWORD syserr_to_win32_error_code (enum syserr_names);
 static enum syserr_names win32_error_code_to_syserr (DWORD);
 \f
@@ -120,6 +121,7 @@ DEFUN_VOID (OS_initialize)
 {
   interactive = 1;
 
+  initialize_locks ();
   NT_gui_init ();
   NT_initialize_channels ();
   NT_initialize_tty ();
@@ -387,6 +389,26 @@ OS_syserr_names (unsigned int * length, unsigned char *** names)
   (*names) = ((unsigned char **) syserr_names_table);
 }
 \f
+static CRITICAL_SECTION interrupt_registers_lock;
+
+static void
+initialize_locks (void)
+{
+  InitializeCriticalSection (&interrupt_registers_lock);
+}
+
+void
+OS_grab_interrupt_registers (void)
+{
+  EnterCriticalSection (&interrupt_registers_lock);
+}
+
+void
+OS_release_interrupt_registers (void)
+{
+  LeaveCriticalSection (&interrupt_registers_lock);
+}
+\f
 /* Machine-generated procedure, do not edit: */
 static DWORD
 syserr_to_win32_error_code (enum syserr_names syserr)
index d067ad7ee0cca3386bbe5c17c2e47e998ca90b22..22dc7736f9beea6d90ee3d1b4cda0602616290e3 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: scheme31.c,v 1.8 1997/01/01 22:58:17 cph Exp $
+$Id: scheme31.c,v 1.9 1997/04/02 07:43:33 cph Exp $
 
 Copyright (c) 1993-97 Massachusetts Institute of Technology
 
@@ -193,7 +193,9 @@ win32_install_async_timer (void ** state_ptr,
                           long ctr_off,
                           unsigned long ctr_message,
                           unsigned long interrupt_message,
-                          HWND window)
+                          HWND window,
+                          void (*grab_int_regs) (void),
+                          void (*release_int_regs) (void))
 {
   struct ntw32lib_itimer_s param;
   LPVOID translation[2];
index 8490ffacc701aa889e4dbbdee1523ce56cb451b8..5bb87f7e2ee10f24916cb69ee26581011a17b8db 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: scheme32.c,v 1.13 1997/01/02 07:07:19 cph Exp $
+$Id: scheme32.c,v 1.14 1997/04/02 07:44:09 cph Exp $
 
 Copyright (c) 1993-97 Massachusetts Institute of Technology
 
@@ -38,9 +38,14 @@ MIT in each case. */
 
 #include "ntscmlib.h"
 #include <stdlib.h>
-#include <mmsystem.h>
+#include <process.h>
 
 static void __cdecl win32_flush_async_timer (void *);
+static unsigned int WINAPI timer_thread_proc (void *);
+
+#ifndef WIN32_TIMER_INTERVAL
+#define WIN32_TIMER_INTERVAL 50
+#endif
 \f
 static BOOL __cdecl
 win32_under_win32s_p (void)
@@ -105,34 +110,83 @@ win32_unlock_memory_area (void * area, unsigned long size)
   (void) VirtualUnlock (area, size);
 }
 \f
-/*   Asynchronous timer interrupt based on multimedia system
- *
- *   WARNING: the docs say that timer_tick and all that it references must
- *   be in a DLL witha a FIXED attribute.
- *   Also, it appears to need _stdcall, but mmsystem.h refutes this
- */
+/* Asynchronous timer interrupt based on auxiliary thread.  */
 
 struct win32_timer_closure_s
 {
-  UINT timer_id;
-  unsigned long * base;
-  long memtop_off;
-  long int_code_off;
-  long int_mask_off;
-  unsigned long bit_mask;
-  long ctr_off;
-  unsigned long catatonia_message;
-  unsigned long interrupt_message;
-  HWND window;
+  unsigned long interval;      /* timer interval in milliseconds */
+  unsigned long * base;                /* register-block base address */
+  long memtop_off;             /* offset to memtop register */
+  long int_code_off;           /* offset to int_code register */
+  long int_mask_off;           /* offset to int_mask register */
+  unsigned long bit_mask;      /* interrupt bits to signal */
+  long ctr_off;                        /* offset to catatonia-counter register */
+  unsigned long catatonia_message; /* message to send for catatonia */
+  unsigned long interrupt_message; /* message to send for interrupt */
+  HWND window;                 /* window to send the messages to */
+  void (*grab_int_regs) (void);        /* grab interrupt registers */
+  void (*release_int_regs) (void); /* release interrupt registers */
 };
 
-#ifdef CL386
-#define __STDCALL _stdcall
-#endif
+/* Setting this to non-zero requests the timer thread to exit.  */
+static int exit_timer_thread;
 
-#ifdef __WATCOMC__
-#define __STDCALL __stdcall
-#endif
+static UINT __cdecl
+win32_install_async_timer (void ** state_ptr,
+                          unsigned long * base,
+                          long memtop_off,
+                          long int_code_off,
+                          long int_mask_off,
+                          unsigned long bit_mask,
+                          long ctr_off,
+                          unsigned long catatonia_message,
+                          unsigned long interrupt_message,
+                          HWND window,
+                          void (*grab_int_regs) (void),
+                          void (*release_int_regs) (void))
+{
+  struct win32_timer_closure_s * scm_timer;
+  unsigned int id;
+
+  scm_timer
+    = ((struct win32_timer_closure_s *)
+       (malloc (sizeof (struct win32_timer_closure_s))));
+  if (scm_timer == 0)
+    return (WIN32_ASYNC_TIMER_NOMEM);
+  (scm_timer -> interval) = WIN32_TIMER_INTERVAL;
+  (scm_timer -> base) = base;
+  (scm_timer -> memtop_off) = memtop_off;
+  (scm_timer -> int_code_off) = int_code_off;
+  (scm_timer -> int_mask_off) = int_mask_off;
+  (scm_timer -> bit_mask) = bit_mask;
+  (scm_timer -> ctr_off) = ctr_off;
+  (scm_timer -> catatonia_message) = catatonia_message;
+  (scm_timer -> interrupt_message) = interrupt_message;
+  (scm_timer -> window) = window;
+  (scm_timer -> grab_int_regs) = grab_int_regs;
+  (scm_timer -> release_int_regs) = release_int_regs;
+  exit_timer_thread = 0;
+  if (_beginthreadex (0, 0, timer_thread_proc, scm_timer, 0, (&id)))
+    {
+      (*state_ptr) = scm_timer;
+      return (WIN32_ASYNC_TIMER_OK);
+    }
+  else
+    {
+      win32_flush_async_timer (scm_timer);
+      return (WIN32_ASYNC_TIMER_EXHAUSTED);
+    }
+}
+
+static void __cdecl
+win32_flush_async_timer (void * state)
+{
+  if (state != 0)
+    {
+      exit_timer_thread = 1;
+      (void) free (state);
+    }
+}
 
 #define INTERRUPT_CODE(scm_timer)                                      \
   ((scm_timer -> base) [scm_timer -> int_code_off])
@@ -152,124 +206,44 @@ struct win32_timer_closure_s
 #define CATATONIA_FLAG(scm_timer)                                      \
   ((scm_timer -> base) [(scm_timer -> ctr_off) + 2])
 
-static void __STDCALL
-win32_nt_timer_tick (UINT wID, UINT wMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
+static unsigned int WINAPI
+timer_thread_proc (void * envptr)
 {
-  struct win32_timer_closure_s * scm_timer
-    = ((struct win32_timer_closure_s *) dwUser);
-  (INTERRUPT_CODE (scm_timer)) |= (scm_timer -> bit_mask);
-  if (((INTERRUPT_CODE (scm_timer)) & (INTERRUPT_MASK (scm_timer))) != 0L)
-    {
-      (MEMTOP (scm_timer)) = ((unsigned long) -1L);
-      /* Post an interrupt message to the window.  This forces it to
-        wake up and exit MsgWaitForMultipleObjects if needed.  */
-      PostMessage ((scm_timer -> window),
-                  (scm_timer -> interrupt_message),
-                  ((WPARAM) 0),
-                  ((LPARAM) 0));
-    }
-  (CATATONIA_COUNTER (scm_timer)) += 1L;
-  if (((CATATONIA_COUNTER (scm_timer)) > (CATATONIA_LIMIT (scm_timer)))
-      && ((CATATONIA_LIMIT (scm_timer)) != 0L))
+  struct win32_timer_closure_s * scm_timer = envptr;
+  while (!exit_timer_thread)
     {
-      if ((CATATONIA_FLAG (scm_timer)) == 0L)
+      Sleep (scm_timer -> interval);
+      (* (scm_timer -> grab_int_regs)) ();
+      (INTERRUPT_CODE (scm_timer)) |= (scm_timer -> bit_mask);
+      if (((INTERRUPT_CODE (scm_timer)) & (INTERRUPT_MASK (scm_timer))) != 0L)
        {
-         (CATATONIA_FLAG (scm_timer)) = 1L;
+         (MEMTOP (scm_timer)) = ((unsigned long) -1L);
+         /* Post an interrupt message to the window.  This forces it to
+            wake up and exit MsgWaitForMultipleObjects if needed.  */
+         (* (scm_timer -> release_int_regs)) ();
          PostMessage ((scm_timer -> window),
-                      (scm_timer -> catatonia_message),
+                      (scm_timer -> interrupt_message),
                       ((WPARAM) 0),
                       ((LPARAM) 0));
        }
-      (CATATONIA_COUNTER (scm_timer)) = 0L;
+      else
+       (* (scm_timer -> release_int_regs)) ();
+      (CATATONIA_COUNTER (scm_timer)) += 1L;
+      if (((CATATONIA_COUNTER (scm_timer)) > (CATATONIA_LIMIT (scm_timer)))
+         && ((CATATONIA_LIMIT (scm_timer)) != 0L))
+       {
+         if ((CATATONIA_FLAG (scm_timer)) == 0L)
+           {
+             (CATATONIA_FLAG (scm_timer)) = 1L;
+             PostMessage ((scm_timer -> window),
+                          (scm_timer -> catatonia_message),
+                          ((WPARAM) 0),
+                          ((LPARAM) 0));
+           }
+         (CATATONIA_COUNTER (scm_timer)) = 0L;
+       }
     }
-}
-\f
-static UINT __cdecl
-win32_install_async_timer (void ** state_ptr,
-                          unsigned long * base,
-                          long memtop_off,
-                          long int_code_off,
-                          long int_mask_off,
-                          unsigned long bit_mask,
-                          long ctr_off,
-                          unsigned long catatonia_message,
-                          unsigned long interrupt_message,
-                          HWND window)
-{
-  TIMECAPS tc;
-  UINT wTimerRes;
-  UINT msInterval = 50;
-  UINT msTargetResolution = 50;
-  struct win32_timer_closure_s * scm_timer;
-
-  if ((timeGetDevCaps (&tc, sizeof (TIMECAPS))) != TIMERR_NOERROR)
-    return (WIN32_ASYNC_TIMER_NONE);
-  wTimerRes = (min ((max (tc.wPeriodMin, msTargetResolution)),
-                   tc.wPeriodMax));
-  if ((timeBeginPeriod (wTimerRes)) == TIMERR_NOCANDO)
-    return (WIN32_ASYNC_TIMER_RESOLUTION);
-
-  scm_timer = ((struct win32_timer_closure_s *)
-              (malloc (sizeof (struct win32_timer_closure_s))));
-
-  if (scm_timer == ((struct win32_timer_closure_s *) NULL))
-    return (WIN32_ASYNC_TIMER_NOMEM);
-
-  scm_timer->timer_id = 0;
-  scm_timer->base = base;
-  scm_timer->memtop_off = memtop_off;
-  scm_timer->int_code_off = int_code_off;
-  scm_timer->int_mask_off = int_mask_off;
-  scm_timer->bit_mask = bit_mask;
-  scm_timer->ctr_off = ctr_off;
-  scm_timer->catatonia_message = catatonia_message;
-  scm_timer->interrupt_message = interrupt_message;
-  scm_timer->window = window;
-
-  if ((! (VirtualLock (((void *) scm_timer),
-                      (sizeof (struct win32_timer_closure_s)))))
-      || (! (VirtualLock (((void *) win32_nt_timer_tick),
-                         (((char *) win32_flush_async_timer)
-                          - ((char *) win32_nt_timer_tick))))))
-  {
-    win32_flush_async_timer ((void *) scm_timer);
-    return (WIN32_ASYNC_TIMER_NOLOCK);
-  }
-
-  scm_timer->timer_id
-    = (timeSetEvent (msInterval,
-                    wTimerRes,
-                    ((LPTIMECALLBACK) win32_nt_timer_tick),
-                    ((DWORD) scm_timer),
-                    TIME_PERIODIC));
-
-  if (scm_timer->timer_id == 0)
-  {
-    win32_flush_async_timer ((void *) scm_timer);
-    return (WIN32_ASYNC_TIMER_EXHAUSTED);
-  }
-
-  * state_ptr = ((void *) scm_timer);
-  return (WIN32_ASYNC_TIMER_OK);
-}
-
-static void __cdecl
-win32_flush_async_timer (void * state)
-{
-  struct win32_timer_closure_s * scm_timer
-    = ((struct win32_timer_closure_s *) state);
-  
-  if (scm_timer == ((struct win32_timer_closure_s *) NULL))
-    return;
-  if (scm_timer->timer_id != 0)
-    (void) timeKillEvent (scm_timer->timer_id);
-  
-  (void) VirtualUnlock (((void *) win32_nt_timer_tick),
-                       (((char *) win32_flush_async_timer)
-                        - ((char *) win32_nt_timer_tick)));
-  (void) VirtualUnlock (scm_timer, (sizeof (struct win32_timer_closure_s)));
-  (void) free ((char *) scm_timer);
-  return;
+  return (0);
 }
 \f
 /* These are NOPs in this version. */