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