compat.c 3.7 KB

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