Move libfmt, libutf into subdirectories of lib9. Add poll-based socket i/o to libthread, so that we can avoid using multiple procs when possible, thus removing dependence on crappy pthreads implementations. Convert samterm, acme to the single-proc libthread. Bring libcomplete, acme up-to-date w.r.t. Plan 9 distribution.
139 lines
2.0 KiB
C
139 lines
2.0 KiB
C
#include <signal.h>
|
|
#include "threadimpl.h"
|
|
|
|
typedef struct Mainarg Mainarg;
|
|
struct Mainarg
|
|
{
|
|
int argc;
|
|
char **argv;
|
|
};
|
|
|
|
int mainstacksize;
|
|
int _threadnotefd;
|
|
int _threadpasserpid;
|
|
static void mainlauncher(void*);
|
|
extern void (*_sysfatal)(char*, va_list);
|
|
|
|
void
|
|
_threaddie(int x)
|
|
{
|
|
extern char *_threadexitsallstatus;
|
|
USED(x);
|
|
|
|
if(_threadexitsallstatus)
|
|
exit(_threadexitsallstatus[0] ? 1 : 0);
|
|
}
|
|
|
|
static void
|
|
_nop(int x)
|
|
{
|
|
USED(x);
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
Mainarg *a;
|
|
Proc *p;
|
|
|
|
signal(SIGTERM, _threaddie);
|
|
signal(SIGCHLD, _nop);
|
|
// rfork(RFREND);
|
|
|
|
//_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0;
|
|
_systhreadinit();
|
|
_qlockinit(_threadrendezvous);
|
|
_sysfatal = _threadsysfatal;
|
|
notify(_threadnote);
|
|
if(mainstacksize == 0)
|
|
mainstacksize = 32*1024;
|
|
|
|
a = _threadmalloc(sizeof *a, 1);
|
|
a->argc = argc;
|
|
a->argv = argv;
|
|
|
|
p = _newproc(mainlauncher, a, mainstacksize, "threadmain", 0, 0);
|
|
_schedinit(p);
|
|
abort(); /* not reached */
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
mainlauncher(void *arg)
|
|
{
|
|
Mainarg *a;
|
|
|
|
a = arg;
|
|
threadmain(a->argc, a->argv);
|
|
threadexits("threadmain");
|
|
}
|
|
|
|
void
|
|
_threadsignal(void)
|
|
{
|
|
}
|
|
|
|
void
|
|
_threadsignalpasser(void)
|
|
{
|
|
}
|
|
|
|
int
|
|
_schedfork(Proc *p)
|
|
{
|
|
int pid;
|
|
lock(&p->lock);
|
|
pid = ffork(RFMEM|RFNOWAIT, _schedinit, p);
|
|
p->pid = pid;
|
|
unlock(&p->lock);
|
|
return pid;
|
|
|
|
}
|
|
|
|
void
|
|
_schedexit(Proc *p)
|
|
{
|
|
char ex[ERRMAX];
|
|
Proc **l;
|
|
|
|
lock(&_threadpq.lock);
|
|
for(l=&_threadpq.head; *l; l=&(*l)->next){
|
|
if(*l == p){
|
|
*l = p->next;
|
|
if(*l == nil)
|
|
_threadpq.tail = l;
|
|
break;
|
|
}
|
|
}
|
|
_threadprocs--;
|
|
unlock(&_threadpq.lock);
|
|
|
|
strncpy(ex, p->exitstr, sizeof ex);
|
|
ex[sizeof ex-1] = '\0';
|
|
free(p);
|
|
_exit(ex[0]);
|
|
}
|
|
|
|
int
|
|
nrand(int n)
|
|
{
|
|
return random()%n;
|
|
}
|
|
|
|
void
|
|
_systhreadinit(void)
|
|
{
|
|
}
|
|
|
|
void
|
|
threadstats(void)
|
|
{
|
|
extern int _threadnrendez, _threadhighnrendez,
|
|
_threadnalt, _threadhighnentry;
|
|
fprint(2, "*** THREAD LIBRARY STATS ***\n");
|
|
fprint(2, "nrendez %d high simultaneous %d\n",
|
|
_threadnrendez, _threadhighnrendez);
|
|
fprint(2, "nalt %d high simultaneous entry %d\n",
|
|
_threadnalt, _threadhighnentry);
|
|
}
|