home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / docs / src / exec_microkernel.doc < prev    next >
Text File  |  1996-11-18  |  4KB  |  90 lines

  1.         The exec microkernel
  2.         --------------------
  3.  
  4. This document describes the inner workings of exec.library. It's not for
  5. normal application programmers but for people who are interested in
  6. such a thing. Most of the things described herein are system private - 
  7. they may or may not be true for future system version.
  8.  
  9. Exec is a shared library giving the ability for multitasking including
  10. communication between tasks, memory management, shared libraries and device
  11. I/O. Large parts of this library are formed by a set of functions that are
  12. called on the users schedule just like any normal C function is (though they
  13. do things you'd usually expect in a kernel). These functions make up the
  14. library part of exec which is built on a smaller set of functions which
  15. form the core of exec (you may call them the real kernel if you like).
  16. This machine dependant core serves things like supervisor mode, traps, 
  17. interrupts, task exceptions and context switching routines.
  18.  
  19. The core of exec in short:
  20. ULONG Supervisor(ULONG (*)());    - calls a user function in supervisor mode
  21. APTR tc_TrapData;
  22. APTR tc_TrapCode;        - user setable trap vector
  23. IntVects[i]            - the different interrupt vectors
  24. void Disable(void);        - disable interrupts
  25. void Enable(void);        - enable them again
  26. BYTE IDNestCnt;            - -1 if interrupts are allowed
  27. APTR PrepareContext(APTR);    - prepare a new stack to hold a context
  28. void Switch(void);        - do a task switch
  29. AttnFlags&0x8000        - delayed dispatch flag
  30. AttnFlags&0x80            - delayed switch flag
  31. tc_Flags&TF_SWITCH        - tc_Switch is active
  32. void (*tc_Switch)();        - vector to be called before task loses CPU
  33. tc_Flags&TF_LAUNCH        - tc_Launch is active
  34. void (*tc_Launch)();        - vector to be called before task gets CPU
  35. UBYTE tc_State;            - where the actual task structure is sorted in
  36. struct Task *ThisTask;        - pointer to actual task structure
  37. struct List TaskReady;        - sorted list of tasks waiting for CPU
  38. tc_Flags&TF_EXCEPT        - raise a task exception for this task at
  39.                   the next context switch
  40. void Exception(void);        - is called to handle the task exception
  41.  
  42. The most important part are the context switching routines. The context of
  43. every task is stored on the task's user stack. The stackpointer is stored
  44. in the task structure. Context switches are raised by moving the current
  45. task to one of the two task lists (must be done with interrupts Disable()d)
  46. and then calling Switch(). However if this happens inside an interrupt
  47. (which is allowed and quite useful) the user context is unavailable.
  48. Therefore Switch() checks if it was called from user mode and sets the
  49. delayed dispatch flag if not. This flag tells the interrupt primitives
  50. to do a context switch (by calling Dispatch()) before falling down to user
  51. mode. When called from user mode Switch() calls Dispatch() directly.
  52. Dispatch() is the function which does the real work, i.e. it replaces the
  53. current task with the first task in the ready list. If the TF_EXCEPT flag
  54. for the new task is set Dispatch() raises a task exception by calling
  55. the Exception() vector of exec with interrupts Disable()d.
  56. tc_Switch and tc_Launch are also handled by Dispatch().
  57.  
  58. The usual way to do a context switch is as follows:
  59.  
  60. if(I_need_a_task_switch)
  61. {
  62.   /* The task lists must be protected with a Disable() */
  63.   Disable();
  64.   /* check if taskswitches are allowed */
  65.   if(SysBase->TDNestCnt<0&&SysBase->IDNestCnt<=0)
  66.   {
  67.     /* Check if there is already a pending task switch (this check can
  68.        be skipped if I can guarantee to be in user mode). */
  69.     if(SysBase->ThisTask->tc_State==TS_RUN)
  70.     {
  71.       /* No. Move the current task away */
  72.       Enqueue(new_list,SysBase->ThisTask);
  73.       SysBase->ThisTask->tc_State=new_state;
  74.       /* And do the switch */
  75.       Switch();
  76.     }
  77.   }else
  78.     /* Memorize taskswitch for a later Enable() or Permit(). */
  79.     SysBase->AttnFlags|=0x80;
  80.   Enable();
  81. }
  82.  
  83. Interrupts and traps are delivered with direct function calls. The different
  84. interrupt levels call different interrupt vectors (stored in IntVects[i]).
  85. Traps are raised by calling the tc_TrapCode vector of the current task
  86. (usually this ends up in an Alert() - the exec equivalent of a kernel panic).
  87. Interrupts may be disabled completely (by calling Disable(), Enable()
  88. enables them again, Disable() calls may be nested) but only for a short
  89. time.
  90.