home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / f / ftp-102.zip / ftape-1.02 / driver / thread.c < prev    next >
C/C++ Source or Header  |  1992-10-12  |  5KB  |  199 lines

  1. /* Do very lightweight threads in interrupt routines.
  2.    Copyright (C) 1992 David L. Brown, Jr.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /*
  19.  * thread.c,v 1.4 1992/10/13 01:45:01 dbrown Exp
  20.  *
  21.  * thread.c,v
  22.  * Revision 1.4  1992/10/13  01:45:01  dbrown
  23.  * Added FSF copyright.
  24.  *
  25.  * Revision 1.3  1992/09/12  23:15:23  dbrown
  26.  * Renamed suspend to th_suspend.
  27.  *
  28.  * Revision 1.2  1992/09/07  16:44:01  dbrown
  29.  * Changed names of routines for Kernel use.
  30.  *
  31.  * Revision 1.1  1992/09/07  14:46:24  dbrown
  32.  * Added thread code.
  33.  *
  34.  */
  35.  
  36. #include "thread.h"
  37.  
  38. /* Register variable declarations. */
  39.  
  40. register long int bx asm ("bx");
  41. register long int si asm ("si");
  42. register long int di asm ("di");
  43. register long int bp asm ("bp");
  44. register long int sp asm ("sp");
  45.  
  46. #ifdef KERNEL
  47. # define abort th_error
  48.  
  49. /*volatile*/ void
  50. th_error ()
  51. {
  52.   panic ("th thread stack underflow.");
  53. }
  54. #endif
  55.  
  56. volatile void abort ();
  57.  
  58. /* Create a thread and return non-zero if successfully. */
  59. int
  60. th_create (thread *th,
  61.        int stack_size,
  62.        void *stack,
  63.        func *function,
  64.        void *arg)
  65. {
  66.   long **tsp;
  67.  
  68.   th->stack = (long *) stack;
  69.   if (th->stack == 0)
  70.     return 0;
  71.  
  72.   tsp = (long **) th->stack + (stack_size / sizeof (long *));
  73.  
  74.   /* Push argument. */
  75.   *--tsp = (long *) arg;
  76.  
  77.   /* Push abort in case the thread tries to return. */
  78.   *--tsp = (long *) abort;
  79.  
  80.   th->slave.sp = (long *) tsp;
  81.   th->slave.bp = 0;        /* Not relevant. */
  82.   th->slave.bx = 0;        /* These don't matter much. */
  83.   th->slave.si = 0;        /* Just clear them for cleanness. */
  84.   th->slave.di = 0;
  85.   th->slave.pc = (void *) function;
  86.  
  87.   return 1;
  88. }
  89.  
  90. /* Perform one thread operation until next suspend.  The argument is
  91.    given as the return value from suspend. */
  92. void *
  93. th_thunk (thread *th, void *arg)
  94. {
  95.   /* Save the general registers. */
  96.  
  97.   th->master.bx = bx;
  98.   th->master.si = si;
  99.   th->master.di = di;
  100.  
  101.   /* Save the return PC. */
  102.   th->master.pc = (void *) ((void **) &th)[-1];
  103.  
  104.   /* Save the caller's FP, not our own. */
  105.   th->master.bp = (void *) ((void **) &th)[-2];
  106.  
  107.   /* Save the caller's BP, not our own. */
  108.   th->master.sp = (void *) &th;
  109.  
  110.   {
  111.     register const __typeof (th[0]) *t asm ("cx");
  112.     register void *a asm ("ax");
  113.  
  114.     t = th;
  115.     a = arg;
  116.  
  117.     bx = (long int) t->slave.bx;
  118.     si = (long int) t->slave.si;
  119.     di = (long int) t->slave.di;
  120.     bp = (long int) t->slave.bp;
  121.     sp = (long int) t->slave.sp;
  122.  
  123.     asm volatile ("jmp %*%0" : : "g" (t->slave.pc), "a" (a));
  124.   }
  125. }
  126.  
  127. /* Suspend the thread.  The arg is returned to the call to thunk. */
  128. void *
  129. th_suspend (thread *th, void *arg)
  130. {
  131.   /* Save the general registers. */
  132.  
  133.   th->slave.bx = bx;
  134.   th->slave.si = si;
  135.   th->slave.di = di;
  136.  
  137.   /* Save the return PC. */
  138.   th->slave.pc = (void *) ((void **) &th)[-1];
  139.  
  140.   /* Save the caller's FP, not our own. */
  141.   th->slave.bp = (void *) ((void **) &th)[-2];
  142.  
  143.   /* Save the caller's BP, not our own. */
  144.   th->slave.sp = (void *) &th;
  145.  
  146.   {
  147.     register const __typeof (th[0]) *t asm ("cx");
  148.     register void *a asm ("ax");
  149.  
  150.     t = th;
  151.     a = arg;
  152.  
  153.     bx = (long int) t->master.bx;
  154.     si = (long int) t->master.si;
  155.     di = (long int) t->master.di;
  156.     bp = (long int) t->master.bp;
  157.     sp = (long int) t->master.sp;
  158.  
  159.     asm volatile ("jmp %*%0" : : "g" (t->master.pc), "a" (a));
  160.   }
  161. }
  162.  
  163. #ifdef TEST_THREADS
  164. /* Test all of this. */
  165.  
  166. thread grunt;
  167.  
  168. int
  169. sub_function (int value)
  170. {
  171.   int result;
  172.   printf ("sub called = %d\n", value);
  173.   result = (int) suspend (&grunt, (void *) 2);
  174.   printf ("foo sub_function: suspend returned %d\n", result);
  175.   return 98;
  176. }
  177.  
  178. void
  179. foo (void *arg)
  180. {
  181.   int result;
  182.   printf ("Foo called. arg = %d\n", (int) arg);
  183.   result = sub_function (99);
  184.   printf ("sub function returned %d\n", result);
  185.   suspend (&grunt, (void *) 4);
  186.   abort ();
  187. }
  188.  
  189. main ()
  190. {
  191.   int result;
  192.   create_thread (&grunt, 2048, foo, (void *) 1);
  193.   result = (int) thunk (&grunt, 0);
  194.   printf ("Thunk returned %d\n", result);
  195.   result = (int) thunk (&grunt, (void *) 3);
  196.   printf ("Thunk returned %d\n", result);
  197. }
  198. #endif /* TEST_THREADS */
  199.