Rune - Stabilization, heap/persist support
[rune.git] / libruntime / thread.c
1 /*
2  * THREAD.C
3  */
4
5 #include "defs.h"
6
7 #define TWHSIZE         512
8 #define TWHMASK         (TWHSIZE - 1)
9
10 typedef struct ThreadWait {
11         struct tdlist   tw_List;
12 } ThreadWait;
13
14 typedef struct ThreadCall {
15         struct tdlist   list;
16         void            (*func)(void *args, void *res);
17         void            *args;
18         void            *res;
19 } ThreadCall;
20
21 static ThreadWait TWArray[TWHSIZE];
22
23 static __inline
24 int
25 hashptr(uintptr_t wchan)
26 {
27         int hv = (int)wchan;
28
29         hv = hv % 988237;
30         hv = hv ^ (hv >> 12);
31
32         return (hv & TWHMASK);
33 }
34
35 /*
36  * Threaded call support, wraps threaded procedure call
37  */
38 void RuneRunTime_ThreadedCall(void *args, void *res,
39                         void (*func)(void *, void *));
40 void RuneRunTime_ThreadedDetach(void);
41
42 static
43 void
44 startThreadedCall(void *data)
45 {
46         ThreadCall      *tc = data;
47
48         tc->func(tc->args, tc->res);
49         /* tc invalid after this point */
50
51         /*
52          * Reload tc, target may have detached
53          */
54         tc = CurThread->th_StartData;
55         if (tc)
56                 threadWakeup1(&tc->list);
57         /* tc invalid after this point */
58 }
59
60 /*
61  * Called from generated code at run-time, cothread placed on run-queue
62  * but guaranteed not to run immediately.  We then stop our current thread
63  * and wait for the cothread to detach.
64  */
65 void
66 RuneRunTime_ThreadedCall(void *args, void *res, void (*func)(void *, void *))
67 {
68         ThreadCall      tc;
69
70         printf("ThreadedCall %p(%p,%p)\n", func, args, res);
71         RUNE_INIT(&tc.list);
72         tc.args = args;
73         tc.res = res;
74         tc.func = func;
75         threadCreate(startThreadedCall, &tc);
76         threadStop(&tc.list, 0);
77         printf("ThreadedResult\n");
78 }
79
80 void
81 RuneRunTime_ThreadedDetach(void)
82 {
83         ThreadCall      *tc;
84
85         printf("ThreadedDetach\n");
86         tc = CurThread->th_StartData;
87         if (tc) {
88                 CurThread->th_StartData = NULL;
89                 threadWakeup1(&tc->list);
90         }
91 }
92
93 /*
94  * SYSTEM CALLS
95  */
96 void RuneSysCall_waitThreads(void *args, void *rval);
97
98 void
99 RuneSysCall_waitThreads(void *args, void *rval)
100 {
101         threadWaitTerminate();
102 }
103
104
105 struct wakeup_args {
106         PointerStor     s;
107 };
108
109 void RuneSysCall_wakeup(struct wakeup_args *args, void *rval);
110
111 void
112 RuneSysCall_wakeup(struct wakeup_args *args, void *rval)
113 {
114         ThreadWait *tw;
115         uintptr_t wchan;
116
117         wchan = (uintptr_t)args->s.s_Addr;
118         tw = &TWArray[hashptr(wchan)];
119
120         threadWakeupWChan(&tw->tw_List, wchan);
121 }
122
123 struct sleep_args {
124         int32_t         ms;
125 };
126
127 void RuneSysCall_sleep(struct sleep_args *args, void *rval);
128
129 void
130 RuneSysCall_sleep(struct sleep_args *args, void *rval)
131 {
132         ThreadWait tw;
133
134         RUNE_INIT(&tw.tw_List);
135
136         if (args->ms > 0)
137                 threadSleep(&tw.tw_List, args->ms);
138 }
139
140
141 struct tsleep_args {
142         PointerStor     s;
143         int32_t         ms;
144 };
145
146 void RuneSysCall_tsleep(struct tsleep_args *args, void *rval);
147
148 void
149 RuneSysCall_tsleep(struct tsleep_args *args, void *rval)
150 {
151         ThreadWait *tw;
152         uintptr_t wchan;
153
154         wchan = (uintptr_t)args->s.s_Addr;
155
156         tw = &TWArray[hashptr(wchan)];
157         if (args->ms > 0)
158                 threadSleepWChan(&tw->tw_List, wchan, args->ms);
159 }