main.c 3.2 KB

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