diff options
| author | forsyth <forsyth@vitanuova.com> | 2011-03-01 19:41:41 +0000 |
|---|---|---|
| committer | forsyth <forsyth@vitanuova.com> | 2011-03-01 19:41:41 +0000 |
| commit | ad7bc8852304a9b4b633bbaffed1f51e4aa9f6bd (patch) | |
| tree | afcdd2439f4d4a09bcd10a1fa477504aafe4c138 /emu/port/kproc-pthreads.c | |
| parent | 1c3105e30dd923f3be624169a5343e472302f15e (diff) | |
20110301-1941
Diffstat (limited to 'emu/port/kproc-pthreads.c')
| -rw-r--r-- | emu/port/kproc-pthreads.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/emu/port/kproc-pthreads.c b/emu/port/kproc-pthreads.c new file mode 100644 index 00000000..b48a00bb --- /dev/null +++ b/emu/port/kproc-pthreads.c @@ -0,0 +1,226 @@ +#include "dat.h" +#include "fns.h" +#include "error.h" + +#undef _POSIX_C_SOURCE +#undef getwd + +#include <unistd.h> +#include <signal.h> +#include <pthread.h> +#include <errno.h> +#include <semaphore.h> + +typedef struct Osdep Osdep; +struct Osdep { + sem_t sem; + pthread_t self; +}; + +static pthread_key_t prdakey; + +extern int dflag; + +Proc* +getup(void) +{ + return pthread_getspecific(prdakey); +} + +void +pexit(char *msg, int t) +{ + Osenv *e; + Proc *p; + Osdep *os; + + USED(t); + + lock(&procs.l); + p = up; + if(p->prev) + p->prev->next = p->next; + else + procs.head = p->next; + + if(p->next) + p->next->prev = p->prev; + else + procs.tail = p->prev; + unlock(&procs.l); + + if(0) + print("pexit: %s: %s\n", p->text, msg); + + e = p->env; + if(e != nil) { + closefgrp(e->fgrp); + closepgrp(e->pgrp); + closeegrp(e->egrp); + closesigs(e->sigs); + free(e->user); + } + free(p->prog); + os = p->os; + if(os != nil){ + sem_destroy(&os->sem); + free(os); + } + free(p); + pthread_exit(0); +} + +static void* +tramp(void *arg) +{ + Proc *p; + Osdep *os; + + p = arg; + os = p->os; + os->self = pthread_self(); + if(pthread_setspecific(prdakey, arg)) + panic("set specific data failed in tramp\n"); + p->func(p->arg); + pexit("{Tramp}", 0); + return nil; +} + +void +kproc(char *name, void (*func)(void*), void *arg, int flags) +{ + pthread_t thread; + Proc *p; + Pgrp *pg; + Fgrp *fg; + Egrp *eg; + pthread_attr_t attr; + Osdep *os; + + p = newproc(); + if(p == nil) + panic("kproc: no memory"); + + os = malloc(sizeof(*os)); + if(os == nil) + panic("kproc: no memory"); + os->self = 0; /* set by tramp */ + sem_init(&os->sem, 0, 0); + p->os = os; + + if(flags & KPDUPPG) { + pg = up->env->pgrp; + incref(&pg->r); + p->env->pgrp = pg; + } + if(flags & KPDUPFDG) { + fg = up->env->fgrp; + incref(&fg->r); + p->env->fgrp = fg; + } + if(flags & KPDUPENVG) { + eg = up->env->egrp; + incref(&eg->r); + p->env->egrp = eg; + } + + p->env->uid = up->env->uid; + p->env->gid = up->env->gid; + kstrdup(&p->env->user, up->env->user); + + strcpy(p->text, name); + + p->func = func; + p->arg = arg; + + lock(&procs.l); + if(procs.tail != nil) { + p->prev = procs.tail; + procs.tail->next = p; + } else { + procs.head = p; + p->prev = nil; + } + procs.tail = p; + unlock(&procs.l); + + memset(&attr, 0, sizeof(attr)); + if(pthread_attr_init(&attr) == -1) + panic("pthread_attr_init failed"); + if(flags & KPX11) + pthread_attr_setstacksize(&attr, 512*1024); /* could be a parameter */ + else if(KSTACK > 0) + pthread_attr_setstacksize(&attr, KSTACK); + pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if(pthread_create(&thread, &attr, tramp, p)) + panic("thr_create failed\n"); + pthread_attr_destroy(&attr); +} + +/* called to wake up kproc blocked on a syscall */ +void +oshostintr(Proc *p) +{ + Osdep *os; + + os = p->os; + if(os != nil && os->self != 0) + pthread_kill(os->self, SIGUSR1); +} + +void +osblock(void) +{ + Osdep *os; + + os = up->os; + while(sem_wait(&os->sem)) + {} /* retry on signals (which shouldn't happen) */ +} + +void +osready(Proc *p) +{ + Osdep *os; + + os = p->os; + sem_post(&os->sem); +} + +void +kprocinit(Proc *p) +{ + if(pthread_key_create(&prdakey, NULL)) + panic("key_create failed"); + if(pthread_setspecific(prdakey, p)) + panic("set specific thread data failed"); +} + +void +osyield(void) +{ +// pthread_yield_np(); + /* define pthread_yield to be sched_yield or pthread_yield_np if required */ + pthread_yield(); +} + +void +ospause(void) +{ + /* main just wants this thread to go away */ + pthread_exit(0); +} + +void +oslopri(void) +{ + struct sched_param param; + int policy; + pthread_t self; + + self = pthread_self(); + pthread_getschedparam(self, &policy, ¶m); + param.sched_priority = sched_get_priority_min(policy); + pthread_setschedparam(self, policy, ¶m); +} |
