home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
mint
/
mntlib16.lzh
/
MNTLIB16
/
THREAD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-03
|
3KB
|
110 lines
/*
* 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;
}