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 #if defined(__NetBSD__) && defined(__powerpc__) 126 { /* XXX: Work around a problem on macppc with kernel semaphores. */ 127 int val; 128 sem_getvalue(&os->sem, &val); 129 } 130 #endif 131 p->os = os; 132 133 if(flags & KPDUPPG) { 134 pg = up->env->pgrp; 135 incref(&pg->r); 136 p->env->pgrp = pg; 137 } 138 if(flags & KPDUPFDG) { 139 fg = up->env->fgrp; 140 incref(&fg->r); 141 p->env->fgrp = fg; 142 } 143 if(flags & KPDUPENVG) { 144 eg = up->env->egrp; 145 incref(&eg->r); 146 p->env->egrp = eg; 147 } 148 149 p->env->uid = up->env->uid; 150 p->env->gid = up->env->gid; 151 kstrdup(&p->env->user, up->env->user); 152 153 strcpy(p->text, name); 154 155 p->func = func; 156 p->arg = arg; 157 158 lock(&procs.l); 159 if(procs.tail != nil) { 160 p->prev = procs.tail; 161 procs.tail->next = p; 162 } else { 163 procs.head = p; 164 p->prev = nil; 165 } 166 procs.tail = p; 167 unlock(&procs.l); 168 169 memset(&attr, 0, sizeof(attr)); 170 if(pthread_attr_init(&attr) == -1) 171 panic("pthread_attr_init failed"); 172 if(flags & KPX11) 173 pthread_attr_setstacksize(&attr, 512*1024); /* could be a parameter */ 174 else if(KSTACK > 0) 175 pthread_attr_setstacksize(&attr, (KSTACK < PTHREAD_STACK_MIN? PTHREAD_STACK_MIN: KSTACK)+1024); 176 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); 177 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 178 if(pthread_create(&thread, &attr, tramp, p)) 179 panic("thr_create failed\n"); 180 pthread_attr_destroy(&attr); 181 } 182 183 /* called to wake up kproc blocked on a syscall */ 184 void 185 oshostintr(Proc *p) 186 { 187 Osdep *os; 188 189 os = p->os; 190 if(os != nil && os->self != 0) 191 pthread_kill(os->self, SIGUSR1); 192 } 193 194 void 195 osblock(void) 196 { 197 Osdep *os; 198 199 os = up->os; 200 while(sem_wait(&os->sem)) 201 {} /* retry on signals (which shouldn't happen) */ 202 } 203 204 void 205 osready(Proc *p) 206 { 207 Osdep *os; 208 209 os = p->os; 210 sem_post(&os->sem); 211 } 212 213 void 214 kprocinit(Proc *p) 215 { 216 if(pthread_key_create(&prdakey, NULL)) 217 panic("key_create failed"); 218 if(pthread_setspecific(prdakey, p)) 219 panic("set specific thread data failed"); 220 } 221 222 void 223 osyield(void) 224 { 225 // pthread_yield_np(); 226 /* define pthread_yield to be sched_yield or pthread_yield_np if required */ 227 pthread_yield(); 228 } 229 230 void 231 ospause(void) 232 { 233 /* main just wants this thread to go away */ 234 pthread_exit(0); 235 } 236 237 void 238 oslopri(void) 239 { 240 struct sched_param param; 241 int policy; 242 pthread_t self; 243 244 self = pthread_self(); 245 pthread_getschedparam(self, &policy, ¶m); 246 param.sched_priority = sched_get_priority_min(policy); 247 pthread_setschedparam(self, policy, ¶m); 248 } 249