| /* |
| * Thread library. |
| */ |
| |
| #include "threadimpl.h" |
| |
| typedef struct Mainarg Mainarg; |
| struct Mainarg |
| { |
| int argc; |
| char **argv; |
| }; |
| |
| int mainstacksize; |
| |
| extern void (*_sysfatal)(char*, va_list); |
| extern Jmp *(*_notejmpbuf)(void); |
| |
| static void |
| mainlauncher(void *arg) |
| { |
| Mainarg *a; |
| |
| a = arg; |
| _kmaininit(); |
| threadmain(a->argc, a->argv); |
| threadexits("threadmain"); |
| } |
| |
| int |
| main(int argc, char **argv) |
| { |
| Mainarg a; |
| Proc *p; |
| |
| /* |
| * In pthreads, threadmain is actually run in a subprocess, |
| * so that the main process can exit (if threaddaemonize is called). |
| * The main process relays notes to the subprocess. |
| * _Threadbackgroundsetup will return only in the subprocess. |
| */ |
| _threadbackgroundinit(); |
| |
| /* |
| * Instruct QLock et al. to use our scheduling functions |
| * so that they can operate at the thread level. |
| */ |
| _qlockinit(_threadsleep, _threadwakeup); |
| |
| /* |
| * Install our own _threadsysfatal which takes down |
| * the whole confederation of procs. |
| */ |
| _sysfatal = _threadsysfatal; |
| |
| /* |
| * Install our own jump handler. |
| */ |
| _notejmpbuf = _threadgetjmp; |
| |
| /* |
| * Install our own signal handler. |
| */ |
| notify(_threadnote); |
| |
| /* |
| * Construct the initial proc running mainlauncher(&a). |
| */ |
| if(mainstacksize == 0) |
| mainstacksize = 32*1024; |
| a.argc = argc; |
| a.argv = argv; |
| p = _newproc(); |
| _newthread(p, mainlauncher, &a, mainstacksize, "threadmain", 0); |
| _threadscheduler(p); |
| abort(); /* not reached */ |
| return 0; |
| } |
| |
| /* |
| * No-op function here so that sched.o drags in main.o. |
| */ |
| void |
| _threadlinkmain(void) |
| { |
| } |
| |
| Jmp* |
| _threadgetjmp(void) |
| { |
| static Jmp j; |
| Proc *p; |
| |
| p = _threadgetproc(); |
| if(p == nil) |
| return &j; |
| return &p->sigjmp; |
| } |