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