main.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "threadimpl.h"
  5. typedef struct Mainarg Mainarg;
  6. struct Mainarg
  7. {
  8. int argc;
  9. char **argv;
  10. };
  11. int mainstacksize;
  12. int _threadnotefd;
  13. int _threadpasserpid;
  14. static jmp_buf _mainjmp;
  15. static void mainlauncher(void*);
  16. extern void (*_sysfatal)(char*, va_list);
  17. extern void (*__assert)(char*);
  18. static Proc **mainp;
  19. void
  20. main(int argc, char **argv)
  21. {
  22. Mainarg *a;
  23. Proc *p;
  24. rfork(RFREND);
  25. mainp = &p;
  26. if(setjmp(_mainjmp))
  27. _schedinit(p);
  28. //_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0;
  29. _systhreadinit();
  30. _qlockinit(_threadrendezvous);
  31. _sysfatal = _threadsysfatal;
  32. __assert = _threadassert;
  33. notify(_threadnote);
  34. if(mainstacksize == 0)
  35. mainstacksize = 8*1024;
  36. a = _threadmalloc(sizeof *a, 1);
  37. a->argc = argc;
  38. a->argv = argv;
  39. p = _newproc(mainlauncher, a, mainstacksize, "threadmain", 0, 0);
  40. _schedinit(p);
  41. abort(); /* not reached */
  42. }
  43. static void
  44. mainlauncher(void *arg)
  45. {
  46. Mainarg *a;
  47. a = arg;
  48. threadmain(a->argc, a->argv);
  49. threadexits("threadmain");
  50. }
  51. static char*
  52. skip(char *p)
  53. {
  54. while(*p == ' ')
  55. p++;
  56. while(*p != ' ' && *p != 0)
  57. p++;
  58. return p;
  59. }
  60. static long
  61. _times(long *t)
  62. {
  63. char b[200], *p;
  64. int f;
  65. ulong r;
  66. memset(b, 0, sizeof(b));
  67. f = open("/dev/cputime", OREAD|OCEXEC);
  68. if(f < 0)
  69. return 0;
  70. if(read(f, b, sizeof(b)) <= 0){
  71. close(f);
  72. return 0;
  73. }
  74. p = b;
  75. if(t)
  76. t[0] = atol(p);
  77. p = skip(p);
  78. if(t)
  79. t[1] = atol(p);
  80. p = skip(p);
  81. r = atol(p);
  82. if(t){
  83. p = skip(p);
  84. t[2] = atol(p);
  85. p = skip(p);
  86. t[3] = atol(p);
  87. }
  88. return r;
  89. }
  90. static void
  91. efork(Execargs *e)
  92. {
  93. char buf[ERRMAX];
  94. _threaddebug(DBGEXEC, "_schedexec %s", e->prog);
  95. close(e->fd[0]);
  96. exec(e->prog, e->args);
  97. _threaddebug(DBGEXEC, "_schedexec failed: %r");
  98. rerrstr(buf, sizeof buf);
  99. if(buf[0]=='\0')
  100. strcpy(buf, "exec failed");
  101. write(e->fd[1], buf, strlen(buf));
  102. close(e->fd[1]);
  103. _exits(buf);
  104. }
  105. int
  106. _schedexec(Execargs *e)
  107. {
  108. int pid;
  109. switch(pid = rfork(RFREND|RFNOTEG|RFFDG|RFMEM|RFPROC)){
  110. case 0:
  111. efork(e);
  112. default:
  113. return pid;
  114. }
  115. }
  116. int
  117. _schedfork(Proc *p)
  118. {
  119. int pid;
  120. switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT|p->rforkflag)){
  121. case 0:
  122. *mainp = p; /* write to stack, so local to proc */
  123. longjmp(_mainjmp, 1);
  124. default:
  125. return pid;
  126. }
  127. }
  128. void
  129. _schedexit(Proc *p)
  130. {
  131. char ex[ERRMAX];
  132. Proc **l;
  133. lock(&_threadpq.lock);
  134. for(l=&_threadpq.head; *l; l=&(*l)->next){
  135. if(*l == p){
  136. *l = p->next;
  137. if(*l == nil)
  138. _threadpq.tail = l;
  139. break;
  140. }
  141. }
  142. unlock(&_threadpq.lock);
  143. utfecpy(ex, ex+sizeof ex, p->exitstr);
  144. free(p);
  145. _exits(ex);
  146. }
  147. void
  148. _schedexecwait(void)
  149. {
  150. int pid;
  151. Channel *c;
  152. Proc *p;
  153. Thread *t;
  154. Waitmsg *w;
  155. p = _threadgetproc();
  156. t = p->thread;
  157. pid = t->ret;
  158. _threaddebug(DBGEXEC, "_schedexecwait %d", t->ret);
  159. rfork(RFCFDG);
  160. for(;;){
  161. w = wait();
  162. if(w == nil)
  163. break;
  164. if(w->pid == pid)
  165. break;
  166. free(w);
  167. }
  168. if(w != nil){
  169. if((c = _threadwaitchan) != nil)
  170. sendp(c, w);
  171. else
  172. free(w);
  173. }
  174. threadexits("procexec");
  175. }
  176. static Proc **procp;
  177. void
  178. _systhreadinit(void)
  179. {
  180. procp = privalloc();
  181. }
  182. Proc*
  183. _threadgetproc(void)
  184. {
  185. return *procp;
  186. }
  187. void
  188. _threadsetproc(Proc *p)
  189. {
  190. *procp = p;
  191. }