home *** CD-ROM | disk | FTP | other *** search
/ MACD 4 / MACD4.iso / Emulatory / AROS / exec / addtask.c < prev    next >
Encoding:
C/C++ Source or Header  |  1978-03-06  |  5.5 KB  |  209 lines

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