home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / gnu / mntlib16.lzh / MNTLIB16 / THREAD.C < prev    next >
C/C++ Source or Header  |  1993-07-29  |  3KB  |  110 lines

  1. /*
  2.  * tfork(function, argument): starts a new thread of execution running
  3.  * in the same address space. The new thread gets its own 4K stack,
  4.  * and starts at the address in "function" with "argument" on the stack,
  5.  * i.e. as though the main program had a call like "function(argument)".
  6.  * The main program continues executing, with tfork returning the process
  7.  * i.d. of the child.
  8.  * (if MiNT is not active, then the child runs first to completion
  9.  *  and the return value is the child's exit status; vfork() relies this
  10.  *  behavior)
  11.  *
  12.  * Note that parent and child share the same memory; this could cause
  13.  * problems with some library calls, notably malloc().
  14.  */
  15.  
  16. #include <osbind.h>
  17. #include <basepage.h>
  18. #include <signal.h>
  19. #include <time.h>
  20. #include <unistd.h>
  21. #include <signal.h>
  22. #include <errno.h>
  23.  
  24. #define SIZE 4096L
  25.  
  26. extern int __mint;
  27. extern long _childtime;            /* in main.c */
  28. extern long _sigpending, _sigmask;    /* in signal.c */
  29. extern __Sigfunc _sig_handler[NSIG];    /* ditto */
  30.  
  31.  
  32. /* this is used by wait() and wait3() to retrieve the child's exit code */
  33. long __waitval = -ENOENT;
  34.  
  35. /* and this is used to retrieve the child's time */
  36. long __waittime = 0;
  37.  
  38. static void
  39. startup(b)
  40.     register BASEPAGE *b;
  41. {
  42.     register int (*func)();
  43.     register long arg;
  44.     extern void _setstack();    /* in crt0.s */
  45.  
  46.     _setstack( ((long)b) + SIZE );
  47.     func = (int (*)())b->p_dbase;
  48.     arg = b->p_dlen;
  49.     Pterm(func(arg));
  50. }
  51.  
  52. /* use long instead of int so vfork works OK with -mshort */
  53.  
  54. long
  55. tfork(func, arg)
  56.     int (*func)();
  57.     long arg;
  58. {
  59.     register BASEPAGE *b;
  60.     register long pid;
  61.     register long savpending, savmask;
  62.     register BASEPAGE *savbase;
  63.     __Sigfunc savhandler[NSIG];
  64.     long now;
  65.     int i;
  66.  
  67.     b = (BASEPAGE *)Pexec(PE_CBASEPAGE, 0L, "", 0L);
  68.     (void)Mshrink(b, SIZE);
  69.     b->p_tbase = (char *)startup;
  70.     b->p_dbase = (char *)func;
  71.     b->p_dlen = arg;
  72.     if (__mint)
  73.         pid = Pexec(104, 0L, b, 0L);
  74.     else {
  75.     /* save the signal masks and signal handlers, the child may change
  76.            them */
  77.         savpending = _sigpending;
  78.         _sigpending = 0;
  79.         savmask = _sigmask;
  80.         _sigmask = 0;
  81.         for (i = 0; i < NSIG; i++)
  82.             savhandler[i] = _sig_handler[i];
  83.         savbase = _base;
  84.         _base = b;
  85.  
  86.         now = clock();
  87.         pid = Pexec(4, 0L, b, 0L);
  88.         (void)Mfree((long)b->p_env);    /* free the memory */
  89.         (void)Mfree((long)b);
  90.  
  91.         _base = savbase;
  92.     /* restore signal stuff */
  93.         for (i = 0; i < NSIG; i++)
  94.             _sig_handler[i] = savhandler[i];
  95.         _sigmask = savmask;
  96.         _sigpending = savpending;
  97.         if (pid >= 0) {
  98.             int retval = pid;
  99.  
  100.         /* see the TOS algorithm for getpid() */
  101.             pid = ((long)b) >> 8;
  102.             __waitval = (pid << 16) | retval;
  103.             raise(SIGCHLD);
  104.             __waittime = clock() - now;
  105.             _childtime += __waittime;
  106.         }
  107.     }
  108.     return pid;
  109. }
  110.