1 #include <u.h> 2 #include <libc.h> 3 #include "compat.h" 4 #include "error.h" 5 6 #include "errstr.h" 7 8 ulong kerndate; 9 Proc **privup; 10 char *eve; 11 extern void *mainmem; 12 13 void 14 _assert(char *fmt) 15 { 16 panic("assert failed: %s", fmt); 17 } 18 19 int 20 errdepth(int ed) 21 { 22 if(ed >= 0 && up->nerrlab != ed) 23 panic("unbalanced error depth: expected %d got %d\n", ed, up->nerrlab); 24 return up->nerrlab; 25 } 26 27 void 28 newup(char *name) 29 { 30 up = smalloc(sizeof(Proc)); 31 up->user = eve; 32 strncpy(up->name, name, KNAMELEN-1); 33 up->name[KNAMELEN-1] = '\0'; 34 } 35 36 void 37 kproc(char *name, void (*f)(void *), void *a) 38 { 39 int pid; 40 41 pid = rfork(RFPROC|RFMEM|RFNOWAIT); 42 switch(pid){ 43 case -1: 44 panic("can't make new thread: %r"); 45 case 0: 46 break; 47 default: 48 return; 49 } 50 51 newup(name); 52 if(!waserror()) 53 (*f)(a); 54 _exits(nil); 55 } 56 57 void 58 kexit(void) 59 { 60 _exits(nil); 61 } 62 63 void 64 initcompat(void) 65 { 66 rfork(RFREND); 67 privup = privalloc(); 68 kerndate = seconds(); 69 eve = getuser(); 70 newup("main"); 71 } 72 73 int 74 openmode(ulong o) 75 { 76 o &= ~(OTRUNC|OCEXEC|ORCLOSE); 77 if(o > OEXEC) 78 error(Ebadarg); 79 if(o == OEXEC) 80 return OREAD; 81 return o; 82 } 83 84 void 85 panic(char *fmt, ...) 86 { 87 char buf[512]; 88 char buf2[512]; 89 va_list va; 90 91 va_start(va, fmt); 92 vseprint(buf, buf+sizeof(buf), fmt, va); 93 va_end(va); 94 sprint(buf2, "panic: %s\n", buf); 95 write(2, buf2, strlen(buf2)); 96 97 exits("error"); 98 } 99 100 void* 101 smalloc(ulong n) 102 { 103 void *p; 104 105 p = mallocz(n, 1); 106 if(p == nil) 107 panic("out of memory"); 108 setmalloctag(p, getcallerpc(&n)); 109 return p; 110 } 111 112 long 113 seconds(void) 114 { 115 return time(nil); 116 } 117 118 void 119 error(char *err) 120 { 121 strncpy(up->error, err, ERRMAX); 122 nexterror(); 123 } 124 125 void 126 nexterror(void) 127 { 128 longjmp(up->errlab[--up->nerrlab], 1); 129 } 130 131 int 132 readstr(ulong off, char *buf, ulong n, char *str) 133 { 134 int size; 135 136 size = strlen(str); 137 if(off >= size) 138 return 0; 139 if(off+n > size) 140 n = size-off; 141 memmove(buf, str+off, n); 142 return n; 143 } 144 145 void 146 _rendsleep(void* tag) 147 { 148 void *value; 149 150 for(;;){ 151 value = rendezvous(tag, (void*)0x22a891b8); 152 if(value == (void*)0x7f7713f9) 153 break; 154 if(tag != (void*)~0) 155 panic("_rendsleep: rendezvous mismatch"); 156 } 157 } 158 159 void 160 _rendwakeup(void* tag) 161 { 162 void *value; 163 164 for(;;){ 165 value = rendezvous(tag, (void*)0x7f7713f9); 166 if(value == (void*)0x22a891b8) 167 break; 168 if(tag != (void*)~0) 169 panic("_rendwakeup: rendezvous mismatch"); 170 } 171 } 172 173 void 174 rendsleep(Rendez *r, int (*f)(void*), void *arg) 175 { 176 lock(&up->rlock); 177 up->r = r; 178 unlock(&up->rlock); 179 180 lock(r); 181 182 /* 183 * if condition happened, never mind 184 */ 185 if(up->intr || f(arg)){ 186 unlock(r); 187 goto Done; 188 } 189 190 /* 191 * now we are committed to 192 * change state and call scheduler 193 */ 194 if(r->p) 195 panic("double sleep"); 196 r->p = up; 197 unlock(r); 198 199 _rendsleep(r); 200 201 Done: 202 lock(&up->rlock); 203 up->r = 0; 204 if(up->intr){ 205 up->intr = 0; 206 unlock(&up->rlock); 207 error(Eintr); 208 } 209 unlock(&up->rlock); 210 } 211 212 int 213 rendwakeup(Rendez *r) 214 { 215 Proc *p; 216 int rv; 217 218 lock(r); 219 p = r->p; 220 rv = 0; 221 if(p){ 222 r->p = nil; 223 _rendwakeup(r); 224 rv = 1; 225 } 226 unlock(r); 227 return rv; 228 } 229 230 void 231 rendintr(void *v) 232 { 233 Proc *p; 234 235 p = v; 236 lock(&p->rlock); 237 p->intr = 1; 238 if(p->r) 239 rendwakeup(p->r); 240 unlock(&p->rlock); 241 } 242 243 void 244 rendclearintr(void) 245 { 246 lock(&up->rlock); 247 up->intr = 0; 248 unlock(&up->rlock); 249 } 250 251