1 #include "dat.h" 2 #include "fns.h" 3 #include "error.h" 4 5 #undef _POSIX_C_SOURCE 6 #undef getwd 7 8 #include <unistd.h> 9 #include <signal.h> 10 #include <pthread.h> 11 #include <limits.h> 12 #include <errno.h> 13 #include <semaphore.h> 14 15 #ifdef __NetBSD__ 16 #include <sched.h> 17 #define pthread_yield() (sched_yield()) 18 #define PTHREAD_STACK_MIN ((size_t)sysconf(_SC_THREAD_STACK_MIN)) 19 #endif 20 21 22 typedef struct Osdep Osdep; 23 struct Osdep { 24 sem_t sem; 25 pthread_t self; 26 }; 27 28 static pthread_key_t prdakey; 29 30 extern int dflag; 31 32 Proc* 33 getup(void) 34 { 35 return pthread_getspecific(prdakey); 36 } 37 38 void 39 pexit(char *msg, int t) 40 { 41 Osenv *e; 42 Proc *p; 43 Osdep *os; 44 45 USED(t); 46 47 lock(&procs.l); 48 p = up; 49 if(p->prev) 50 p->prev->next = p->next; 51 else 52 procs.head = p->next; 53 54 if(p->next) 55 p->next->prev = p->prev; 56 else 57 procs.tail = p->prev; 58 unlock(&procs.l); 59 60 if(0) 61 print("pexit: %s: %s\n", p->text, msg); 62 63 e = p->env; 64 if(e != nil) { 65 closefgrp(e->fgrp); 66 closepgrp(e->pgrp); 67 closeegrp(e->egrp); 68 closesigs(e->sigs); 69 free(e->user); 70 } 71 free(p->prog); 72 os = p->os; 73 if(os != nil){ 74 sem_destroy(&os->sem); 75 free(os); 76 } 77 free(p); 78 pthread_exit(0); 79 } 80 81 static void* 82 tramp(void *arg) 83 { 84 Proc *p; 85 Osdep *os; 86 87 p = arg; 88 os = p->os; 89 os->self = pthread_self(); 90 if(pthread_setspecific(prdakey, arg)) 91 panic("set specific data failed in tramp\n"); 92 if(0){ 93 pthread_attr_t attr; 94 memset(&attr, 0, sizeof(attr)); 95 pthread_getattr_np(pthread_self(), &attr); 96 size_t s; 97 pthread_attr_getstacksize(&attr, &s); 98 print("stack size = %d\n", s); 99 } 100 p->func(p->arg); 101 pexit("{Tramp}", 0); 102 return nil; 103 } 104 105 void 106 kproc(char *name, void (*func)(void*), void *arg, int flags) 107 { 108 pthread_t thread; 109 Proc *p; 110 Pgrp *pg; 111 Fgrp *fg; 112 Egrp *eg; 113 pthread_attr_t attr; 114 Osdep *os; 115 116 p = newproc(); 117 if(p == nil) 118 panic("kproc: no memory"); 119 120 os = malloc(sizeof(*os)); 121 if(os == nil) 122 panic("kproc: no memory"); 123 os->self = 0; /* set by tramp */ 124 sem_init(&os->sem, 0, 0); 125 p->os = os; 126 127 if(flags & KPDUPPG) { 128 pg = up->env->pgrp; 129 incref(&pg->r); 130 p->env->pgrp = pg; 131 } 132 if(flags & KPDUPFDG) { 133 fg = up->env->fgrp; 134 incref(&fg->r); 135 p->env->fgrp = fg; 136 } 137 if(flags & KPDUPENVG) { 138 eg = up->env->egrp; 139 incref(&eg->r); 140 p->env->egrp = eg; 141 } 142 143 p->env->uid = up->env->uid; 144 p->env->gid = up->env->gid; 145 kstrdup(&p->env->user, up->env->user); 146 147 strcpy(p->text, name); 148 149 p->func = func; 150 p->arg = arg; 151 152 lock(&procs.l); 153 if(procs.tail != nil) { 154 p->prev = procs.tail; 155 procs.tail->next = p; 156 } else { 157 procs.head = p; 158 p->prev = nil; 159 } 160 procs.tail = p; 161 unlock(&procs.l); 162 163 memset(&attr, 0, sizeof(attr)); 164 if(pthread_attr_init(&attr) == -1) 165 panic("pthread_attr_init failed"); 166 if(flags & KPX11) 167 pthread_attr_setstacksize(&attr, 512*1024); /* could be a parameter */ 168 else if(KSTACK > 0) 169 pthread_attr_setstacksize(&attr, (KSTACK < PTHREAD_STACK_MIN? PTHREAD_STACK_MIN: KSTACK)+1024); 170 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); 171 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 172 if(pthread_create(&thread, &attr, tramp, p)) 173 panic("thr_create failed\n"); 174 pthread_attr_destroy(&attr); 175 } 176 177 /* called to wake up kproc blocked on a syscall */ 178 void 179 oshostintr(Proc *p) 180 { 181 Osdep *os; 182 183 os = p->os; 184 if(os != nil && os->self != 0) 185 pthread_kill(os->self, SIGUSR1); 186 } 187 188 void 189 osblock(void) 190 { 191 Osdep *os; 192 193 os = up->os; 194 while(sem_wait(&os->sem)) 195 {} /* retry on signals (which shouldn't happen) */ 196 } 197 198 void 199 osready(Proc *p) 200 { 201 Osdep *os; 202 203 os = p->os; 204 sem_post(&os->sem); 205 } 206 207 void 208 kprocinit(Proc *p) 209 { 210 if(pthread_key_create(&prdakey, NULL)) 211 panic("key_create failed"); 212 if(pthread_setspecific(prdakey, p)) 213 panic("set specific thread data failed"); 214 } 215 216 void 217 osyield(void) 218 { 219 // pthread_yield_np(); 220 /* define pthread_yield to be sched_yield or pthread_yield_np if required */ 221 pthread_yield(); 222 } 223 224 void 225 ospause(void) 226 { 227 /* main just wants this thread to go away */ 228 pthread_exit(0); 229 } 230 231 void 232 oslopri(void) 233 { 234 struct sched_param param; 235 int policy; 236 pthread_t self; 237 238 self = pthread_self(); 239 pthread_getschedparam(self, &policy, ¶m); 240 param.sched_priority = sched_get_priority_min(policy); 241 pthread_setschedparam(self, policy, ¶m); 242 } 243