0000: 2f 2a 20 43 6f 70 79 72 69 67 68 74 20 28 63 29 /* Copyright (c)
0010: 20 32 30 30 35 20 52 75 73 73 20 43 6f 78 2c 20 2005 Russ Cox,
0020: 4d 49 54 3b 20 73 65 65 20 43 4f 50 59 52 49 47 MIT; see COPYRIG
0030: 48 54 20 2a 2f 0a 0a 23 69 6e 63 6c 75 64 65 20 HT */..#include
0040: 22 74 61 73 6b 69 6d 70 6c 2e 68 22 0a 23 69 6e "taskimpl.h".#in
0050: 63 6c 75 64 65 20 3c 66 63 6e 74 6c 2e 68 3e 0a clude <fcntl.h>.
0060: 0a 74 79 70 65 64 65 66 20 73 74 72 75 63 74 20 .typedef struct
0070: 54 61 73 6b 6c 69 73 74 20 54 61 73 6b 6c 69 73 Tasklist Tasklis
0080: 74 3b 0a 73 74 72 75 63 74 20 54 61 73 6b 6c 69 t;.struct Taskli
0090: 73 74 0a 7b 0a 09 54 61 73 6b 20 2a 68 65 61 64 st.{..Task *head
00a0: 3b 0a 09 54 61 73 6b 20 2a 74 61 69 6c 3b 0a 7d ;..Task *tail;.}
00b0: 3b 0a 0a 69 6e 74 09 74 61 73 6b 64 65 62 75 67 ;..int.taskdebug
00c0: 6c 65 76 65 6c 3b 0a 69 6e 74 09 74 61 73 6b 63 level;.int.taskc
00d0: 6f 75 6e 74 3b 0a 69 6e 74 09 74 61 73 6b 6e 73 ount;.int.taskns
00e0: 77 69 74 63 68 3b 0a 69 6e 74 09 74 61 73 6b 65 witch;.int.taske
00f0: 78 69 74 76 61 6c 3b 0a 54 61 73 6b 09 2a 74 61 xitval;.Task.*ta
0100: 73 6b 72 75 6e 6e 69 6e 67 3b 0a 0a 43 6f 6e 74 skrunning;..Cont
0110: 65 78 74 09 74 61 73 6b 73 63 68 65 64 63 6f 6e ext.taskschedcon
0120: 74 65 78 74 3b 0a 54 61 73 6b 6c 69 73 74 09 74 text;.Tasklist.t
0130: 61 73 6b 72 75 6e 71 75 65 75 65 3b 0a 0a 73 74 askrunqueue;..st
0140: 61 74 69 63 20 63 68 61 72 20 2a 61 72 67 76 30 atic char *argv0
0150: 3b 0a 73 74 61 74 69 63 09 76 6f 69 64 09 09 61 ;.static.void..a
0160: 64 64 74 61 73 6b 28 54 61 73 6b 6c 69 73 74 2a ddtask(Tasklist*
0170: 2c 20 54 61 73 6b 2a 29 3b 0a 73 74 61 74 69 63 , Task*);.static
0180: 09 76 6f 69 64 09 09 64 65 6c 74 61 73 6b 28 54 .void..deltask(T
0190: 61 73 6b 6c 69 73 74 2a 2c 20 54 61 73 6b 2a 29 asklist*, Task*)
01a0: 3b 0a 73 74 61 74 69 63 09 76 6f 69 64 09 09 63 ;.static.void..c
01b0: 6f 6e 74 65 78 74 73 77 69 74 63 68 28 43 6f 6e ontextswitch(Con
01c0: 74 65 78 74 20 2a 66 72 6f 6d 2c 20 43 6f 6e 74 text *from, Cont
01d0: 65 78 74 20 2a 74 6f 29 3b 0a 0a 73 74 61 74 69 ext *to);..stati
01e0: 63 20 76 6f 69 64 0a 74 61 73 6b 64 65 62 75 67 c void.taskdebug
01f0: 28 63 68 61 72 20 2a 66 6d 74 2c 20 2e 2e 2e 29 (char *fmt, ...)
0200: 0a 7b 0a 09 76 61 5f 6c 69 73 74 20 61 72 67 3b .{..va_list arg;
0210: 0a 09 63 68 61 72 20 62 75 66 5b 31 32 38 5d 3b ..char buf[128];
0220: 0a 09 54 61 73 6b 20 2a 74 3b 0a 09 63 68 61 72 ..Task *t;..char
0230: 20 2a 70 3b 0a 09 73 74 61 74 69 63 20 69 6e 74 *p;..static int
0240: 20 66 64 20 3d 20 2d 31 3b 0a 0a 72 65 74 75 72 fd = -1;..retur
0250: 6e 3b 0a 09 76 61 5f 73 74 61 72 74 28 61 72 67 n;..va_start(arg
0260: 2c 20 66 6d 74 29 3b 0a 09 76 66 70 72 69 6e 74 , fmt);..vfprint
0270: 28 31 2c 20 66 6d 74 2c 20 61 72 67 29 3b 0a 09 (1, fmt, arg);..
0280: 76 61 5f 65 6e 64 28 61 72 67 29 3b 0a 72 65 74 va_end(arg);.ret
0290: 75 72 6e 3b 0a 0a 09 69 66 28 66 64 20 3c 20 30 urn;...if(fd < 0
02a0: 29 7b 0a 09 09 70 20 3d 20 73 74 72 72 63 68 72 ){...p = strrchr
02b0: 28 61 72 67 76 30 2c 20 27 2f 27 29 3b 0a 09 09 (argv0, '/');...
02c0: 69 66 28 70 29 0a 09 09 09 70 2b 2b 3b 0a 09 09 if(p)....p++;...
02d0: 65 6c 73 65 0a 09 09 09 70 20 3d 20 61 72 67 76 else....p = argv
02e0: 30 3b 0a 09 09 73 6e 70 72 69 6e 74 28 62 75 66 0;...snprint(buf
02f0: 2c 20 73 69 7a 65 6f 66 20 62 75 66 2c 20 22 2f , sizeof buf, "/
0300: 74 6d 70 2f 25 73 2e 74 6c 6f 67 22 2c 20 70 29 tmp/%s.tlog", p)
0310: 3b 0a 09 09 69 66 28 28 66 64 20 3d 20 6f 70 65 ;...if((fd = ope
0320: 6e 28 62 75 66 2c 20 4f 5f 43 52 45 41 54 7c 4f n(buf, O_CREAT|O
0330: 5f 57 52 4f 4e 4c 59 2c 20 30 36 36 36 29 29 20 _WRONLY, 0666))
0340: 3c 20 30 29 0a 09 09 09 66 64 20 3d 20 6f 70 65 < 0)....fd = ope
0350: 6e 28 22 2f 64 65 76 2f 6e 75 6c 6c 22 2c 20 4f n("/dev/null", O
0360: 5f 57 52 4f 4e 4c 59 29 3b 0a 09 7d 0a 0a 09 76 _WRONLY);..}...v
0370: 61 5f 73 74 61 72 74 28 61 72 67 2c 20 66 6d 74 a_start(arg, fmt
0380: 29 3b 0a 09 76 73 6e 70 72 69 6e 74 28 62 75 66 );..vsnprint(buf
0390: 2c 20 73 69 7a 65 6f 66 20 62 75 66 2c 20 66 6d , sizeof buf, fm
03a0: 74 2c 20 61 72 67 29 3b 0a 09 76 61 5f 65 6e 64 t, arg);..va_end
03b0: 28 61 72 67 29 3b 0a 09 74 20 3d 20 74 61 73 6b (arg);..t = task
03c0: 72 75 6e 6e 69 6e 67 3b 0a 09 69 66 28 74 29 0a running;..if(t).
03d0: 09 09 66 70 72 69 6e 74 28 66 64 2c 20 22 25 64 ..fprint(fd, "%d
03e0: 2e 25 64 3a 20 25 73 5c 6e 22 2c 20 67 65 74 70 .%d: %s\n", getp
03f0: 69 64 28 29 2c 20 74 2d 3e 69 64 2c 20 62 75 66 id(), t->id, buf
0400: 29 3b 0a 09 65 6c 73 65 0a 09 09 66 70 72 69 6e );..else...fprin
0410: 74 28 66 64 2c 20 22 25 64 2e 5f 3a 20 25 73 5c t(fd, "%d._: %s\
0420: 6e 22 2c 20 67 65 74 70 69 64 28 29 2c 20 62 75 n", getpid(), bu
0430: 66 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f f);.}..static vo
0440: 69 64 0a 74 61 73 6b 73 74 61 72 74 28 75 69 6e id.taskstart(uin
0450: 74 20 79 2c 20 75 69 6e 74 20 78 29 0a 7b 0a 09 t y, uint x).{..
0460: 54 61 73 6b 20 2a 74 3b 0a 09 75 6c 6f 6e 67 20 Task *t;..ulong
0470: 7a 3b 0a 0a 09 7a 20 3d 20 78 3c 3c 31 36 3b 09 z;...z = x<<16;.
0480: 2f 2a 20 68 69 64 65 20 75 6e 64 65 66 69 6e 65 /* hide undefine
0490: 64 20 33 32 2d 62 69 74 20 73 68 69 66 74 20 66 d 32-bit shift f
04a0: 72 6f 6d 20 33 32 2d 62 69 74 20 63 6f 6d 70 69 rom 32-bit compi
04b0: 6c 65 72 73 20 2a 2f 0a 09 7a 20 3c 3c 3d 20 31 lers */..z <<= 1
04c0: 36 3b 0a 09 7a 20 7c 3d 20 79 3b 0a 09 74 20 3d 6;..z |= y;..t =
04d0: 20 28 54 61 73 6b 2a 29 7a 3b 0a 0a 2f 2f 70 72 (Task*)z;..//pr
04e0: 69 6e 74 28 22 74 61 73 6b 73 74 61 72 74 20 25 int("taskstart %
04f0: 70 5c 6e 22 2c 20 76 29 3b 0a 09 74 2d 3e 73 74 p\n", v);..t->st
0500: 61 72 74 66 6e 28 74 2d 3e 73 74 61 72 74 61 72 artfn(t->startar
0510: 67 29 3b 0a 2f 2f 70 72 69 6e 74 28 22 74 61 73 g);.//print("tas
0520: 6b 65 78 69 74 73 20 25 70 5c 6e 22 2c 20 76 29 kexits %p\n", v)
0530: 3b 0a 09 74 61 73 6b 65 78 69 74 28 30 29 3b 0a ;..taskexit(0);.
0540: 2f 2f 70 72 69 6e 74 28 22 6e 6f 74 20 72 65 61 //print("not rea
0550: 63 65 68 64 5c 6e 22 29 3b 0a 7d 0a 0a 73 74 61 cehd\n");.}..sta
0560: 74 69 63 20 69 6e 74 20 74 61 73 6b 69 64 67 65 tic int taskidge
0570: 6e 3b 0a 0a 73 74 61 74 69 63 20 54 61 73 6b 2a n;..static Task*
0580: 0a 74 61 73 6b 61 6c 6c 6f 63 28 76 6f 69 64 20 .taskalloc(void
0590: 28 2a 66 6e 29 28 76 6f 69 64 2a 29 2c 20 76 6f (*fn)(void*), vo
05a0: 69 64 20 2a 61 72 67 2c 20 75 69 6e 74 20 73 74 id *arg, uint st
05b0: 61 63 6b 29 0a 7b 0a 09 54 61 73 6b 20 2a 74 3b ack).{..Task *t;
05c0: 0a 09 73 69 67 73 65 74 5f 74 20 7a 65 72 6f 3b ..sigset_t zero;
05d0: 0a 09 75 69 6e 74 20 78 2c 20 79 3b 0a 09 75 6c ..uint x, y;..ul
05e0: 6f 6e 67 20 7a 3b 0a 0a 09 2f 2a 20 61 6c 6c 6f ong z;.../* allo
05f0: 63 61 74 65 20 74 68 65 20 74 61 73 6b 20 61 6e cate the task an
0600: 64 20 73 74 61 63 6b 20 74 6f 67 65 74 68 65 72 d stack together
0610: 20 2a 2f 0a 09 74 20 3d 20 6d 61 6c 6c 6f 63 28 */..t = malloc(
0620: 73 69 7a 65 6f 66 20 2a 74 2b 73 74 61 63 6b 29 sizeof *t+stack)
0630: 3b 0a 09 69 66 28 74 20 3d 3d 20 6e 69 6c 29 7b ;..if(t == nil){
0640: 0a 09 09 66 70 72 69 6e 74 28 32 2c 20 22 74 61 ...fprint(2, "ta
0650: 73 6b 61 6c 6c 6f 63 20 6d 61 6c 6c 6f 63 3a 20 skalloc malloc:
0660: 25 72 5c 6e 22 29 3b 0a 09 09 61 62 6f 72 74 28 %r\n");...abort(
0670: 29 3b 0a 09 7d 0a 09 6d 65 6d 73 65 74 28 74 2c );..}..memset(t,
0680: 20 30 2c 20 73 69 7a 65 6f 66 20 2a 74 29 3b 0a 0, sizeof *t);.
0690: 09 74 2d 3e 73 74 6b 20 3d 20 28 75 63 68 61 72 .t->stk = (uchar
06a0: 2a 29 28 74 2b 31 29 3b 0a 09 74 2d 3e 73 74 6b *)(t+1);..t->stk
06b0: 73 69 7a 65 20 3d 20 73 74 61 63 6b 3b 0a 09 74 size = stack;..t
06c0: 2d 3e 69 64 20 3d 20 2b 2b 74 61 73 6b 69 64 67 ->id = ++taskidg
06d0: 65 6e 3b 0a 09 74 2d 3e 73 74 61 72 74 66 6e 20 en;..t->startfn
06e0: 3d 20 66 6e 3b 0a 09 74 2d 3e 73 74 61 72 74 61 = fn;..t->starta
06f0: 72 67 20 3d 20 61 72 67 3b 0a 0a 09 2f 2a 20 64 rg = arg;.../* d
0700: 6f 20 61 20 72 65 61 73 6f 6e 61 62 6c 65 20 69 o a reasonable i
0710: 6e 69 74 69 61 6c 69 7a 61 74 69 6f 6e 20 2a 2f nitialization */
0720: 0a 09 6d 65 6d 73 65 74 28 26 74 2d 3e 63 6f 6e ..memset(&t->con
0730: 74 65 78 74 2e 75 63 2c 20 30 2c 20 73 69 7a 65 text.uc, 0, size
0740: 6f 66 20 74 2d 3e 63 6f 6e 74 65 78 74 2e 75 63 of t->context.uc
0750: 29 3b 0a 09 73 69 67 65 6d 70 74 79 73 65 74 28 );..sigemptyset(
0760: 26 7a 65 72 6f 29 3b 0a 09 73 69 67 70 72 6f 63 &zero);..sigproc
0770: 6d 61 73 6b 28 53 49 47 5f 42 4c 4f 43 4b 2c 20 mask(SIG_BLOCK,
0780: 26 7a 65 72 6f 2c 20 26 74 2d 3e 63 6f 6e 74 65 &zero, &t->conte
0790: 78 74 2e 75 63 2e 75 63 5f 73 69 67 6d 61 73 6b xt.uc.uc_sigmask
07a0: 29 3b 0a 0a 09 2f 2a 20 6d 75 73 74 20 69 6e 69 );.../* must ini
07b0: 74 69 61 6c 69 7a 65 20 77 69 74 68 20 63 75 72 tialize with cur
07c0: 72 65 6e 74 20 63 6f 6e 74 65 78 74 20 2a 2f 0a rent context */.
07d0: 09 69 66 28 67 65 74 63 6f 6e 74 65 78 74 28 26 .if(getcontext(&
07e0: 74 2d 3e 63 6f 6e 74 65 78 74 2e 75 63 29 20 3c t->context.uc) <
07f0: 20 30 29 7b 0a 09 09 66 70 72 69 6e 74 28 32 2c 0){...fprint(2,
0800: 20 22 67 65 74 63 6f 6e 74 65 78 74 3a 20 25 72 "getcontext: %r
0810: 5c 6e 22 29 3b 0a 09 09 61 62 6f 72 74 28 29 3b \n");...abort();
0820: 0a 09 7d 0a 0a 09 2f 2a 20 63 61 6c 6c 20 6d 61 ..}.../* call ma
0830: 6b 65 63 6f 6e 74 65 78 74 20 74 6f 20 64 6f 20 kecontext to do
0840: 74 68 65 20 72 65 61 6c 20 77 6f 72 6b 2e 20 2a the real work. *
0850: 2f 0a 09 2f 2a 20 6c 65 61 76 65 20 61 20 66 65 /../* leave a fe
0860: 77 20 77 6f 72 64 73 20 6f 70 65 6e 20 6f 6e 20 w words open on
0870: 62 6f 74 68 20 65 6e 64 73 20 2a 2f 0a 09 74 2d both ends */..t-
0880: 3e 63 6f 6e 74 65 78 74 2e 75 63 2e 75 63 5f 73 >context.uc.uc_s
0890: 74 61 63 6b 2e 73 73 5f 73 70 20 3d 20 74 2d 3e tack.ss_sp = t->
08a0: 73 74 6b 2b 38 3b 0a 09 74 2d 3e 63 6f 6e 74 65 stk+8;..t->conte
08b0: 78 74 2e 75 63 2e 75 63 5f 73 74 61 63 6b 2e 73 xt.uc.uc_stack.s
08c0: 73 5f 73 69 7a 65 20 3d 20 74 2d 3e 73 74 6b 73 s_size = t->stks
08d0: 69 7a 65 2d 36 34 3b 0a 23 69 66 64 65 66 20 5f ize-64;.#ifdef _
08e0: 5f 73 75 6e 5f 5f 09 09 2f 2a 20 73 69 67 68 20 _sun__../* sigh
08f0: 2a 2f 0a 09 2f 2a 20 63 61 6e 20 61 76 6f 69 64 */../* can avoid
0900: 20 74 68 69 73 20 77 69 74 68 20 5f 5f 4d 41 4b this with __MAK
0910: 45 43 4f 4e 54 45 58 54 5f 56 32 5f 53 4f 55 52 ECONTEXT_V2_SOUR
0920: 43 45 20 62 75 74 20 6f 6e 6c 79 20 6f 6e 20 53 CE but only on S
0930: 75 6e 4f 53 20 35 2e 39 20 2a 2f 0a 09 74 2d 3e unOS 5.9 */..t->
0940: 63 6f 6e 74 65 78 74 2e 75 63 2e 75 63 5f 73 74 context.uc.uc_st
0950: 61 63 6b 2e 73 73 5f 73 70 20 3d 20 0a 09 09 28 ack.ss_sp = ...(
0960: 63 68 61 72 2a 29 74 2d 3e 63 6f 6e 74 65 78 74 char*)t->context
0970: 2e 75 63 2e 75 63 5f 73 74 61 63 6b 2e 73 73 5f .uc.uc_stack.ss_
0980: 73 70 0a 09 09 2b 74 2d 3e 63 6f 6e 74 65 78 74 sp...+t->context
0990: 2e 75 63 2e 75 63 5f 73 74 61 63 6b 2e 73 73 5f .uc.uc_stack.ss_
09a0: 73 69 7a 65 3b 0a 23 65 6e 64 69 66 0a 09 2f 2a size;.#endif../*
09b0: 0a 09 20 2a 20 41 6c 6c 20 74 68 69 73 20 6d 61 .. * All this ma
09c0: 67 69 63 20 69 73 20 62 65 63 61 75 73 65 20 79 gic is because y
09d0: 6f 75 20 68 61 76 65 20 74 6f 20 70 61 73 73 20 ou have to pass
09e0: 6d 61 6b 65 63 6f 6e 74 65 78 74 20 61 0a 09 20 makecontext a..
09f0: 2a 20 66 75 6e 63 74 69 6f 6e 20 74 68 61 74 20 * function that
0a00: 74 61 6b 65 73 20 73 6f 6d 65 20 6e 75 6d 62 65 takes some numbe
0a10: 72 20 6f 66 20 77 6f 72 64 2d 73 69 7a 65 64 20 r of word-sized
0a20: 76 61 72 69 61 62 6c 65 73 2c 0a 09 20 2a 20 61 variables,.. * a
0a30: 6e 64 20 6f 6e 20 36 34 2d 62 69 74 20 6d 61 63 nd on 64-bit mac
0a40: 68 69 6e 65 73 20 70 6f 69 6e 74 65 72 73 20 61 hines pointers a
0a50: 72 65 20 62 69 67 67 65 72 20 74 68 61 6e 20 77 re bigger than w
0a60: 6f 72 64 73 2e 0a 09 20 2a 2f 0a 09 7a 20 3d 20 ords... */..z =
0a70: 28 75 6c 6f 6e 67 29 74 3b 0a 09 79 20 3d 20 7a (ulong)t;..y = z
0a80: 3b 0a 09 7a 20 3e 3e 3d 20 31 36 3b 09 2f 2a 20 ;..z >>= 16;./*
0a90: 68 69 64 65 20 75 6e 64 65 66 69 6e 65 64 20 33 hide undefined 3
0aa0: 32 2d 62 69 74 20 73 68 69 66 74 20 66 72 6f 6d 2-bit shift from
0ab0: 20 33 32 2d 62 69 74 20 63 6f 6d 70 69 6c 65 72 32-bit compiler
0ac0: 73 20 2a 2f 0a 09 78 20 3d 20 7a 3e 3e 31 36 3b s */..x = z>>16;
0ad0: 0a 09 6d 61 6b 65 63 6f 6e 74 65 78 74 28 26 74 ..makecontext(&t
0ae0: 2d 3e 63 6f 6e 74 65 78 74 2e 75 63 2c 20 28 76 ->context.uc, (v
0af0: 6f 69 64 28 2a 29 28 29 29 74 61 73 6b 73 74 61 oid(*)())tasksta
0b00: 72 74 2c 20 32 2c 20 79 2c 20 78 29 3b 0a 0a 09 rt, 2, y, x);...
0b10: 72 65 74 75 72 6e 20 74 3b 0a 7d 0a 0a 69 6e 74 return t;.}..int
0b20: 0a 74 61 73 6b 63 72 65 61 74 65 28 76 6f 69 64 .taskcreate(void
0b30: 20 28 2a 66 6e 29 28 76 6f 69 64 2a 29 2c 20 76 (*fn)(void*), v
0b40: 6f 69 64 20 2a 61 72 67 2c 20 75 69 6e 74 20 73 oid *arg, uint s
0b50: 74 61 63 6b 29 0a 7b 0a 09 69 6e 74 20 69 64 3b tack).{..int id;
0b60: 0a 09 54 61 73 6b 20 2a 74 3b 0a 0a 09 74 20 3d ..Task *t;...t =
0b70: 20 74 61 73 6b 61 6c 6c 6f 63 28 66 6e 2c 20 61 taskalloc(fn, a
0b80: 72 67 2c 20 73 74 61 63 6b 29 3b 0a 09 74 61 73 rg, stack);..tas
0b90: 6b 63 6f 75 6e 74 2b 2b 3b 0a 09 69 64 20 3d 20 kcount++;..id =
0ba0: 74 2d 3e 69 64 3b 0a 09 74 61 73 6b 72 65 61 64 t->id;..taskread
0bb0: 79 28 74 29 3b 0a 09 72 65 74 75 72 6e 20 69 64 y(t);..return id
0bc0: 3b 0a 7d 0a 0a 76 6f 69 64 0a 74 61 73 6b 73 77 ;.}..void.tasksw
0bd0: 69 74 63 68 28 76 6f 69 64 29 0a 7b 0a 09 6e 65 itch(void).{..ne
0be0: 65 64 73 74 61 63 6b 28 30 29 3b 0a 09 63 6f 6e edstack(0);..con
0bf0: 74 65 78 74 73 77 69 74 63 68 28 26 74 61 73 6b textswitch(&task
0c00: 72 75 6e 6e 69 6e 67 2d 3e 63 6f 6e 74 65 78 74 running->context
0c10: 2c 20 26 74 61 73 6b 73 63 68 65 64 63 6f 6e 74 , &taskschedcont
0c20: 65 78 74 29 3b 0a 7d 0a 0a 76 6f 69 64 0a 74 61 ext);.}..void.ta
0c30: 73 6b 72 65 61 64 79 28 54 61 73 6b 20 2a 74 29 skready(Task *t)
0c40: 0a 7b 0a 09 61 64 64 74 61 73 6b 28 26 74 61 73 .{..addtask(&tas
0c50: 6b 72 75 6e 71 75 65 75 65 2c 20 74 29 3b 0a 7d krunqueue, t);.}
0c60: 0a 0a 69 6e 74 0a 74 61 73 6b 79 69 65 6c 64 28 ..int.taskyield(
0c70: 76 6f 69 64 29 0a 7b 0a 09 69 6e 74 20 6e 3b 0a void).{..int n;.
0c80: 09 0a 09 6e 20 3d 20 74 61 73 6b 6e 73 77 69 74 ...n = tasknswit
0c90: 63 68 3b 0a 09 74 61 73 6b 72 65 61 64 79 28 74 ch;..taskready(t
0ca0: 61 73 6b 72 75 6e 6e 69 6e 67 29 3b 0a 09 74 61 askrunning);..ta
0cb0: 73 6b 73 77 69 74 63 68 28 29 3b 0a 09 72 65 74 skswitch();..ret
0cc0: 75 72 6e 20 74 61 73 6b 6e 73 77 69 74 63 68 20 urn tasknswitch
0cd0: 2d 20 6e 3b 0a 7d 0a 0a 69 6e 74 0a 61 6e 79 72 - n;.}..int.anyr
0ce0: 65 61 64 79 28 76 6f 69 64 29 0a 7b 0a 09 72 65 eady(void).{..re
0cf0: 74 75 72 6e 20 74 61 73 6b 72 75 6e 71 75 65 75 turn taskrunqueu
0d00: 65 2e 68 65 61 64 20 21 3d 20 6e 69 6c 3b 0a 7d e.head != nil;.}
0d10: 0a 0a 76 6f 69 64 0a 74 61 73 6b 65 78 69 74 61 ..void.taskexita
0d20: 6c 6c 28 69 6e 74 20 76 61 6c 29 0a 7b 0a 09 65 ll(int val).{..e
0d30: 78 69 74 28 76 61 6c 29 3b 0a 7d 0a 0a 76 6f 69 xit(val);.}..voi
0d40: 64 0a 74 61 73 6b 65 78 69 74 28 69 6e 74 20 76 d.taskexit(int v
0d50: 61 6c 29 0a 7b 0a 09 74 61 73 6b 65 78 69 74 76 al).{..taskexitv
0d60: 61 6c 20 3d 20 76 61 6c 3b 0a 09 74 61 73 6b 72 al = val;..taskr
0d70: 75 6e 6e 69 6e 67 2d 3e 65 78 69 74 69 6e 67 20 unning->exiting
0d80: 3d 20 31 3b 0a 09 74 61 73 6b 73 77 69 74 63 68 = 1;..taskswitch
0d90: 28 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f ();.}..static vo
0da0: 69 64 0a 63 6f 6e 74 65 78 74 73 77 69 74 63 68 id.contextswitch
0db0: 28 43 6f 6e 74 65 78 74 20 2a 66 72 6f 6d 2c 20 (Context *from,
0dc0: 43 6f 6e 74 65 78 74 20 2a 74 6f 29 0a 7b 0a 09 Context *to).{..
0dd0: 69 66 28 73 77 61 70 63 6f 6e 74 65 78 74 28 26 if(swapcontext(&
0de0: 66 72 6f 6d 2d 3e 75 63 2c 20 26 74 6f 2d 3e 75 from->uc, &to->u
0df0: 63 29 20 3c 20 30 29 7b 0a 09 09 66 70 72 69 6e c) < 0){...fprin
0e00: 74 28 32 2c 20 22 73 77 61 70 63 6f 6e 74 65 78 t(2, "swapcontex
0e10: 74 20 66 61 69 6c 65 64 3a 20 25 72 5c 6e 22 29 t failed: %r\n")
0e20: 3b 0a 09 09 61 73 73 65 72 74 28 30 29 3b 0a 09 ;...assert(0);..
0e30: 7d 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f 69 64 }.}..static void
0e40: 0a 74 61 73 6b 73 63 68 65 64 75 6c 65 72 28 76 .taskscheduler(v
0e50: 6f 69 64 29 0a 7b 0a 09 54 61 73 6b 20 2a 74 3b oid).{..Task *t;
0e60: 0a 0a 09 74 61 73 6b 64 65 62 75 67 28 22 73 63 ...taskdebug("sc
0e70: 68 65 64 75 6c 65 72 20 65 6e 74 65 72 22 29 3b heduler enter");
0e80: 0a 09 66 6f 72 28 3b 3b 29 7b 0a 09 09 74 20 3d ..for(;;){...t =
0e90: 20 74 61 73 6b 72 75 6e 71 75 65 75 65 2e 68 65 taskrunqueue.he
0ea0: 61 64 3b 0a 09 09 69 66 28 74 20 3d 3d 20 6e 69 ad;...if(t == ni
0eb0: 6c 29 7b 0a 09 09 09 69 66 28 74 61 73 6b 63 6f l){....if(taskco
0ec0: 75 6e 74 20 3d 3d 20 30 29 0a 09 09 09 09 65 78 unt == 0).....ex
0ed0: 69 74 28 74 61 73 6b 65 78 69 74 76 61 6c 29 3b it(taskexitval);
0ee0: 0a 09 09 09 66 70 72 69 6e 74 28 32 2c 20 22 6e ....fprint(2, "n
0ef0: 6f 20 72 75 6e 6e 61 62 6c 65 20 74 61 73 6b 73 o runnable tasks
0f00: 21 20 25 64 20 74 61 73 6b 73 20 73 74 61 6c 6c ! %d tasks stall
0f10: 65 64 5c 6e 22 2c 20 74 61 73 6b 63 6f 75 6e 74 ed\n", taskcount
0f20: 29 3b 0a 09 09 09 65 78 69 74 28 31 29 3b 0a 09 );....exit(1);..
0f30: 09 7d 0a 09 09 64 65 6c 74 61 73 6b 28 26 74 61 .}...deltask(&ta
0f40: 73 6b 72 75 6e 71 75 65 75 65 2c 20 74 29 3b 0a skrunqueue, t);.
0f50: 09 09 74 61 73 6b 72 75 6e 6e 69 6e 67 20 3d 20 ..taskrunning =
0f60: 74 3b 0a 09 09 74 61 73 6b 6e 73 77 69 74 63 68 t;...tasknswitch
0f70: 2b 2b 3b 0a 09 09 74 61 73 6b 64 65 62 75 67 28 ++;...taskdebug(
0f80: 22 72 75 6e 20 25 64 20 28 25 73 29 22 2c 20 74 "run %d (%s)", t
0f90: 2d 3e 69 64 2c 20 74 2d 3e 6e 61 6d 65 29 3b 0a ->id, t->name);.
0fa0: 09 09 63 6f 6e 74 65 78 74 73 77 69 74 63 68 28 ..contextswitch(
0fb0: 26 74 61 73 6b 73 63 68 65 64 63 6f 6e 74 65 78 &taskschedcontex
0fc0: 74 2c 20 26 74 2d 3e 63 6f 6e 74 65 78 74 29 3b t, &t->context);
0fd0: 0a 2f 2f 70 72 69 6e 74 28 22 62 61 63 6b 20 69 .//print("back i
0fe0: 6e 20 73 63 68 65 64 75 6c 65 72 5c 6e 22 29 3b n scheduler\n");
0ff0: 0a 09 09 74 61 73 6b 72 75 6e 6e 69 6e 67 20 3d ...taskrunning =
1000: 20 6e 69 6c 3b 0a 09 09 69 66 28 74 2d 3e 65 78 nil;...if(t->ex
1010: 69 74 69 6e 67 29 7b 0a 09 09 09 74 61 73 6b 63 iting){....taskc
1020: 6f 75 6e 74 2d 2d 3b 0a 09 09 09 66 72 65 65 28 ount--;....free(
1030: 74 29 3b 0a 09 09 7d 0a 09 7d 0a 7d 0a 0a 76 6f t);...}..}.}..vo
1040: 69 64 2a 2a 0a 74 61 73 6b 64 61 74 61 28 76 6f id**.taskdata(vo
1050: 69 64 29 0a 7b 0a 09 72 65 74 75 72 6e 20 26 74 id).{..return &t
1060: 61 73 6b 72 75 6e 6e 69 6e 67 2d 3e 75 64 61 74 askrunning->udat
1070: 61 3b 0a 7d 0a 0a 2f 2a 0a 20 2a 20 64 65 62 75 a;.}../*. * debu
1080: 67 67 69 6e 67 0a 20 2a 2f 0a 76 6f 69 64 0a 74 gging. */.void.t
1090: 61 73 6b 73 65 74 6e 61 6d 65 28 63 68 61 72 20 asksetname(char
10a0: 2a 66 6d 74 2c 20 2e 2e 2e 29 0a 7b 0a 09 76 61 *fmt, ...).{..va
10b0: 5f 6c 69 73 74 20 61 72 67 3b 0a 09 54 61 73 6b _list arg;..Task
10c0: 20 2a 74 3b 0a 0a 09 74 20 3d 20 74 61 73 6b 72 *t;...t = taskr
10d0: 75 6e 6e 69 6e 67 3b 0a 09 76 61 5f 73 74 61 72 unning;..va_star
10e0: 74 28 61 72 67 2c 20 66 6d 74 29 3b 0a 09 76 73 t(arg, fmt);..vs
10f0: 6e 70 72 69 6e 74 28 74 2d 3e 6e 61 6d 65 2c 20 nprint(t->name,
1100: 73 69 7a 65 6f 66 20 74 2d 3e 6e 61 6d 65 2c 20 sizeof t->name,
1110: 66 6d 74 2c 20 61 72 67 29 3b 0a 09 76 61 5f 65 fmt, arg);..va_e
1120: 6e 64 28 61 72 67 29 3b 0a 7d 0a 0a 63 68 61 72 nd(arg);.}..char
1130: 2a 0a 74 61 73 6b 67 65 74 6e 61 6d 65 28 76 6f *.taskgetname(vo
1140: 69 64 29 0a 7b 0a 09 72 65 74 75 72 6e 20 74 61 id).{..return ta
1150: 73 6b 72 75 6e 6e 69 6e 67 2d 3e 6e 61 6d 65 3b skrunning->name;
1160: 0a 7d 0a 0a 76 6f 69 64 0a 74 61 73 6b 73 65 74 .}..void.taskset
1170: 73 74 61 74 65 28 63 68 61 72 20 2a 66 6d 74 2c state(char *fmt,
1180: 20 2e 2e 2e 29 0a 7b 0a 09 76 61 5f 6c 69 73 74 ...).{..va_list
1190: 20 61 72 67 3b 0a 09 54 61 73 6b 20 2a 74 3b 0a arg;..Task *t;.
11a0: 0a 09 74 20 3d 20 74 61 73 6b 72 75 6e 6e 69 6e ..t = taskrunnin
11b0: 67 3b 0a 09 76 61 5f 73 74 61 72 74 28 61 72 67 g;..va_start(arg
11c0: 2c 20 66 6d 74 29 3b 0a 09 76 73 6e 70 72 69 6e , fmt);..vsnprin
11d0: 74 28 74 2d 3e 73 74 61 74 65 2c 20 73 69 7a 65 t(t->state, size
11e0: 6f 66 20 74 2d 3e 6e 61 6d 65 2c 20 66 6d 74 2c of t->name, fmt,
11f0: 20 61 72 67 29 3b 0a 09 76 61 5f 65 6e 64 28 61 arg);..va_end(a
1200: 72 67 29 3b 0a 7d 0a 0a 76 6f 69 64 0a 6e 65 65 rg);.}..void.nee
1210: 64 73 74 61 63 6b 28 69 6e 74 20 6e 29 0a 7b 0a dstack(int n).{.
1220: 09 54 61 73 6b 20 2a 74 3b 0a 0a 09 74 20 3d 20 .Task *t;...t =
1230: 74 61 73 6b 72 75 6e 6e 69 6e 67 3b 0a 0a 09 69 taskrunning;...i
1240: 66 28 28 63 68 61 72 2a 29 26 74 20 3c 3d 20 28 f((char*)&t <= (
1250: 63 68 61 72 2a 29 74 2d 3e 73 74 6b 0a 09 7c 7c char*)t->stk..||
1260: 20 28 63 68 61 72 2a 29 26 74 20 2d 20 28 63 68 (char*)&t - (ch
1270: 61 72 2a 29 74 2d 3e 73 74 6b 20 3c 20 32 35 36 ar*)t->stk < 256
1280: 2b 6e 29 7b 0a 09 09 66 70 72 69 6e 74 28 32 2c +n){...fprint(2,
1290: 20 22 74 61 73 6b 20 73 74 61 63 6b 20 6f 76 65 "task stack ove
12a0: 72 66 6c 6f 77 3a 20 26 74 3d 25 70 20 74 73 74 rflow: &t=%p tst
12b0: 6b 3d 25 70 20 6e 3d 25 64 5c 6e 22 2c 20 26 74 k=%p n=%d\n", &t
12c0: 2c 20 74 2d 3e 73 74 6b 2c 20 32 35 36 2b 6e 29 , t->stk, 256+n)
12d0: 3b 0a 09 09 61 62 6f 72 74 28 29 3b 0a 09 7d 0a ;...abort();..}.
12e0: 7d 0a 0a 2f 2a 0a 20 2a 20 73 74 61 72 74 75 70 }../*. * startup
12f0: 0a 20 2a 2f 0a 0a 73 74 61 74 69 63 20 69 6e 74 . */..static int
1300: 20 74 61 73 6b 61 72 67 63 3b 0a 73 74 61 74 69 taskargc;.stati
1310: 63 20 63 68 61 72 20 2a 2a 74 61 73 6b 61 72 67 c char **taskarg
1320: 76 3b 0a 69 6e 74 20 6d 61 69 6e 73 74 61 63 6b v;.int mainstack
1330: 73 69 7a 65 3b 0a 0a 73 74 61 74 69 63 20 76 6f size;..static vo
1340: 69 64 0a 74 61 73 6b 6d 61 69 6e 73 74 61 72 74 id.taskmainstart
1350: 28 76 6f 69 64 20 2a 76 29 0a 7b 0a 09 74 61 73 (void *v).{..tas
1360: 6b 6d 61 69 6e 28 74 61 73 6b 61 72 67 63 2c 20 kmain(taskargc,
1370: 74 61 73 6b 61 72 67 76 29 3b 0a 7d 0a 0a 69 6e taskargv);.}..in
1380: 74 0a 6d 61 69 6e 28 69 6e 74 20 61 72 67 63 2c t.main(int argc,
1390: 20 63 68 61 72 20 2a 2a 61 72 67 76 29 0a 7b 0a char **argv).{.
13a0: 09 61 72 67 76 30 20 3d 20 61 72 67 76 5b 30 5d .argv0 = argv[0]
13b0: 3b 0a 09 74 61 73 6b 61 72 67 63 20 3d 20 61 72 ;..taskargc = ar
13c0: 67 63 3b 0a 09 74 61 73 6b 61 72 67 76 20 3d 20 gc;..taskargv =
13d0: 61 72 67 76 3b 0a 0a 09 69 66 28 6d 61 69 6e 73 argv;...if(mains
13e0: 74 61 63 6b 73 69 7a 65 20 3d 3d 20 30 29 0a 09 tacksize == 0)..
13f0: 09 6d 61 69 6e 73 74 61 63 6b 73 69 7a 65 20 3d .mainstacksize =
1400: 20 32 35 36 2a 31 30 32 34 3b 0a 09 74 61 73 6b 256*1024;..task
1410: 63 72 65 61 74 65 28 74 61 73 6b 6d 61 69 6e 73 create(taskmains
1420: 74 61 72 74 2c 20 6e 69 6c 2c 20 6d 61 69 6e 73 tart, nil, mains
1430: 74 61 63 6b 73 69 7a 65 29 3b 0a 09 74 61 73 6b tacksize);..task
1440: 73 63 68 65 64 75 6c 65 72 28 29 3b 0a 09 66 70 scheduler();..fp
1450: 72 69 6e 74 28 32 2c 20 22 74 61 73 6b 73 63 68 rint(2, "tasksch
1460: 65 64 75 6c 65 72 20 72 65 74 75 72 6e 65 64 20 eduler returned
1470: 69 6e 20 6d 61 69 6e 21 5c 6e 22 29 3b 0a 09 61 in main!\n");..a
1480: 62 6f 72 74 28 29 3b 0a 09 72 65 74 75 72 6e 20 bort();..return
1490: 30 3b 0a 7d 0a 0a 2f 2a 0a 20 2a 20 68 6f 6f 72 0;.}../*. * hoor
14a0: 61 79 20 66 6f 72 20 6c 69 6e 6b 65 64 20 6c 69 ay for linked li
14b0: 73 74 73 0a 20 2a 2f 0a 73 74 61 74 69 63 20 76 sts. */.static v
14c0: 6f 69 64 0a 61 64 64 74 61 73 6b 28 54 61 73 6b oid.addtask(Task
14d0: 6c 69 73 74 20 2a 6c 2c 20 54 61 73 6b 20 2a 74 list *l, Task *t
14e0: 29 0a 7b 0a 09 69 66 28 6c 2d 3e 74 61 69 6c 29 ).{..if(l->tail)
14f0: 7b 0a 09 09 6c 2d 3e 74 61 69 6c 2d 3e 6e 65 78 {...l->tail->nex
1500: 74 20 3d 20 74 3b 0a 09 09 74 2d 3e 70 72 65 76 t = t;...t->prev
1510: 20 3d 20 6c 2d 3e 74 61 69 6c 3b 0a 09 7d 65 6c = l->tail;..}el
1520: 73 65 7b 0a 09 09 6c 2d 3e 68 65 61 64 20 3d 20 se{...l->head =
1530: 74 3b 0a 09 09 74 2d 3e 70 72 65 76 20 3d 20 6e t;...t->prev = n
1540: 69 6c 3b 0a 09 7d 0a 09 6c 2d 3e 74 61 69 6c 20 il;..}..l->tail
1550: 3d 20 74 3b 0a 09 74 2d 3e 6e 65 78 74 20 3d 20 = t;..t->next =
1560: 6e 69 6c 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 76 nil;.}..static v
1570: 6f 69 64 0a 64 65 6c 74 61 73 6b 28 54 61 73 6b oid.deltask(Task
1580: 6c 69 73 74 20 2a 6c 2c 20 54 61 73 6b 20 2a 74 list *l, Task *t
1590: 29 0a 7b 0a 09 69 66 28 74 2d 3e 70 72 65 76 29 ).{..if(t->prev)
15a0: 0a 09 09 74 2d 3e 70 72 65 76 2d 3e 6e 65 78 74 ...t->prev->next
15b0: 20 3d 20 74 2d 3e 6e 65 78 74 3b 0a 09 65 6c 73 = t->next;..els
15c0: 65 0a 09 09 6c 2d 3e 68 65 61 64 20 3d 20 74 2d e...l->head = t-
15d0: 3e 6e 65 78 74 3b 0a 09 69 66 28 74 2d 3e 6e 65 >next;..if(t->ne
15e0: 78 74 29 0a 09 09 74 2d 3e 6e 65 78 74 2d 3e 70 xt)...t->next->p
15f0: 72 65 76 20 3d 20 74 2d 3e 70 72 65 76 3b 0a 09 rev = t->prev;..
1600: 65 6c 73 65 0a 09 09 6c 2d 3e 74 61 69 6c 20 3d else...l->tail =
1610: 20 74 2d 3e 70 72 65 76 3b 0a 7d 0a 0a 75 6e 73 t->prev;.}..uns
1620: 69 67 6e 65 64 20 69 6e 74 0a 74 61 73 6b 69 64 igned int.taskid
1630: 28 76 6f 69 64 29 0a 7b 0a 09 72 65 74 75 72 6e (void).{..return
1640: 20 74 61 73 6b 72 75 6e 6e 69 6e 67 2d 3e 69 64 taskrunning->id
1650: 3b 0a 7d 0a 0a ;.}..