home *** CD-ROM | disk | FTP | other *** search
- /*
- * tfork(function, argument): starts a new thread of execution running
- * in the same address space. The new thread gets its own 4K stack,
- * and starts at the address in "function" with "argument" on the stack,
- * i.e. as though the main program had a call like "function(argument)".
- * The main program continues executing, with tfork returning the process
- * i.d. of the child.
- * (if MiNT is not active, then the child runs first to completion
- * and the return value is the child's exit status; vfork() relies this
- * behavior)
- *
- * Note that parent and child share the same memory; this could cause
- * problems with some library calls, notably malloc().
- */
-
- #include <osbind.h>
- #include <basepage.h>
- #include <signal.h>
- #include <time.h>
- #include <unistd.h>
- #include <signal.h>
- #include <errno.h>
-
- #define SIZE 4096L
-
- extern int __mint;
- extern long _childtime; /* in main.c */
- extern long _sigpending, _sigmask; /* in signal.c */
- extern __Sigfunc _sig_handler[NSIG]; /* ditto */
-
-
- /* this is used by wait() and wait3() to retrieve the child's exit code */
- long __waitval = -ENOENT;
-
- /* and this is used to retrieve the child's time */
- long __waittime = 0;
-
- static void
- startup(b)
- register BASEPAGE *b;
- {
- register int (*func)();
- register long arg;
- extern void _setstack(); /* in crt0.s */
-
- _setstack( ((long)b) + SIZE );
- func = (int (*)())b->p_dbase;
- arg = b->p_dlen;
- Pterm((*func)(arg));
- }
-
- /* use long instead of int so vfork works OK with -mshort */
-
- long
- tfork(func, arg)
- int (*func)();
- long arg;
- {
- register BASEPAGE *b;
- register long pid;
- register long savpending, savmask;
- register BASEPAGE *savbase;
- __Sigfunc savhandler[NSIG];
- long now;
- int i;
-
- b = (BASEPAGE *)Pexec(PE_CBASEPAGE, 0L, "", 0L);
- (void)Mshrink(b, SIZE);
- b->p_tbase = (char *)startup;
- b->p_dbase = (char *)func;
- b->p_dlen = arg;
- if (__mint)
- pid = Pexec(104, 0L, b, 0L);
- else {
- /* save the signal masks and signal handlers, the child may change
- them */
- savpending = _sigpending;
- _sigpending = 0;
- savmask = _sigmask;
- _sigmask = 0;
- for (i = 0; i < NSIG; i++)
- savhandler[i] = _sig_handler[i];
- savbase = _base;
- _base = b;
-
- now = clock();
- pid = Pexec(4, 0L, b, 0L);
- (void)Mfree((long)b->p_env); /* free the memory */
- (void)Mfree((long)b);
-
- _base = savbase;
- /* restore signal stuff */
- for (i = 0; i < NSIG; i++)
- _sig_handler[i] = savhandler[i];
- _sigmask = savmask;
- _sigpending = savpending;
- if (pid >= 0) {
- int retval = pid;
-
- /* see the TOS algorithm for getpid() */
- pid = ((long)b) >> 8;
- __waitval = (pid << 16) | retval;
- raise(SIGCHLD);
- __waittime = clock() - now;
- _childtime += __waittime;
- }
- }
- return pid;
- }
-