home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / misc / amigem.lha / amigem / exec / kernel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-30  |  6.8 KB  |  244 lines

  1. /*
  2.  * Following is the basis of the whole system (including the dispatcher).
  3.  * Therefore I'd like to call it the kernel though it's probably
  4.  * too small for a real kernel or even a microkernel and it doesn't all run in
  5.  * supervisor mode like a kernel usually does...
  6.  *
  7.  * Anyway - the interface to the interrupt mechanism of the "hardware"
  8.  * and other important stuff consists of 6 well-known and 4 private functions:
  9.  *
  10.  * void RaiseInt(ULONG intnum);
  11.  *
  12.  *   Generates a certain interrupt (immediately if not in disabled state).
  13.  *
  14.  * APTR SwitchContext(APTR newstack);
  15.  *
  16.  *   Switches the underlying user context (stack) to a new one.
  17.  *   Returns the old one. Must be called from interrupt code.
  18.  *
  19.  * APTR AddContext(APTR oldstack,APTR function,APTR data);
  20.  *
  21.  *   Can be used to build a new context on top of some old one or some
  22.  *   fresh stackspace (oldstack). Returns the new top of stack.
  23.  *   'function' gets called with 'data' provided and in disabled state.
  24.  *   Falling through the end of it returns to the old context.
  25.  *
  26.  * void FallAsleep(void);
  27.  *
  28.  *   Puts the whole system asleep and waits until some interrupts had happened.
  29.  *
  30.  * As always: Don't use private stuff - it's explained here to be able to port
  31.  *            or understand it, not to use it.
  32.  */
  33.  
  34. #include <stdio.h>
  35. #include <signal.h>
  36. #include <setjmp.h>
  37. #include <sys/time.h>
  38. #include <hardware/intbits.h>
  39. #include <clib/_exec.h>
  40. #include <amigem/utils.h>
  41. #include "exec.h"
  42. #include "machine.h"
  43.  
  44. #ifdef ABSEXECBASE
  45. #define SYSBASE (*(struct ExecBase **)(ABSEXECBASE))
  46. #else
  47. struct ExecBase *sysbase;
  48. #define SYSBASE sysbase
  49. #endif
  50.  
  51. #include <amigem/fd_lib.h>
  52. #define LIBBASE struct ExecBase *SysBase
  53.  
  54. #define cacheclearu              (*(void (*)(void))SysBase->functable[0])
  55. #define cachecleare      (*(void (*)(APTR,ULONG,ULONG))SysBase->functable[1])
  56. #define cachepredma     (*(APTR (*)(APTR,LONG *,ULONG))SysBase->functable[2])
  57. #define cachepostdma     (*(void (*)(APTR,LONG *,ULONG))SysBase->functable[3])
  58. #define setjmp                (*(int (*)(jmp_buf))SysBase->functable[4])
  59. #define longjmp               (*(void (*)(jmp_buf,int))SysBase->functable[5])
  60. #define kill              (*(int (*)(pid_t,int))SysBase->functable[6])
  61. #define getpid                 (*(pid_t (*)(void))SysBase->functable[7])
  62. #define sigprocmask \
  63.         (*(int (*)(int,const sigset_t *,sigset_t *))SysBase->functable[8])
  64. #define sigsuspend       (*(int (*)(const sigset_t *))SysBase->functable[9])
  65. #define setitimer \
  66.  (*(int (*)(int,struct itimerval *,struct itimerval *))SysBase->functable[11])
  67.  
  68. /*
  69.  * How to map signals to interrupts.
  70.  */
  71. static const WORD maptabl[][2]=
  72. {
  73.   { SIGALRM,INTB_VERTB },
  74.   { SIGUSR1,INTB_SOFTINT }
  75. };
  76.  
  77. void handler(int sig);
  78.  
  79. /*
  80.  * This initializes some things.
  81.  */
  82. void InitKernel(struct ExecBase *SysBase)
  83. {
  84.   int i;
  85.   struct sigaction sa;
  86.  
  87.   SYSBASE=SysBase;
  88.  
  89.   sigemptyset(&SysBase->used);
  90.   sigemptyset(&SysBase->currentints);
  91.   SysBase->currentcontext=NULL;
  92.  
  93.   for(i=0;i<sizeof(maptabl)/(sizeof(WORD))/2;i++)
  94.   {
  95.     SysBase->inttabl[maptabl[i][0]]=maptabl[i][1];
  96.     SysBase->sigtabl[maptabl[i][1]]=maptabl[i][0];
  97.     sigaddset(&SysBase->used,maptabl[i][0]);
  98.   }
  99.   sa.sa_handler=&handler;
  100.   sa.sa_mask=SysBase->used;
  101.   sa.sa_flags=0;
  102.   for(i=0;i<sizeof(maptabl)/(sizeof(WORD))/2;i++)
  103.     (*(void (*)(int,struct sigaction *,struct sigaction *))SysBase->functable[10])
  104.       (maptabl[i][0],&sa,NULL); /* sigaction() */
  105.   {
  106.     struct itimerval t;
  107.  
  108.     t.it_interval.tv_sec =t.it_value.tv_sec =0;
  109.     t.it_interval.tv_usec=t.it_value.tv_usec=20000;
  110.     setitimer(ITIMER_REAL,&t,NULL);
  111.   }
  112. }
  113.  
  114. FD0F(20,p,void,Disable)
  115. {
  116.   sigprocmask(SIG_BLOCK,&SysBase->used,NULL); /* To make it reentrant disable always */
  117.   SysBase->IDNestCnt++;
  118. }
  119.  
  120. FD0F(21,p,void,Enable)
  121. {
  122.   if(!SysBase->IDNestCnt--)
  123.   {
  124.     if(SysBase->currentcontext!=NULL) /* Save to call from supervisor mode */
  125.       sigprocmask(SIG_SETMASK,&SysBase->currentints,NULL);
  126.     else
  127.       sigprocmask(SIG_UNBLOCK,&SysBase->used,NULL);
  128.   }
  129. }
  130.  
  131. FD0(6,void,Private_1) /* FallAsleep */
  132. {
  133.   sigsuspend(&SysBase->used);
  134. }
  135.  
  136. /* Call function over base register A5 */
  137. FC2F(0,b,void,IntHandler,A5,APTR is_data,A1,struct ExecBase *SysBase,A6)
  138. ;
  139.  
  140. FC2(0,void,super,A0,int sig,D0,APTR stack,SP)
  141. {
  142.   sigset_t omask;
  143.   struct ExecBase *SysBase=SYSBASE;
  144.  
  145.   sigaddset(&SysBase->currentints,sig);
  146.   sigprocmask(SIG_SETMASK,&SysBase->currentints,&omask);
  147.   if(SysBase->IntVects[SysBase->inttabl[sig]].iv_Code)
  148.     IntHandler(SysBase->IntVects[SysBase->inttabl[sig]].iv_Code,
  149.                SysBase->IntVects[SysBase->inttabl[sig]].iv_Data,SysBase);
  150.   sigdelset(&SysBase->currentints,sig);
  151.   sigprocmask(SIG_SETMASK,&omask,NULL);
  152. }
  153.  
  154. struct jb /* You cannot build the address of a jmp_buf but of a struct jb */
  155. { jmp_buf jb; };
  156.  
  157. #define JB2SP(jb) ((char *)&(jb)-CONTEXTOFFSET)
  158. #define SP2JB(sp) (((struct jb *)((char *)(sp)+CONTEXTOFFSET))->jb)
  159.  
  160. /*
  161.  * This function is single-threaded by setting all bits in the signal mask
  162.  * of sigaction(). It calls itself recursively on the supervisor stack
  163.  * (if not already done) then reenables all signals not currently delivered.
  164.  * The current position on the user stack is memorized as the current context.
  165.  */
  166. void handler(int sig)
  167. {
  168.   volatile struct ExecBase *SysBase=SYSBASE;
  169.  
  170.   if(!SysBase->currentcontext)
  171.   {
  172.     struct jb jb;
  173.     SysBase->currentcontext=JB2SP(jb.jb);
  174.     if(!setjmp(jb.jb))
  175.     {
  176.       super(&__super,sig,STACKPOINTER(SysBase->SysStkLower,SysBase->SysStkUpper));
  177.       longjmp(SP2JB(SysBase->currentcontext),1);
  178.     }
  179.     SysBase->currentcontext=NULL;
  180.   }else
  181.     ___super(NULL,sig,NULL);
  182. }
  183.  
  184. FD1(7,APTR,Private_2,APTR newstack,A0) /* SwitchContext */
  185. {
  186.   APTR ret;
  187.   Disable();
  188.     ret=SysBase->currentcontext;
  189.     SysBase->currentcontext=newstack;
  190.   Enable();
  191.   return ret;
  192. }
  193.  
  194. FC3(0,void,newcontext,A0,APTR function,A1,APTR data,A2,APTR stack,SP)
  195. {
  196.   volatile APTR f2=function,d2=data,sp=stack;
  197.   volatile struct ExecBase *SysBase=SYSBASE;
  198.  
  199.   struct jb jb;
  200.  
  201.   if(!setjmp(jb.jb))
  202.   {
  203.     struct jb *t;
  204.     t=(struct jb *)SysBase->newstack;
  205.     SysBase->newstack=(APTR)&jb;
  206.     longjmp(t->jb,1);
  207.   }
  208.   SysBase->currentcontext=NULL;
  209.   SysBase->IDNestCnt=0;
  210.   IntHandler(f2,d2,(struct ExecBase *)SysBase);
  211.   SysBase->IDNestCnt=-1;
  212.   longjmp(SP2JB(sp),1);
  213. }
  214.  
  215. FD3(8,APTR,Private_3,APTR oldstack,A0,APTR function,A1,APTR data,A2) /* AddContext */
  216. {
  217.   APTR ret;
  218.   struct jb jb;
  219.   Disable();
  220.   SysBase->newstack=(APTR)&jb;
  221.   if(!setjmp(jb.jb))
  222.     newcontext(&__newcontext,function,data,oldstack);
  223.   ret=JB2SP(*SysBase->newstack);
  224.   Enable();
  225.   return ret;
  226. }
  227.  
  228. FD1(9,void,Private_4,ULONG intnum,D0) /* RaiseInt */
  229. {
  230.   kill(getpid(),SysBase->sigtabl[intnum]);
  231. }
  232.  
  233. FD0(106,void,CacheClearU)
  234. { cacheclearu(); }
  235.  
  236. FD3(107,void,CacheClearE,APTR address,A0,ULONG length,D0,ULONG flags,D1)
  237. { cachecleare(address,length,flags); }
  238.  
  239. FD3(127,APTR,CachePreDMA,APTR address,A0,LONG *length,A1,ULONG flags,D0)
  240. { return cachepredma(address,length,flags); }
  241.  
  242. FD3(128,void,CachePostDMA,APTR address,A0,LONG *length,A1,ULONG flags,D0)
  243. { cachepostdma(address,length,flags); }
  244.