home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / MAILBOX.ZIP / MPTHD.H < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-27  |  10.3 KB  |  234 lines

  1. /****************************************************************************/
  2. /* mpthd.h  -- THREAD CLUSTER (INTERFACE)                    */
  3. /* Created:  10/31/87        Release:  0.7        Version:  06/27/88  */
  4. /****************************************************************************
  5. (c) Copyright 1987 by Michael Benjamin Parker           (USA SS# 557-49-4130)
  6.  
  7. All Rights Reserved unless specified in the following include files: */
  8. #include "mptsk.cpy" /*
  9.  
  10. DO NOT REMOVE OR ALTER THIS NOTICE AND ITS PROVISIONS.
  11. ****************************************************************************/
  12. /* OVERVIEW:
  13.  
  14. The thread cluster implements basic context switching in the
  15. ``C'' environment for single or multiprocessor machines.  It provides
  16. primitives useful for implementing multitasking.
  17.  
  18. The cluster allows its user to create independent threads of execution
  19. (contexts), each with its own processor state, stack frame (local
  20. variables), and heap.  All threads share the same address space, however,
  21. and so can share global variables and the global heap for simple
  22. communication.
  23.  
  24. To help manage the somewhat complex notion of parallel processing, a
  25. thread is treated as an ordinary data object.  Though a thread is
  26. executed, it is created and destroyed, examined and modified, just like
  27. any other data object.
  28.  
  29. The number of bizzar flow control constructs has also been kept to a
  30. minimum.  Namely, the thread cluster has a single switch function which
  31. uquickly switches between contexts, and operates quite like an ordinary
  32. function call.
  33.  
  34. As well as being fast, the implementation is highly portable.  Its design
  35. is independent of the operating system, number of processors, memory
  36. management hardware and software, and C library routines (except setjmp and
  37. longjmp).  And the powerful interface can be used to quickly build
  38. a full multiprocessing/multitasking enviornment in ``C'' that runs on
  39. many machines.
  40.  
  41. SUPPORTS:
  42.     MS-DOS, in Turbo C 1.0+
  43.     UNIX BSD 4.3 on    IBM RT
  44. TO BE SUPPORTED:
  45.     MS-DOS in Microsoft C 5.0+
  46.     UNIX BSD 4.3 on    VAX (file mpvaxsj.s STILL HAS BUGS IN IT)
  47.     UNIX BSD 4.3 on SUN
  48.  
  49. NOTE:    for multiprocessor implementations, the design assumes a shared
  50. address space between processors.
  51.  
  52. WARNING: Must be compiled with all stack-overflow checking features
  53. turned off!
  54. *****************************************************************************/
  55. /****************************************************************************/
  56. #ifndef    MPTHD_H
  57. #define MPTHD_H
  58. #include "mpmisc.h"
  59. /****************************************************************************/
  60. #if (!((defined(unix) && (defined(vax) || defined(ibm032)||defined(ibm370))) \
  61.     || defined(__TURBOC__) || defined(M_I86)))
  62.     Error!  Currently, this code only runs:
  63.         in UNIX C (on the IBM RT or VAX)
  64.         in MS-DOS (in  Turbo C or Microsoft C)
  65. #endif
  66. /****************************************************************************/
  67. /****************************************************************************/
  68. /* DATA INTERFACE:                                */
  69. typedef    UINT    MPDEFID;
  70. typedef    struct _MPTHD    MPTHD, PTR MPTHDID;    /* THREAD (CONTEXT) STRUCT  */
  71. #ifdef    ANSI_C
  72. typedef    MPTHDID    (*MPTHDFN)(MPTHDID oldmpthd);    /* THREAD FUNCTION TYPE        */
  73. #else
  74. typedef    MPTHDID    (*MPTHDFN)();
  75. #endif
  76. /****************************************************************************/
  77. /****************************************************************************/
  78. /* CODE INTERFACE:                                */
  79. /****************************************************************************/
  80. MPTHDID    mpthd_switch    ARGS((MPTHDID newmpthd)); /*
  81.  
  82. Switches between thread contexts.  Specifically, switches from the
  83. caller's (current) context to the newmpthd context.  Returns the context
  84. (oldmpthd) which restored the calling thread's control.  An indivisable
  85. (atomic) operation.    */
  86. /****************************************************************************/
  87. /*MPTHDID    mpthd_me(void)        MPTHDID
  88.  
  89. Returns the unique id of the calling thread. */
  90. /****************************************************************************/
  91. MPTHDID    mpthd_init    ARGS((VOIDPTR buff, UINT size, MPTHDFN mpthdfn)); /*
  92.  
  93. Initializes a new thread structure in buff of size bytes, and returns the
  94. id of the new thread structure.  This structure stores the new thread of
  95. execution's context, including its processor state, stack, and possibly
  96. heap.
  97.  
  98. When the new thread is switched to, it will call tskfn with the id of the
  99. previous thread which first gave it control.  When the mpthdfn returns,
  100. the new thread will switch to the thread id mpthdfn returns.  When the
  101. switch returns, the new thread will call mpthdfn with the thread id
  102. switch returns...  And and this way the new thread loops infinitely,
  103. alternately calling mpthdfn and switch with each other's return values:
  104.  
  105.     for (EVER) {
  106.         oldmpthd=    mpthd_switch(mpthdfn(oldmpthd));
  107.     }
  108.  
  109. On the first call of mpthdfn, oldmpthd is the id of the first thread to
  110. switch to the new thread.  Also, on the first call of mpthdfn, the signal
  111. state (signals blocked/unblocked) is the same as the signal state when
  112. the new thread was initialized.
  113.  
  114. WARNING: To prevent unrealistically small stack/heap sizes, the size
  115. of buff should be at least 3 times the sizeof of the MPTHD structure. */
  116. /****************************************************************************/
  117. VOIDPTR        mpthd_dinit    ARGS((MPTHDID mpthd)); /*
  118.  
  119. Deinitializes the mpthd structure, returning a pointer to the buffer original
  120. buffer space so that it can be reclaimed.
  121.  
  122. WARNING:  You cannot denitialize a currently executing thread.  Thus, iff you
  123. try to deinitalize yourself (mpthd==mpthd_me()), nil will be returned.  And,
  124. iff you try to deinitalize a thread executing on any other processor, the
  125. operation will wait until the processor has switched to another thread. */
  126. /****************************************************************************/
  127. /* STRTYPE PTR    mpthd_heap(MPTHDID mpthd,STRTYPE);    */
  128. /* STRTYPE PTR    mpthd_myheap(STRTYPE);            */
  129.  
  130. /* Returns STRTYPE pointer to a thread's local heap space.
  131.  
  132. The heap is just a buffer opposite the stack in the heap/stack field of the
  133. thread structure.  The heap and stack share the leftover space in the
  134. thread structure after the processor state has been stored.
  135.  
  136. Although no heap management functions are provided, a thread could
  137. potentially use its heap to store its own set of dynamically allocated
  138. variables.  More importantly, the heap can be used to pass arguments
  139. between threads (global variables may also be used for this purpose).
  140. One thread could store and retrieve variables into another thread's heap
  141. (hopefully when it's not running), say, to pass arguments to a newly
  142. initialized thread, and read arguments from an executed thread before
  143. deinitalizing it.
  144.  
  145. WARNING:  Since there are no heap managment functions, there is no check
  146. for heap/stack collision, only stack/processor state collision (and, by that
  147. point, the heap would have been destroyed).
  148.  
  149. NOTE:    mpthd_myheap() is essentially mpthd_heap(mpthd_me())        */
  150. /****************************************************************************/
  151. /****************************************************************************/
  152. void    mpthd_setup    ARGS((void));
  153. /*
  154. ###
  155. MPTHDID    mpthd_setup    ARGS((VOIDPTR buf, UINT size));
  156. Sets up the calling processor to use the thread cluster.
  157.  
  158. Your program's *main* function should look something like this:
  159.  
  160. void    main() {
  161.     ...
  162.     MPTHD    mpthd_main[3];
  163.     ...
  164.     mpthd_setup(mpthd_main,3*sizeof(MPTHD));
  165.     ...
  166.     ...
  167. }
  168.  
  169. Returns the initialized thread, or NIL iff the initialization failed
  170. (see mpthd_init()).
  171.  
  172. WARNING:   mpthd_setup should be called before any other mpthd function!    */
  173. /****************************************************************************/
  174. void    _mpthd_setup    ARGS((MPTHDID mpthd));
  175. /*
  176. Used by internally mpthd_setup, but provided here for higher-level
  177. multitasking setup functions.  Makes an initialized thread the current
  178. running thread.  */
  179. /****************************************************************************/
  180. /****************************************************************************/
  181. /* STRUCTURE, EXTERNAL-VARIBLE, AND MACRO DEFINITION:                */
  182. /****************************************************************************/
  183. /****************************************************************************/
  184. #ifdef    vax
  185. #include "mpvaxsj.h"
  186. #define    setjmp(jmp)        mpvaxsj_setjmp(jmp)
  187. #define    longjmp(jmp,ret)    mpvaxsj_longjmp(jmp,ret)
  188. #define    jmp_buf            MPVAXSJ
  189. #else
  190. #include <setjmp.h>
  191. #endif
  192. #include "mpsem.h"
  193. #include "mpsig.h"
  194.  
  195. struct _MPTHD {
  196.     jmp_buf    state;        /* THE CURRENT STATE OF THE THREAD */
  197.     MPSIGSTATE mpsigstate;    /* THE SIGNAL STATE WHEN THREAD CREATED */
  198.     MPSEM    mpsem;        /* SEMAPHORE TO ALLOW ONLY ONE PROCESSOR */
  199.     MPTHDID    oldmpthd;       /* THE THREAD EXECUTING PRIOR TO THIS ONE */
  200.     MPTHDFN    mpthdfn;    /* THE FUNCTION THIS THREAD EXECUTES */
  201.     BOOL    stackoverflow;    /* STACK OVERFLOW DETECTOR VARIABLE */
  202.     MPDEFID mpdefsize;     /* SIZE OF MPDEF'AULTS (IN CHARS) */
  203.     char    mpdefs[1];     /* THE MPDEF'AULT STORAGE */
  204. /*        |
  205.         V
  206.  
  207.         ^
  208.         |
  209.         stack           THREAD'S STACK (ASSUME GROWS DOWN) */
  210. };
  211. /****************************************************************************/
  212. /****************************************************************************/
  213. extern    MPTHDID    mpthd_me_reg;
  214. /****************************************************************************/
  215. /****************************************************************************/
  216. #define    mpthd_me()    (mpthd_me_reg)
  217.  
  218. #define    mpdef_size(mpthd)        ((mpthd)->mpdefsize)
  219. #define    mpdef_mysize()            mpdef_size(mpthd_me())
  220. #define    mpdef_add(mpthd,TYPE)        \
  221.     mpdef_size(mpthd);        \
  222.     mpdef_size(mpthd)+=    (sizeof(TYPE))
  223. #define    mpdef_myadd(TYPE)        mpdef_add(mpthd_me(),TYPE)
  224. #define    mpdef_myval(mpdef,TYPE)        mpdef_val(mpthd_me(),mpdef,TYPE)
  225. #define    mpdef_val(mpthd,mpdef,TYPE)    (*mpdef_idval(mpthd,mpdef,TYPE *))
  226. #define    mpdef_myidval(mpdef,TYPEID)    mpdef_idval(mpthd_me(),mpdef,TYPEID)
  227. #define    mpdef_idval(mpthd,mpdef,TYPEID)    ((TYPEID)str2fld(mpthd,mpdefs[mpdef]))
  228. #define    mpdef_idval2mpthd(mpdef,id)    fld2str(MPTHDID,mpdefs[mpdef],id)
  229. /****************************************************************************/
  230. /****************************************************************************/
  231. /****************************************************************************/
  232. #endif    /* MPTHD_H */
  233.  
  234.