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