1/** \file
2 *  \brief A simple work stealing library based upon both cilk and wool.
3 */
4
5/*
6 * Copyright (c) 2010, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#ifndef TWEED_H_
15#define TWEED_H_
16
17/* remove this to use mfence approach instead of CAS approach */
18#define TWEED_USE_CAS
19
20/* remove this to use lock-based approach */
21#define TWEED_LOCK_FREE
22
23
24/* Select waiting mechanism here */
25//#define TWEED_WAITING
26#define TWEED_LEAPFROG
27//#define TWEED_PARK
28
29#include <barrelfish/barrelfish.h>
30#include <arch/x86/barrelfish_kpi/asm_inlines_arch.h>
31#include <barrelfish/threads.h>
32
33
34/* Constants */
35#define TWEED_LOG_TASK_STACK_SIZE 12
36#define TWEED_TASK_STACK_SIZE (1ll << TWEED_LOG_TASK_STACK_SIZE)
37#define TWEED_TASK_STACK_MASK (TWEED_TASK_STACK_SIZE - 1)
38
39#define TWEED_TASK_NEW       0x1
40#define TWEED_TASK_INLINED   0x2
41#define TWEED_TASK_STOLEN    0x4
42#define TWEED_TASK_COMPLETE  0x10
43
44
45/* Main tweed task declaration */
46#define MAIN_TASK(name, arg1_name)                                           \
47int name ## _task_func (struct generic_task_desc * _tweed_top_,              \
48                        void* arg1_name);                                    \
49int name ## _task_func (struct generic_task_desc * _tweed_top_,              \
50                        void* arg1_name)
51
52
53/* Task declaration macro */
54#define TASK(rtype, name, arg_count, ...)                                    \
55    rtype name ## _task_func (struct generic_task_desc * _tweed_top_         \
56                              _ARGS_FUNC_DEF_ ## arg_count ( __VA_ARGS__ ) );\
57    void name ## _task_wrapper (struct generic_task_desc * _tweed_top_,      \
58                                void* task_arg);                             \
59struct name ## _task_desc {                                                  \
60    struct generic_task_desc task;                                           \
61    rtype ret;   						             \
62    _ARGS_STRUCT_DEF_ ## arg_count ( __VA_ARGS__ );                          \
63};								             \
64void name ## _task_wrapper (struct generic_task_desc * _tweed_top_,          \
65                            void* task_arg) {                                \
66    struct name ## _task_desc * task = (struct name ## _task_desc *)task_arg;\
67    task->ret = _INLINE_FUNC_ ## arg_count (_tweed_top_, name, task);        \
68}                                                                            \
69rtype name ## _task_func (struct generic_task_desc * _tweed_top_             \
70                          _ARGS_FUNC_DEF_ ## arg_count ( __VA_ARGS__ ) )
71
72
73/* Task declaration macro for tasks with void return */
74#define TASK_VOID(name, arg_count, ...)                                      \
75    void name ## _task_func (struct generic_task_desc * _tweed_top_          \
76                             _ARGS_FUNC_DEF_ ## arg_count ( __VA_ARGS__ ) ); \
77    void name ## _task_wrapper (struct generic_task_desc * _tweed_top_,      \
78                                void* task_arg);                             \
79struct name ## _task_desc {                                                  \
80    struct generic_task_desc task;                                           \
81    void * ret;   /* placeholder, not used */                                \
82    _ARGS_STRUCT_DEF_ ## arg_count ( __VA_ARGS__ );                          \
83};								             \
84void name ## _task_wrapper (struct generic_task_desc * _tweed_top_,          \
85                            void* task_arg) {                                \
86    struct name ## _task_desc * task = (struct name ## _task_desc *)task_arg;\
87    _INLINE_FUNC_ ## arg_count (_tweed_top_, name, task);                    \
88}                                                                            \
89void name ## _task_func (struct generic_task_desc * _tweed_top_             \
90                          _ARGS_FUNC_DEF_ ## arg_count ( __VA_ARGS__ ) )
91
92
93/* Function macros, to be used externally */
94
95#define INIT_TWEED(workers, main_task, args)                                 \
96    init_tweed(workers, & main_task ## _task_func, args);
97
98
99#define SPAWN(name, arg_count, ...)                                          \
100    _SPAWN(TOKEN_CONCAT(_task_, __LINE__),TOKEN_CONCAT(_prev_top_, __LINE__),\
101            name, arg_count, ##__VA_ARGS__)
102
103
104#define _SPAWN(task_id, prev_top_id, name, arg_count, ...)                   \
105    if (_tweed_top_ == NULL) {                                               \
106        _tweed_top_ = set_top();                                             \
107    } else {                                                                 \
108        /* move top pointer past last task */                                \
109        _tweed_top_ = NEXT_TASK(_tweed_top_,                                 \
110                                sizeof(struct name ## _task_desc));          \
111    }                                                                        \
112    /* Allocate space for new task */                                        \
113    if ((~TWEED_TASK_STACK_MASK & ((uint64_t)_tweed_top_)) !=                \
114        (~TWEED_TASK_STACK_MASK & ((uint64_t)(((char*)_tweed_top_) +         \
115            sizeof(struct name ## _task_desc))))) {                          \
116        fprintf(stderr, "Tweed task stack overflowed\n");                    \
117        exit(1);                                                             \
118    }                                                                        \
119    struct name ## _task_desc * task_id =                                    \
120        (struct name ## _task_desc *) _tweed_top_;                           \
121    INIT_THIEF(task_id);                                                     \
122    task_id ->task.size     = sizeof(struct name ## _task_desc);             \
123    task_id ->task.f.func   = & name ## _task_wrapper;                       \
124    _SET_SPAWN_ARGS_ ## arg_count ( task_id, ##__VA_ARGS__);                 \
125    __asm volatile ("" ::: "memory");                                        \
126    task_id ->task.balarm   = TWEED_TASK_NEW;                                \
127
128
129#define CALL(name, arg_cnt, ...)                                             \
130    (name ## _task_func (_tweed_top_, ##__VA_ARGS__ ))
131
132
133#define SYNC(name, arg_cnt)                                                  \
134    _SYNC( TOKEN_CONCAT(_task_, __LINE__), name, arg_cnt)
135
136
137#define _SYNC(task_id, name, arg_cnt)                                        \
138    ({                                                                       \
139        int stolen = 0;                                                      \
140        struct name ## _task_desc * task_id =                                \
141            (struct name ## _task_desc *) _tweed_top_;                       \
142        /* pop task from stack */                                            \
143        if (AT_TOP_OF_STACK) {                                               \
144            /* already at top of stack, set top to NULL */                   \
145            _tweed_top_ = NULL;                                              \
146        } else {                                                             \
147            /* otherwise release the task data-structure */                  \
148            _tweed_top_ = PREV_TASK(_tweed_top_,                             \
149                                    sizeof(struct name ## _task_desc));      \
150        }                                                                    \
151        SET_FUNC_INLINED(task_id);                                           \
152        if (WAS_STOLEN(task_id) &&                                           \
153            sync_stolen((struct generic_task_desc *)task_id)) {              \
154            handle_stolen_task((struct generic_task_desc *)task_id);         \
155            stolen=1;                                                        \
156        }                                                                    \
157        /* Return result */                                                  \
158        stolen ? task_id->ret :                                              \
159                _INLINE_FUNC_ ## arg_cnt (_tweed_top_, name, task_id);       \
160    })
161
162
163
164/* Private function macros (only used internally) */
165
166#ifdef TWEED_USE_CAS
167// use CAS operations instead of mfences
168#define SET_FUNC_INLINED(t)                                                  \
169    int __success = cmpxchg128((uint64_t *)&(t->task.f.func),                \
170                               (uint64_t)t->task.f.func, TWEED_TASK_NEW,     \
171                               (uint64_t)NULL, TWEED_TASK_INLINED);
172#define WAS_STOLEN(t) (!__success)
173#define INIT_THIEF(t) /* nop */
174#else
175// use mfence operations
176#define SET_FUNC_INLINED(t)                                                  \
177        t->task.f.func = NULL;                                               \
178        mfence();
179#define WAS_STOLEN(t) (t->task.balarm & TWEED_TASK_STOLEN) != 0
180#define INIT_THIEF(t) t->task.thief = NULL
181#endif
182
183#define PREV_TASK(x,y)                                                       \
184    ((struct generic_task_desc *) (((char*)(x)) - (y)))
185#define NEXT_TASK(x,y)                                                       \
186    ((struct generic_task_desc *) (((char*)(x)) + (y)))
187#define AT_TOP_OF_STACK                                                      \
188    ((((uint64_t )_tweed_top_) & TWEED_TASK_STACK_MASK) == 0)
189
190#define TOKEN_CONCAT2(x, y) x ## y
191#define TOKEN_CONCAT(x, y) TOKEN_CONCAT2(x, y)
192
193
194/* Decleration of arguments for functions */
195#define _ARGS_FUNC_DEF_0()
196#define _ARGS_FUNC_DEF_1(arg1_type, arg1_name)                               \
197    , arg1_type arg1_name
198#define _ARGS_FUNC_DEF_2(arg1_type, arg1_name, arg2_type, arg2_name)         \
199    , arg1_type arg1_name, arg2_type arg2_name
200#define _ARGS_FUNC_DEF_3(arg1_type, arg1_name, arg2_type, arg2_name,         \
201                         arg3_type, arg3_name)                               \
202    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name
203#define _ARGS_FUNC_DEF_4(arg1_type, arg1_name, arg2_type, arg2_name,         \
204                         arg3_type, arg3_name, arg4_type, arg4_name)         \
205    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name,         \
206      arg4_type arg4_name
207#define _ARGS_FUNC_DEF_5(arg1_type, arg1_name, arg2_type, arg2_name,         \
208                         arg3_type, arg3_name, arg4_type, arg4_name,         \
209                         arg5_type, arg5_name)                               \
210    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name,         \
211      arg4_type arg4_name, arg5_type arg5_name
212#define _ARGS_FUNC_DEF_6(arg1_type, arg1_name, arg2_type, arg2_name,         \
213                         arg3_type, arg3_name, arg4_type, arg4_name,         \
214                         arg5_type, arg5_name, arg6_type, arg6_name)         \
215    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name,         \
216      arg4_type arg4_name, arg5_type arg5_name, arg6_type arg6_name
217#define _ARGS_FUNC_DEF_7(arg1_type, arg1_name, arg2_type, arg2_name,         \
218                         arg3_type, arg3_name, arg4_type, arg4_name,         \
219                         arg5_type, arg5_name, arg6_type, arg6_name,         \
220                         arg7_type, arg7_name)                               \
221    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name,         \
222      arg4_type arg4_name, arg5_type arg5_name, arg6_type arg6_name,         \
223      arg7_type arg7_name
224#define _ARGS_FUNC_DEF_8(arg1_type, arg1_name, arg2_type, arg2_name,         \
225                         arg3_type, arg3_name, arg4_type, arg4_name,         \
226                         arg5_type, arg5_name, arg6_type, arg6_name,         \
227                         arg7_type, arg7_name, arg8_type, arg8_name)         \
228    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name,         \
229      arg4_type arg4_name, arg5_type arg5_name, arg6_type arg6_name,         \
230      arg7_type arg7_name, arg8_type arg8_name
231#define _ARGS_FUNC_DEF_9(arg1_type, arg1_name, arg2_type, arg2_name,         \
232                         arg3_type, arg3_name, arg4_type, arg4_name,         \
233                         arg5_type, arg5_name, arg6_type, arg6_name,         \
234                         arg7_type, arg7_name, arg8_type, arg8_name,         \
235                         arg9_type, arg9_name)                               \
236    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name,         \
237      arg4_type arg4_name, arg5_type arg5_name, arg6_type arg6_name,         \
238      arg7_type arg7_name, arg8_type arg8_name, arg9_type arg9_name
239#define _ARGS_FUNC_DEF_10(arg1_type, arg1_name, arg2_type, arg2_name,        \
240                          arg3_type, arg3_name, arg4_type, arg4_name,        \
241                          arg5_type, arg5_name, arg6_type, arg6_name,        \
242                          arg7_type, arg7_name, arg8_type, arg8_name,        \
243                          arg9_type, arg9_name, arg10_type, arg10_name)      \
244    , arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name,         \
245      arg4_type arg4_name, arg5_type arg5_name, arg6_type arg6_name,         \
246      arg7_type arg7_name, arg8_type arg8_name, arg9_type arg9_name,         \
247      arg10_type arg10_name
248
249
250/* Decleration of arguments fields in the task descriptor */
251#define _ARGS_STRUCT_DEF_0()
252#define _ARGS_STRUCT_DEF_1(arg1_type, arg1_name)                             \
253    arg1_type arg1;
254#define _ARGS_STRUCT_DEF_2(arg1_type, arg1_name, arg2_type, arg2_name)       \
255    arg1_type arg1;                                                          \
256    arg2_type arg2;
257#define _ARGS_STRUCT_DEF_3(arg1_type, arg1_name, arg2_type, arg2_name,       \
258                           arg3_type, arg3_name)                             \
259    arg1_type arg1;                                                          \
260    arg2_type arg2;                                                          \
261    arg3_type arg3;
262#define _ARGS_STRUCT_DEF_4(arg1_type, arg1_name, arg2_type, arg2_name,       \
263                           arg3_type, arg3_name, arg4_type, arg4_name)       \
264    arg1_type arg1;                                                          \
265    arg2_type arg2;                                                          \
266    arg3_type arg3;                                                          \
267    arg4_type arg4;
268#define _ARGS_STRUCT_DEF_5(arg1_type, arg1_name, arg2_type, arg2_name,       \
269                           arg3_type, arg3_name, arg4_type, arg4_name,       \
270                           arg5_type, arg5_name)                             \
271    arg1_type arg1;                                                          \
272    arg2_type arg2;                                                          \
273    arg3_type arg3;                                                          \
274    arg4_type arg4;                                                          \
275    arg5_type arg5;
276#define _ARGS_STRUCT_DEF_6(arg1_type, arg1_name, arg2_type, arg2_name,       \
277                           arg3_type, arg3_name, arg4_type, arg4_name,       \
278                           arg5_type, arg5_name, arg6_type, arg6_name)       \
279    arg1_type arg1;                                                          \
280    arg2_type arg2;                                                          \
281    arg3_type arg3;                                                          \
282    arg4_type arg4;                                                          \
283    arg5_type arg5;                                                          \
284    arg6_type arg6;
285#define _ARGS_STRUCT_DEF_7(arg1_type, arg1_name, arg2_type, arg2_name,       \
286                           arg3_type, arg3_name, arg4_type, arg4_name,       \
287                           arg5_type, arg5_name, arg6_type, arg6_name,       \
288                           arg7_type, arg7_name)                             \
289    arg1_type arg1;                                                          \
290    arg2_type arg2;                                                          \
291    arg3_type arg3;                                                          \
292    arg4_type arg4;                                                          \
293    arg5_type arg5;                                                          \
294    arg6_type arg6;                                                          \
295    arg7_type arg7;
296#define _ARGS_STRUCT_DEF_8(arg1_type, arg1_name, arg2_type, arg2_name,       \
297                           arg3_type, arg3_name, arg4_type, arg4_name,       \
298                           arg5_type, arg5_name, arg6_type, arg6_name,       \
299                           arg7_type, arg7_name, arg8_type, arg8_name)       \
300    arg1_type arg1;                                                          \
301    arg2_type arg2;                                                          \
302    arg3_type arg3;                                                          \
303    arg4_type arg4;                                                          \
304    arg5_type arg5;                                                          \
305    arg6_type arg6;                                                          \
306    arg7_type arg7;                                                          \
307    arg8_type arg8;
308#define _ARGS_STRUCT_DEF_9(arg1_type, arg1_name, arg2_type, arg2_name,       \
309                           arg3_type, arg3_name, arg4_type, arg4_name,       \
310                           arg5_type, arg5_name, arg6_type, arg6_name,       \
311                           arg7_type, arg7_name, arg8_type, arg8_name,       \
312                           arg9_type, arg9_name)                             \
313    arg1_type arg1;                                                          \
314    arg2_type arg2;                                                          \
315    arg3_type arg3;                                                          \
316    arg4_type arg4;                                                          \
317    arg5_type arg5;                                                          \
318    arg6_type arg6;                                                          \
319    arg7_type arg7;                                                          \
320    arg8_type arg8;                                                          \
321    arg9_type arg9;
322#define _ARGS_STRUCT_DEF_10(arg1_type, arg1_name, arg2_type, arg2_name,      \
323                            arg3_type, arg3_name, arg4_type, arg4_name,      \
324                            arg5_type, arg5_name, arg6_type, arg6_name,      \
325                            arg7_type, arg7_name, arg8_type, arg8_name,      \
326                            arg9_type, arg9_name, arg10_type, arg10_name)    \
327    arg1_type arg1;                                                          \
328    arg2_type arg2;                                                          \
329    arg3_type arg3;                                                          \
330    arg4_type arg4;                                                          \
331    arg5_type arg5;                                                          \
332    arg6_type arg6;                                                          \
333    arg7_type arg7;                                                          \
334    arg8_type arg8;                                                          \
335    arg9_type arg9;                                                          \
336    arg10_type arg10;
337
338
339/* Set spawn args */
340#define _SET_SPAWN_ARGS_0(task_name)
341
342#define _SET_SPAWN_ARGS_1(task_name, arg_val_1)                              \
343    task_name->arg1 = arg_val_1;
344
345#define _SET_SPAWN_ARGS_2(task_name, arg_val_1, arg_val_2)                   \
346    _SET_SPAWN_ARGS_1(task_name, arg_val_1);                                 \
347    task_name->arg2 = arg_val_2;
348
349#define _SET_SPAWN_ARGS_3(task_name, arg_val_1, arg_val_2, arg_val_3)        \
350    _SET_SPAWN_ARGS_2(task_name, arg_val_1, arg_val_2);                      \
351    task_name->arg3 = arg_val_3;
352
353#define _SET_SPAWN_ARGS_4(task_name, arg_val_1, arg_val_2, arg_val_3,        \
354                          arg_val_4)                                         \
355    _SET_SPAWN_ARGS_3(task_name, arg_val_1, arg_val_2, arg_val_3);           \
356    task_name->arg4 = arg_val_4;
357
358#define _SET_SPAWN_ARGS_5(task_name, arg_val_1, arg_val_2, arg_val_3,        \
359                          arg_val_4, arg_val_5)                              \
360    _SET_SPAWN_ARGS_4(task_name, arg_val_1, arg_val_2, arg_val_3, arg_val_4);\
361    task_name->arg5 = arg_val_5;
362
363#define _SET_SPAWN_ARGS_6(task_name, arg_val_1, arg_val_2, arg_val_3,        \
364                          arg_val_4, arg_val_5, arg_val_6)                   \
365    _SET_SPAWN_ARGS_5(task_name, arg_val_1, arg_val_2, arg_val_3, arg_val_4, \
366                      arg_val_5);                                            \
367    task_name->arg6 = arg_val_6;
368
369#define _SET_SPAWN_ARGS_7(task_name, arg_val_1, arg_val_2, arg_val_3,        \
370                          arg_val_4, arg_val_5, arg_val_6, arg_val_7)        \
371    _SET_SPAWN_ARGS_6(task_name, arg_val_1, arg_val_2, arg_val_3, arg_val_4, \
372                      arg_val_5, arg_val_6);                                 \
373    task_name->arg7 = arg_val_7;
374
375#define _SET_SPAWN_ARGS_8(task_name, arg_val_1, arg_val_2, arg_val_3,        \
376                          arg_val_4, arg_val_5, arg_val_6, arg_val_7,        \
377                          arg_val_8)                                         \
378    _SET_SPAWN_ARGS_7(task_name, arg_val_1, arg_val_2, arg_val_3, arg_val_4, \
379                      arg_val_5, arg_val_6, arg_val_7);                      \
380    task_name->arg8 = arg_val_8;
381
382#define _SET_SPAWN_ARGS_9(task_name, arg_val_1, arg_val_2, arg_val_3,        \
383                          arg_val_4, arg_val_5, arg_val_6, arg_val_7,        \
384                          arg_val_8, arg_val_9)                              \
385    _SET_SPAWN_ARGS_8(task_name, arg_val_1, arg_val_2, arg_val_3, arg_val_4, \
386                      arg_val_5, arg_val_6, arg_val_7, arg_val_8);           \
387    task_name->arg9 = arg_val_9;
388
389#define _SET_SPAWN_ARGS_10(task_name, arg_val_1, arg_val_2, arg_val_3,       \
390                           arg_val_4, arg_val_5, arg_val_6, arg_val_7,       \
391                           arg_val_8, arg_val_9, arg_val_10)                 \
392    _SET_SPAWN_ARGS_9(task_name, arg_val_1, arg_val_2, arg_val_3, arg_val_4, \
393                      arg_val_5, arg_val_6, arg_val_7, arg_val_8, arg_val_9);\
394    task_name->arg10 = arg_val_10;
395
396
397/* Inline function call */
398#define _INLINE_FUNC_0(_tweed_top_, name, task_name)                         \
399    name ## _task_func(_tweed_top_)
400#define _INLINE_FUNC_1(_tweed_top_, name, task_name)                         \
401    name ## _task_func(_tweed_top_, task_name->arg1)
402#define _INLINE_FUNC_2(_tweed_top_, name, task_name)                         \
403    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2)
404#define _INLINE_FUNC_3(_tweed_top_, name, task_name)                         \
405    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
406                       task_name->arg3)
407#define _INLINE_FUNC_4(_tweed_top_, name, task_name)                         \
408    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
409                        task_name->arg3, task_name->arg4)
410#define _INLINE_FUNC_5(_tweed_top_, name, task_name)                         \
411    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
412                       task_name->arg3, task_name->arg4, task_name->arg5)
413#define _INLINE_FUNC_6(_tweed_top_, name, task_name)                         \
414    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
415                       task_name->arg3, task_name->arg4, task_name->arg5,    \
416                       task_name->arg6)
417#define _INLINE_FUNC_7(_tweed_top_, name, task_name)                         \
418    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
419                       task_name->arg3, task_name->arg4, task_name->arg5,    \
420                       task_name->arg6, task_name->arg7)
421#define _INLINE_FUNC_8(_tweed_top_, name, task_name)                         \
422    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
423                       task_name->arg3, task_name->arg4, task_name->arg5,    \
424                       task_name->arg6, task_name->arg7, task_name->arg8)
425#define _INLINE_FUNC_9(_tweed_top_, name, task_name)                         \
426    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
427                       task_name->arg3, task_name->arg4, task_name->arg5,    \
428                       task_name->arg6, task_name->arg7, task_name->arg8,    \
429                       task_name->arg9)
430#define _INLINE_FUNC_10(_tweed_top_, name, task_name)                        \
431    name ## _task_func(_tweed_top_, task_name->arg1, task_name->arg2,        \
432                       task_name->arg3, task_name->arg4, task_name->arg5,    \
433                       task_name->arg6, task_name->arg7, task_name->arg8,    \
434                       task_name->arg9, task_name->arg10)
435
436
437/* Data-structures (only to be used internally by tweed macro's) */
438
439struct generic_task_desc;
440
441/** Task wrapper function type */
442typedef void(*tweed_task_func_t)(struct generic_task_desc * _tweed_top_,
443                                 void * task);
444
445/** Common task structure (extended with arguments and and return
446    types as required by a given task */
447struct generic_task_desc {
448
449    /* func/thief and balarm need to be together, and in this order for the
450       DWCAS operations to work */
451    union {
452#ifdef TWEED_USE_CAS
453        volatile struct worker_desc * thief;
454#endif
455        volatile tweed_task_func_t func;
456    } f;
457    volatile long balarm;
458    int size;
459#ifndef TWEED_USE_CAS
460    volatile struct worker_desc * thief;
461#endif
462};
463
464/** Main task's description */
465struct main_task_desc {
466    struct generic_task_desc task;
467    void* arg1;
468};
469
470/** Worker descriptor */
471struct worker_desc {
472    // task descriptors for this worker
473    struct generic_task_desc * task_desc_stack;
474    // pointer to first task to steal
475    struct generic_task_desc * bot;
476#ifndef TWEED_LOCK_FREE
477    // lock, primarily used by thief
478    spinlock_t lock;
479#endif
480    // worker's thread
481    struct thread * worker_thr;
482    int id;
483    int core_id;
484};
485
486
487/* Library routines, only to be used internally by macro's */
488int init_tweed(int workers_requested,
489               int(*main_func)(struct generic_task_desc *,void*),
490               void* main_args);
491
492struct generic_task_desc * set_top(void);
493
494int sync_stolen(struct generic_task_desc * _tweed_top_);
495
496int handle_stolen_task(struct generic_task_desc * _tweed_top_);
497
498#endif
499