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

  1. /****************************************************************************/
  2. /* mpres.c  -- MAIL BOX MULTITASKING CLUSTER        (IMPLEMENTATION)    */
  3. /* Created:  06/26/88        Release:  0.7        Version: 06/27/88   */
  4. /****************************************************************************
  5. (c) Copyright 1987, 1988 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:    See mpres.h                            */
  13.  
  14. WARNING WARNING:    This code has not been debugged.  It is
  15. presented only for educational purposes and will likely not work.  It
  16. will be completed by release 1.0.
  17.  
  18.  
  19. NOTES ON CONSTRUCTING HANDLERS FOR HARDWARE INTERRUPTS:
  20.  
  21. Hardware interrupts (interrupts on a processor not explicitly invoked
  22. by the processor) must be handled very carefully.  The purpose of the
  23. hardware interrupt handler is to merely *indicate* to the scheduler
  24. that an interrupt has occured.  By comparing the current task's
  25. priority with that of the task waiting for the interrupt, the
  26. scheduler may then decide whether to process the interrupt now or
  27. hold off until some time later.  The handler should NOT process the
  28. interrupt, as this may require system resources and CPU time.  It
  29. should only indicate that the interrupt has occured.
  30.  
  31. Here are some rules for constructing safe hardware interrupt handlers:
  32.  
  33.     The handler must not access any system (global) resources,
  34. including dynamic heap memory allocation/deallocation.
  35.  
  36.     The handler may allocate a small amount of temporary stack memory
  37. for handling the current interrupt.
  38.  
  39.     The handler may also access shared static memory, however,
  40. accesses to this memory must be autonomous.  Whenever this memory is
  41. accessed, the accessing processor must block all interrupts which
  42. may access the memory, then, by claiming a semaphore on the memory, attempt
  43. to block all processors which may access that memory; if the claim fails,
  44. interrupts should be restored to their prior state before trying
  45. again.  Because autonomous accesses are exclusive, they must be very fast.
  46.  
  47.     The handler must execute VERY quickly (in negligable time).
  48.  
  49.     In general, it is probably simplest and safest to disable all
  50. interrupts within a hardware interrupt handler.
  51.  
  52.  
  53. /****************************************************************************/
  54. /****************************************************************************/
  55. #include "mpmisc.h"
  56. #include "mpres.h"
  57. #include "mptsk.h"
  58. #include <errno.h>
  59. #ifdef    __MSDOS__
  60. #include "mpdos.h"
  61. #endif
  62. #ifdef    unix
  63. #include <signal.h>
  64. #include <fcntl.h>
  65. #include <sys/ioctl.h>
  66. #endif
  67. /****************************************************************************/
  68. /****************************************************************************/
  69. /****************************************************************************/
  70. typedef    MPBOX    MPRES,    MPRES,    PTR MPRESID;
  71. typedef    struct _MPSOR    MPSOR,    PTR MPSORID;
  72.  
  73. struct _MPSOR {
  74.     MPMSG    mpmsg;    /* MESSAGE HEADER */
  75.     MPTSKID    mptsk;    /* TASK WHICH OWNS THE RESOURCE */
  76.     MPRESID    mpres;    /* RESOURCE OF WHICH THIS IS A SOURCE */
  77.  
  78. }
  79. /****************************************************************************/
  80. /****************************************************************************/
  81.  
  82. MPRES    mpres_stdin[1],mpres_stdout[1],mpres_stderr[1];
  83. MPRES    mpres_filesystem[1],mpres_network[1],mpres_terminalin[1],mpres_terminalout[1];
  84. MPRES    mpres_harddisk[1],mpres_floppydisk[1],mpres_modem[1],mpres_printer[1],
  85.     mpres_parallel[1],mpres_serial[1];
  86. /****************************************************************************/
  87. /****************************************************************************/
  88. /****************************************************************************/
  89. /* mpres / mpbox FUNCTION CALLS                    */
  90. #define    mpres_init    mpbox_init
  91. #define    mpscd_init    mpbox_init
  92. #define    mpres_dinit    mpbox_dinit
  93. #define    mpscd_dinit    mpbox_dinit
  94. #define    mpres_create    mpbox_create
  95. #define    mpscd_create    mpbox_create
  96. #define    mpres_destroy    mpbox_destroy
  97. #define    mpscd_destroy    mpbox_destroy
  98. /****************************************************************************/
  99. MPBOXID    mpbox_create(void)
  100. {
  101.     MPBOXID    mpbox;
  102.     mpres_ram(mpbox= (MPBOXID)malloc(sizeof(MPBOX)));
  103.     if (mpbox)    mpbox_init(mpbox);
  104.     return(mpbox);
  105. }
  106. /****************************************************************************/
  107. void    mpbox_destroy(MPBOXID mpbox)
  108. {
  109.     mpbox_dinit(mpbox);
  110.     mpres_ram(free(mpbox));
  111. }
  112. /****************************************************************************/
  113. /****************************************************************************/
  114. /* mpsor FUNCTION CALLS                                */
  115. MPSORID    mpsor_init(VOIDPTR buf,MPRESID mpres)
  116. {
  117.     MPSORID    mpsor=    (MPSORID)buf;
  118.     mprng_init(str2fld(mpsor,mpmsg));
  119.     mpsor->mptsk=    0;
  120.     mpsor->mpres=    mpres;
  121.     return(mpsor);
  122. }
  123. MPSORID    mpsor_create(MPRESID mpres)
  124. {
  125.     MPSORID    mpsor;
  126.     mpres_ram(mpsor= (MPSORID)malloc(sizeof(MPSOR)));
  127.     if (mpsor)    mpsor_init(mpsor,mpres);
  128.     return(mpsor);
  129. }
  130. /****************************************************************************/
  131. VOIDPTR    mpsor_dinit(MPSORID mpsor)
  132. {
  133.     mprng_dinit(str2fld(mpsor,mpmsg);
  134.     return((VOIDPTR)mpsor);
  135. }
  136. /****************************************************************************/
  137. void    mpsor_destroy(MPSORID mpsor)
  138. {
  139.     mpsor_dinit(mpsor);
  140.     mpres_ram(free(mpsor));
  141. }
  142. /****************************************************************************/
  143. /****************************************************************************/
  144. /* mpres/mpsor COMBINATION FUNCTION CALLS                    */
  145. /****************************************************************************/
  146. MPSORID    mpres_mpsor(MPRESID mpres,MPTSKID mptsk)
  147. {
  148.     MPSORID    mpsor=    mptsk_owns(mptsk);
  149.     while ((mpsor=    mprng_next(mpsor)) != mptsk_owns(mptsk))
  150.         if (mpsor->mpres == mpres)    return(mpsor);
  151.     return(0);
  152. }
  153. #define    mpres_mympsor(mpres)    mpres_mpsor(mpres,mptsk_me())
  154. /****************************************************************************/
  155. #define    mpres_takenew(mpres)    mptsk_recv(mpres)
  156. #define    mpres_giveold(mpsor)    mptsk_send((mpsor)->mpres,mpsor)
  157. /****************************************************************************/
  158. /****************************************************************************/
  159. void    mpres_take(mpres)
  160. {
  161.     MPSORID    mpsor=    mpres_mympsor(mpres);
  162.     if (!mpsor) {
  163.         mpsor=    mpres_takenew(mpres);
  164.         mprng_twistnn(mpsor,mptsk_myowns());
  165.     }
  166. }
  167. /****************************************************************************/
  168. void    mpres_give(mpres)
  169. {
  170.     MPSORID    mpsor=    mpres_mympsor(mpres);
  171.     if (mpsor) {
  172.         mprng_sub(mpsor);
  173.         mpres_giveold(mpsor);
  174.     }
  175. }
  176.  
  177. /****************************************************************************/
  178. /****************************************************************************/
  179. #define    mpres_critsect(mpres,CODEBLOCK)                    \
  180. {                                    \
  181.     mpres_take(mpres);                        \
  182.     {CODEBLOCK};                            \
  183.      mpres_give(mpres);                        \
  184. }
  185. /****************************************************************************/
  186. /****************************************************************************/
  187.  
  188.  
  189.  
  190. /****************************************************************************/
  191. /* RAM CONTENTION MANAGEMENT                            */
  192. MPRES    _mpres_ram[1];
  193. MPSOR    _mpsor_ram[1];
  194. #define    mpres_ram(RAMCALLS)    mpres_critsect(_mpres_ram,RAMCALLS)
  195. /****************************************************************************/
  196. /* errno CONTENTION MANAGEMENT                            */
  197. MPRES    _mpres_errno[1];
  198. MPSOR    _mpsor_errno[1];
  199. #define    mpres_errno(IOCALLS)    mpres_critsect(_mpres_errno,IOCALLS)
  200. /****************************************************************************/
  201. /****************************************************************************/
  202. /****************************************************************************/
  203. /* PRE-EMPTIVE MULTIPROCESSING                            */
  204. /****************************************************************************/
  205. #define    MPSIG_CLOCKTICK    (0x08)
  206. void    (* _mpsig_oldclocktick)();
  207. void    _mpsig_clocktick()
  208. {
  209. #ifdef    __MSDOS__
  210.     _mpsig_oldclocktick();
  211. #endif
  212. #ifdef    unix
  213.     alarm(1);    /* CALL ME AGAIN IN 1 SECOND */
  214. #endif
  215.     mptsk_yield();
  216. }
  217. /****************************************************************************/
  218. MPTHDID    _mpthdfn_idletask(MPTHDID mpthd)
  219. {
  220.     for(ever)    mptsk_yield();
  221. }
  222. /****************************************************************************/
  223. MPTHDID    mpthdfn_death(MPTHDID mpthd)
  224. {
  225.     for(ever)
  226.         mpthd_destroy(mptsk_destroy(mptsk_recv(mptsk_mympbox())));
  227. }
  228. /****************************************************************************/
  229. /****************************************************************************/
  230. /****************************************************************************/
  231. /* INTERRUPT OPTIMIZATIONS -- MS-DOS                        */
  232. #ifdef    __MSDOS__
  233. /****************************************************************************/
  234. /****************************************************************************/
  235. #define    MPSIG_KEYSTROKE    (0x09)
  236. MPRES    _mpres_keyboard[1];
  237. void    interrupt    (* _mpsig_oldkeystroke)(void);
  238. void    interrupt    _mpsig_keystroke(void)
  239. {
  240.     _mpsig_oldkeystroke();
  241.     mptsk_broadcast(mpres_keystroke,(MPMSGID)~0);
  242. }
  243. /****************************************************************************/
  244. #define    MPSIG_KEYBOARD    (0x16)
  245. void    interrupt    (* _mpsig_oldkeyboard)();
  246. void    interrupt    _mpsig_keyboard(bp, di, si, ds, es, dx, cx, bx,
  247.                     char al, char ah, ip, cs, flags)
  248. {
  249.     if (ah==0) {    /* IF ABOUT TO READ A CHARACTER */
  250.         /* WHILE NO CHARACTER IS AVAILABLE */
  251.         while(_AH= 1, _mpsig_oldkeystroke(), flags & FLAG_ZF)
  252.             /* WAIT TO BE SIGNALED */
  253.             mptsk_recv(_mpres_keyboard);
  254.     }
  255.     _AH=    ah;
  256.     _mpsig_oldkeystroke();
  257. }
  258. #endif    /* __MSDOS__ */
  259. /****************************************************************************/
  260. /****************************************************************************/
  261. /****************************************************************************/
  262. /* INTERRUPT OPTIMIZATIONS -- UNIX                        */
  263. #ifdef    unix
  264. /****************************************************************************/
  265. /****************************************************************************/
  266. MPRES    _mpres_io[1];
  267. void    (* _mpsig_oldsigio)();
  268.  
  269. void    _mpsig_sigio(void)
  270. {
  271.     _mpsig_oldsigio();
  272.     mptsk_broadcast(mpres_io,(MPMSGID)~0);
  273. }
  274. #define    mpres_io(IOCALL)                        \
  275.     for(ever) {                            \
  276.         int    _errno;                        \
  277.         mpres_critsect(mpres_errno, {                \
  278.             errno= 0;                    \
  279.             {IOCMD};                    \
  280.             _errno=    errno;                    \
  281.         });                            \
  282.         if (_errno!=EWOULDBLOCK)    break;            \
  283.         mptsk_recv(_mpres_io);                    \
  284.     }
  285.  
  286. #define    mpres_ioinit(filedescriptor)                    \
  287.     fcntl(filedescriptor,F_SETFL,                    \
  288.         fcntl(filedescriptor,F_GETFL) | FNDELAY | FASYNC)
  289.  
  290. #endif    /* unix */
  291. /****************************************************************************/
  292. /****************************************************************************/
  293. void    mpres_setup(void)
  294. {
  295.     mpres_init(_mpres_ram);
  296.      mpres_init(_mpres_errno);
  297.         mptsk_create(mpthd_create(mpthdfn_death,1000),mpscd_toptasks());
  298.     mptsk_create(mpthd_create(mpthdfn_idletask,1000),mpscd_idletasks);
  299.  
  300. #ifdef    __MSDOS__
  301.     _mpsig_oldclocktick=    mpdos_vect(MPSIG_CLOCKTICK,_mpsig_clocktick);
  302.     _mpsig_oldkeystroke=    mpdos_vect(MPSIG_KEYSTROKE,_mpsig_keystroke);
  303.     _mpsig_oldkeyboard=    mpdos_vect(MPSIG_KEYBOARD, _mpsig_keyboard);
  304. #endif
  305. #ifdef    unix
  306.     _mpsig_oldclocktick=    signal(SIGALRM,_mpsig_clocktick);
  307.     _mpsig_oldsigio=    signal(SIGIO,_mpsig_sigio);
  308. #endif
  309. }
  310. /****************************************************************************/
  311. /****************************************************************************/
  312. /****************************************************************************/
  313. MPTHDID    mpthd_create(MPTHDFN mpthdfn,UINT threadsize)
  314. {
  315.     MPTHDID    mpthd;
  316.     mpres_ram(mpthd= (MPTHDID)malloc(3*sizeof(MPTHD)+threadsize));
  317.     if (mpthd)    mpthd=    mpthd_init(mpthd,3*sizeof(MPTHD)+threadsize));
  318.     return(mpthd);
  319. }
  320. void    mpthd_destroy(MPTHD mpthd)
  321. {
  322.     if (mpthd)    mpres_ram(free(mpthd_dinit(mpthd)));
  323. }
  324. /****************************************************************************/
  325. MPTSKID    mptsk_create(MPTHD mpthd, MPSCDID sched)
  326. {
  327.     MPTSKID    mptsk;
  328.     mpres_ram(mptsk= (MPTSKID)malloc(sizeof(MPTSK)));
  329.     if (mpthd && mptsk)    mptsk=    mptsk_init(mptsk,mpthd,sched);
  330.     return(mptsk);
  331. }
  332. MPTHDID    mptsk_destroy(MPTSKID mptsk)
  333. {
  334.     MPTHDID    mpthd=    0;
  335.     if (mptsk) {
  336.         mpthd=    mptsk_mpthd(mptsk);
  337.         mpres_ram(free(mptsk_dinit(mptsk));
  338.     }
  339.     return(mpthd);
  340. }
  341. /****************************************************************************/
  342. /****************************************************************************/
  343.