home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / examples / multitask / process.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  3.5 KB  |  121 lines

  1. /* Copyright (c) 1993 SAS Institute, Inc, Cary, NC, USA */
  2. /* All Rights Reserved */
  3.  
  4. #include "process.h"
  5.  
  6. void process_starter(void)
  7. {
  8.    struct Process *proc;
  9.    struct ProcMsg *mess;
  10.    long (*fp)(void);
  11.          
  12.    proc = (struct Process *)FindTask((char *)NULL);
  13.  
  14.    /* get the startup message */
  15.    WaitPort(&proc->pr_MsgPort);
  16.    mess = (struct ProcMsg *)GetMsg(&proc->pr_MsgPort);
  17.  
  18.    /* gather necessary info from message */
  19.    fp = mess->fp;
  20.    putreg(REG_A4, (long)mess->global_data);
  21.    
  22.    
  23.    /* Call the desired function */
  24.    mess->return_code = (*fp)();
  25.    
  26.    /* Forbid so the child can finish completely, before */
  27.    /* the parent cleans up.                             */
  28.    Forbid();
  29.  
  30.    /* Reply so process who spawed us knows we're done */   
  31.    ReplyMsg((struct Message *)mess);
  32. }
  33.  
  34.  
  35. struct ProcMsg *start_process(fp, priority, stacksize)
  36. long (*fp)(void);
  37. long priority,stacksize;
  38. {
  39.    struct MsgPort *child_port;
  40.    struct ProcMsg *start_msg;
  41.    struct FAKE_SegList *seg_ptr;
  42.    
  43.    /* Allocate memory for both fake seglist and startup message */
  44.    /* If either fail we can return, before the CreateProc()     */ 
  45.    seg_ptr = (struct FAKE_SegList *)AllocMem(sizeof (*seg_ptr), MEMF_PUBLIC);
  46.    if (seg_ptr == NULL) return NULL;
  47.    start_msg = (struct ProcMsg *)AllocMem(sizeof(struct ProcMsg), 
  48.                                           MEMF_PUBLIC|MEMF_CLEAR);
  49.    if (start_msg == NULL)
  50.    {
  51.       FreeMem(seg_ptr, sizeof (*seg_ptr));
  52.       return NULL;
  53.    }
  54.    
  55.    
  56.    /* Fill in Fake SegList */
  57.    seg_ptr->space = 0;
  58.    seg_ptr->length = (sizeof(*seg_ptr) + 3) & ~3;
  59.    seg_ptr->nextseg = NULL;
  60.    
  61.    /* Fill in JMP to function */
  62.    seg_ptr->jmp = 0x4EF9;  /* JMP instruction */
  63.    seg_ptr->func = process_starter;
  64.    
  65.    /* If we're running under 2.0 it's possible to be on a 68040 */
  66.    /* Therefore the cache needs to be flushed before the child  */
  67.    /* can start executing.                                      */
  68.    if (SysBase->LibNode.lib_Version >= 36)
  69.       CacheClearU();
  70.       
  71.    /* create the child process */   
  72.    if((child_port = CreateProc("New Process",
  73.                                priority,
  74.                                (BPTR)((long)&seg_ptr->nextseg>>2),
  75.                                stacksize)) == NULL)
  76.    {
  77.       /* error, cleanup and abort */
  78.       FreeMem(seg_ptr, sizeof(*seg_ptr));
  79.       FreeMem(start_msg, sizeof(*start_msg));
  80.       return NULL;
  81.    }
  82.    
  83.    /* Create the startup message */
  84.    start_msg->msg.mn_Length = sizeof(struct ProcMsg) - sizeof(struct Message);
  85.    start_msg->msg.mn_ReplyPort = CreatePort(0,0);
  86.    start_msg->msg.mn_Node.ln_Type = NT_MESSAGE;
  87.    
  88.    /* save global data reg (A4) */
  89.    start_msg->global_data = (void *)getreg(REG_A4);
  90.  
  91.    start_msg->seg = seg_ptr;
  92.    start_msg->fp = fp;                 /* Fill in function pointer */
  93.    
  94.    /* send startup message to child */
  95.    PutMsg(child_port, (struct Message *)start_msg);
  96.    
  97.    return start_msg;
  98. }
  99.  
  100. long wait_process(start_msg)
  101. struct ProcMsg *start_msg;
  102. {
  103.     struct ProcMsg *msg;
  104.     long ret;
  105.            
  106.     /* Wait for child to reply, signifying that it is finished */
  107.     while ((msg = (struct ProcMsg *)
  108.                    WaitPort(start_msg->msg.mn_ReplyPort)) != start_msg) 
  109.           ReplyMsg((struct Message *)msg);
  110.  
  111.     /* get return code */
  112.     ret = msg->return_code;
  113.  
  114.     /* Free up remaining resources */
  115.     DeletePort(start_msg->msg.mn_ReplyPort);
  116.     FreeMem((void *)start_msg->seg, sizeof(struct FAKE_SegList));
  117.     FreeMem((void *)start_msg, sizeof(*start_msg));
  118.  
  119.     return(ret);
  120. }
  121.