home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / exec / addtask.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-09  |  5.7 KB  |  217 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: addtask.c,v 1.11 1997/01/01 03:46:04 ldp Exp $
  4.     $Log: addtask.c,v $
  5.     Revision 1.11  1997/01/01 03:46:04  ldp
  6.     Committed Amiga native (support) code
  7.  
  8.     Changed clib to proto
  9.  
  10.     Revision 1.10  1996/12/10 13:51:36  aros
  11.     Moved all #include's in the first column so makedepend can see it.
  12.  
  13.     Revision 1.9  1996/10/24 15:50:42  aros
  14.     Use the official AROS macros over the __AROS versions.
  15.  
  16.     Revision 1.8  1996/10/23 14:21:23  aros
  17.     Renamed a few macros from XYZ to AROS_XYZ so we know which if from AROS and
  18.     which not.
  19.  
  20.     Revision 1.7  1996/10/19 17:07:23  aros
  21.     Include <aros/machine.h> instead of machine.h
  22.  
  23.     Revision 1.6  1996/09/11 16:54:23  digulla
  24.     Always use AROS_SLIB_ENTRY() to access shared external symbols, because
  25.     some systems name an external symbol "x" as "_x" and others as "x".
  26.     (The problem arises with assembler symbols which might differ)
  27.  
  28.     Revision 1.5  1996/08/16 14:05:12  digulla
  29.     Added debug output
  30.  
  31.     Revision 1.4  1996/08/13 13:55:57  digulla
  32.     Replaced AROS_LA by AROS_LHA
  33.     Replaced some AROS_LH*I by AROS_LH*
  34.     Sorted and added includes
  35.  
  36.     Revision 1.3  1996/08/01 17:41:03  digulla
  37.     Added standard header for all files
  38.  
  39.     Desc:
  40.     Lang: english
  41. */
  42. #include <exec/execbase.h>
  43. #include <aros/libcall.h>
  44. #include <aros/machine.h>
  45. #include <proto/exec.h>
  46.  
  47. #include "exec_debug.h"
  48. #ifndef DEBUG_AddTask
  49. #   define DEBUG_AddTask 0
  50. #endif
  51. #if DEBUG_AddTask
  52. #   undef DEBUG
  53. #   define DEBUG 1
  54. #endif
  55. #include <aros/debug.h>
  56.  
  57. static void KillCurrentTask(void);
  58. void AROS_SLIB_ENTRY(TrapHandler,Exec)(void);
  59.  
  60. /*****************************************************************************
  61.  
  62.     NAME */
  63.  
  64.     AROS_LH3(APTR, AddTask,
  65.  
  66. /*  SYNOPSIS */
  67.     AROS_LHA(struct Task *,     task,      A1),
  68.     AROS_LHA(APTR,              initialPC, A2),
  69.     AROS_LHA(APTR,              finalPC,   A3),
  70.  
  71. /*  LOCATION */
  72.     struct ExecBase *, SysBase, 47, Exec)
  73.  
  74. /*  FUNCTION
  75.     Add a new task to the system. If the new task has the highest
  76.     priority of all and task switches are allowed it will be started
  77.     immediately.
  78.     Certain task fields should be intitialized and a stack must be
  79.     allocated before calling this function. tc_SPReg will be used as the
  80.     starting location for the stack pointer, i.e. a part of the stack can
  81.     be reserved to pass the task some initial arguments.
  82.     Memory can be added to the tc_MemEntry list and will be freed when the
  83.     task dies. The new task's registers are set to 0.
  84.  
  85.     INPUTS
  86.     task      - Pointer to task structure.
  87.     initialPC - Entry point for the new task.
  88.     finalPC   - Routine that is called if the initialPC() function returns.
  89.             A NULL pointer installs the default finalizer.
  90.  
  91.     RESULT
  92.     The address of the new task or NULL if the operation failed (can only
  93.     happen with TF_ETASK set - currenty not implemented).
  94.  
  95.     NOTES
  96.  
  97.     EXAMPLE
  98.  
  99.     BUGS
  100.  
  101.     SEE ALSO
  102.     RemTask()
  103.  
  104.     INTERNALS
  105.  
  106.     HISTORY
  107.  
  108. ******************************************************************************/
  109. {
  110.     AROS_LIBFUNC_INIT
  111.     APTR sp;
  112.  
  113.     D(bug("Call AddTask (%08lx (\"%s\"), %08lx, %08lx)\n"
  114.     , task
  115.     , task->tc_Node.ln_Name
  116.     , initialPC
  117.     , finalPC
  118.     ));
  119.  
  120.     /* Set node type to NT_TASK if not set to something else. */
  121.     if(!task->tc_Node.ln_Type)
  122.     task->tc_Node.ln_Type=NT_TASK;
  123.  
  124.     /* Sigh - you should provide a name for your task. */
  125.     if(task->tc_Node.ln_Name==NULL)
  126.     task->tc_Node.ln_Name="unknown task";
  127.  
  128.     /* This is moved into SysBase at the tasks's startup */
  129.     task->tc_IDNestCnt=-1;
  130.  
  131.     /* Signals default to all system signals allocated. */
  132.     if(task->tc_SigAlloc==0)
  133.     task->tc_SigAlloc=0xffff;
  134.  
  135.     /* Currently only used for segmentation violation */
  136.     if(task->tc_TrapCode==NULL)
  137.     task->tc_TrapCode=&AROS_SLIB_ENTRY(TrapHandler,Exec);
  138.  
  139.     /* Get new stackpointer. */
  140.     sp=task->tc_SPReg;
  141.     if(task->tc_SPReg==NULL)
  142. #if AROS_STACK_GROWS_DOWNWARDS
  143.     sp=(UBYTE *)task->tc_SPUpper-SP_OFFSET;
  144. #else
  145.     sp=(UBYTE *)task->tc_SPLower-SP_OFFSET;
  146. #endif
  147.  
  148.     /* Default finalizer? */
  149.     if(finalPC==NULL)
  150.     finalPC=&KillCurrentTask;
  151.  
  152.     /* Init new context. */
  153.     sp=PrepareContext(sp,initialPC,finalPC);
  154.  
  155.     /* store sp */
  156.     task->tc_SPReg=sp;
  157.  
  158.     /* Set the task flags for switch and launch. */
  159.     if(task->tc_Switch)
  160.     task->tc_Flags|=TF_SWITCH;
  161.  
  162.     if(task->tc_Launch)
  163.     task->tc_Flags|=TF_LAUNCH;
  164.  
  165.     /* tc_MemEntry _must_ already be set. */
  166.  
  167.     /*
  168.     Protect the task lists. This must be done with Disable() because
  169.     of Signal() which is usable from interrupts and may change those
  170.     lists.
  171.      */
  172.     Disable();
  173.  
  174.     /* Add the new task to the ready list. */
  175.     task->tc_State=TS_READY;
  176.     Enqueue(&SysBase->TaskReady,&task->tc_Node);
  177.  
  178.     /*
  179.     Determine if a task switch is necessary. (If the new task has a
  180.     higher priority than the current one and the current one
  181.     is still active.) If the current task isn't of type TS_RUN it
  182.     is already gone.
  183.     */
  184.     if(task->tc_Node.ln_Pri>SysBase->ThisTask->tc_Node.ln_Pri&&
  185.        SysBase->ThisTask->tc_State==TS_RUN)
  186.     {
  187.     /* Are taskswitches allowed? (Don't count own Disable() here) */
  188.     if(SysBase->TDNestCnt>=0||SysBase->IDNestCnt>0)
  189.         /* No. Store it for later. */
  190.         SysBase->AttnResched|=0x80;
  191.     else
  192.     {
  193.         /* Switches are allowed. Move the current task away. */
  194.         SysBase->ThisTask->tc_State=TS_READY;
  195.         Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
  196.  
  197.         /* And force a rescedule. */
  198.         Switch();
  199.     }
  200.     }
  201.  
  202.     Enable();
  203.  
  204.     ReturnPtr ("AddTask", struct Task *, task);
  205.     AROS_LIBFUNC_EXIT
  206. } /* AddTask */
  207.  
  208. /* Default finalizer. */
  209. static void KillCurrentTask(void)
  210. {
  211.     /* I need the global SysBase variable here - there's no local way to get it. */
  212.     extern struct ExecBase *SysBase;
  213.  
  214.     /* Get rid of current task. */
  215.     RemTask(SysBase->ThisTask);
  216. }
  217.