Changes in / [ad6343e:4a9ccc3]
- Files:
-
- 11 edited
-
doc/proposals/concurrency/thePlan.md (modified) (1 diff)
-
src/driver/cfa.cc (modified) (1 diff)
-
src/examples/thread.c (modified) (3 diffs)
-
src/libcfa/concurrency/coroutines (modified) (1 diff)
-
src/libcfa/concurrency/coroutines.c (modified) (3 diffs)
-
src/libcfa/concurrency/invoke.c (modified) (1 diff)
-
src/libcfa/concurrency/invoke.h (modified) (2 diffs)
-
src/libcfa/concurrency/kernel (modified) (3 diffs)
-
src/libcfa/concurrency/kernel.c (modified) (10 diffs)
-
src/libcfa/concurrency/threads (modified) (2 diffs)
-
src/libcfa/concurrency/threads.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/proposals/concurrency/thePlan.md
rad6343e r4a9ccc3 4 4 done - SimpleBlockingLock. 5 5 done - Synchronisation points in thread destructors. 6 done -Processors & SpinLock.6 Processors & SpinLock. 7 7 8 8 _Phase 2_ : Minimum Viable Product 9 Monitor type and enter/leave mutex member routines 10 Monitors as a language feature (not calling enter/leave by hand) 11 Internal scheduling 9 Basic monitors for synchronisation (No internal/external scheduling). 10 Non-thrash scheduler. 11 Clusters. 12 12 13 13 _Phase 3_ : Kernel features 14 Detach thread 15 Cluster migration 16 Preemption 14 Threads features ex: detach 15 Internal scheduling 17 16 18 17 _Phase 4_ : Monitor features -
src/driver/cfa.cc
rad6343e r4a9ccc3 267 267 } 268 268 nargs += 1; 269 args[nargs] = "-lpthread";270 nargs += 1;271 269 } // if 272 270 #endif //HAVE_LIBCFA -
src/examples/thread.c
rad6343e r4a9ccc3 1 #line 1 "thread.c"2 1 #include <fstream> 3 #include <kernel>4 2 #include <stdlib> 5 3 #include <threads> … … 12 10 }; 13 11 14 DECL_THREAD(MyThread) 15 16 void ?{}( MyThread * this ) { 17 } 12 // DECL_THREAD(MyThread) 18 13 19 14 void ?{}( MyThread * this, unsigned id, unsigned count ) { … … 22 17 } 23 18 24 void main(MyThread* this) {25 sout | "Thread" | this->id | " : Suspending" | this->count | "times" | endl;26 yield();19 // void main(MyThread* this) { 20 // sout | "Thread" | this->id | " : Suspending" | this->count | "times" | endl; 21 // yield(); 27 22 28 for(int i = 0; i < this->count; i++) {29 sout | "Thread" | this->id | " : Suspend No." | i + 1 | endl;30 yield();31 }32 }23 // for(int i = 0; i < this->count; i++) { 24 // sout | "Thread" | this->id | " : Suspend No." | i + 1 | endl; 25 // yield(); 26 // } 27 // } 33 28 34 29 int main(int argc, char* argv[]) { 35 30 36 unsigned itterations = 10u;37 if(argc == 2) {38 int val = ato(argv[1]);39 assert(val >= 0);40 itterations = val;41 }31 // unsigned itterations = 10u; 32 // if(argc == 2) { 33 // int val = ato(argv[1]); 34 // assert(val >= 0); 35 // itterations = val; 36 // } 42 37 43 38 sout | "User main begin" | endl; 44 39 45 { 46 processor p; 47 { 48 thread(MyThread) thread1 = { 1u, itterations }; 49 thread(MyThread) thread2 = { 2u, itterations }; 50 } 51 } 40 // { 41 // thread(MyThread) thread1 = { 1u, itterations }; 42 // thread(MyThread) thread2 = { 2u, itterations }; 43 // } 52 44 53 45 sout | "User main end" | endl; -
src/libcfa/concurrency/coroutines
rad6343e r4a9ccc3 73 73 74 74 assertf( src->last != 0, 75 "Attempt to suspend coroutine \"%.256s\"(%p) that has never been resumed.\n"75 "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n" 76 76 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", 77 77 src->name, src ); 78 78 assertf( src->last->notHalted, 79 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\"(%p).\n"79 "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n" 80 80 "Possible cause is terminated coroutine's main routine has already returned.", 81 81 src->name, src, src->last->name, src->last ); -
src/libcfa/concurrency/coroutines.c
rad6343e r4a9ccc3 1 // -*- Mode: CFA -*-2 1 // 3 2 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo … … 32 31 #include "invoke.h" 33 32 34 extern processor * get_this_processor();33 /*thread_local*/ extern processor * this_processor; 35 34 36 35 //----------------------------------------------------------------------------- … … 111 110 112 111 // set new coroutine that task is executing 113 get_this_processor()->current_coroutine = dst;112 this_processor->current_coroutine = dst; 114 113 115 114 // context switch to specified coroutine -
src/libcfa/concurrency/invoke.c
rad6343e r4a9ccc3 1 // -*- Mode: CFA -*-2 //3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo4 //5 // The contents of this file are covered under the licence agreement in the6 // file "LICENCE" distributed with Cforall.7 //8 // invoke.c --9 //10 // Author : Thierry Delisle11 // Created On : Tue Jan 17 12:27:26 201612 // Last Modified By : Thierry Delisle13 // Last Modified On : --14 // Update Count : 015 //16 1 17 2 #include <stdbool.h> -
src/libcfa/concurrency/invoke.h
rad6343e r4a9ccc3 1 // -*- Mode: CFA -*-2 //3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo4 //5 // The contents of this file are covered under the licence agreement in the6 // file "LICENCE" distributed with Cforall.7 //8 // invoke.h --9 //10 // Author : Thierry Delisle11 // Created On : Tue Jan 17 12:27:26 201612 // Last Modified By : Thierry Delisle13 // Last Modified On : --14 // Update Count : 015 //16 17 1 #include <stdbool.h> 18 2 #include <stdint.h> … … 27 11 28 12 #define unlikely(x) __builtin_expect(!!(x), 0) 29 #define thread_local _Thread_local30 13 #define SCHEDULER_CAPACITY 10 31 14 -
src/libcfa/concurrency/kernel
rad6343e r4a9ccc3 22 22 #include "invoke.h" 23 23 24 extern "C" {25 #include <pthread.h>26 }27 28 24 //----------------------------------------------------------------------------- 29 25 // Cluster 30 26 struct cluster { 31 27 simple_thread_list ready_queue; 32 pthread_spinlock_t lock;33 28 }; 34 29 … … 43 38 coroutine * current_coroutine; 44 39 thread_h * current_thread; 45 pthread_t kernel_thread; 46 simple_lock lock; 47 volatile bool terminated; 40 bool terminated; 48 41 }; 49 42 50 void ?{}(processor * this);51 43 void ?{}(processor * this, cluster * cltr); 52 44 void ^?{}(processor * this); … … 62 54 void unlock( simple_lock * ); 63 55 64 struct pthread_spinlock_guard {65 pthread_spinlock_t * lock;66 };67 68 static inline void ?{}( pthread_spinlock_guard * this, pthread_spinlock_t * lock ) {69 this->lock = lock;70 pthread_spin_lock( this->lock );71 }72 73 static inline void ^?{}( pthread_spinlock_guard * this ) {74 pthread_spin_unlock( this->lock );75 }76 77 // //Simple spinlock implementation from78 // //http://stackoverflow.com/questions/1383363/is-my-spin-lock-implementation-correct-and-optimal79 // //Not optimal but correct80 // #define VOL81 82 // struct simple_spinlock {83 // VOL int lock;84 // };85 86 // extern VOL int __sync_lock_test_and_set( VOL int *, VOL int);87 // extern void __sync_synchronize();88 89 // static inline void lock( simple_spinlock * this ) {90 // while (__sync_lock_test_and_set(&this->lock, 1)) {91 // // Do nothing. This GCC builtin instruction92 // // ensures memory barrier.93 // }94 // }95 96 // static inline void unlock( simple_spinlock * this ) {97 // __sync_synchronize(); // Memory barrier.98 // this->lock = 0;99 // }100 101 56 #endif //KERNEL_H 102 57 -
src/libcfa/concurrency/kernel.c
rad6343e r4a9ccc3 32 32 #include "invoke.h" 33 33 34 //----------------------------------------------------------------------------- 35 // Kernel storage 34 cluster * systemCluster; 35 processor * systemProcessor; 36 thread_h * mainThread; 37 38 void kernel_startup(void) __attribute__((constructor(101))); 39 void kernel_shutdown(void) __attribute__((destructor(101))); 40 41 void ?{}(processor * this, cluster * cltr) { 42 this->ctx = NULL; 43 this->cltr = cltr; 44 this->terminated = false; 45 } 46 47 void ^?{}(processor * this) {} 48 49 void ?{}(cluster * this) { 50 ( &this->ready_queue ){}; 51 } 52 53 void ^?{}(cluster * this) {} 54 55 //----------------------------------------------------------------------------- 56 // Global state 57 58 /*thread_local*/ processor * this_processor; 59 60 coroutine * this_coroutine(void) { 61 return this_processor->current_coroutine; 62 } 63 64 thread_h * this_thread(void) { 65 return this_processor->current_thread; 66 } 67 68 //----------------------------------------------------------------------------- 69 // Processor coroutine 36 70 struct processorCtx_t { 37 71 processor * proc; … … 41 75 DECL_COROUTINE(processorCtx_t) 42 76 77 void ?{}(processorCtx_t * this, processor * proc) { 78 (&this->c){}; 79 this->proc = proc; 80 } 81 82 void CtxInvokeProcessor(processor * proc) { 83 processorCtx_t proc_cor_storage = {proc}; 84 resume( &proc_cor_storage ); 85 } 86 87 //----------------------------------------------------------------------------- 88 // Processor running routines 89 void main(processorCtx_t * ctx); 90 thread_h * nextThread(cluster * this); 91 void runThread(processor * this, thread_h * dst); 92 void spin(processor * this, unsigned int * spin_count); 93 94 void main(processorCtx_t * ctx) { 95 processor * this = ctx->proc; 96 LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this); 97 98 thread_h * readyThread = NULL; 99 for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) { 100 101 readyThread = nextThread( this->cltr ); 102 103 if(readyThread) { 104 runThread(this, readyThread); 105 spin_count = 0; 106 } else { 107 spin(this, &spin_count); 108 } 109 } 110 111 LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this); 112 } 113 114 void runThread(processor * this, thread_h * dst) { 115 coroutine * proc_ctx = get_coroutine(this->ctx); 116 coroutine * thrd_ctx = get_coroutine(dst); 117 thrd_ctx->last = proc_ctx; 118 119 // context switch to specified coroutine 120 // Which is now the current_coroutine 121 // LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine); 122 this->current_thread = dst; 123 this->current_coroutine = thrd_ctx; 124 CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context ); 125 this->current_coroutine = proc_ctx; 126 // LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine); 127 128 // when CtxSwitch returns we are back in the processor coroutine 129 } 130 131 void spin(processor * this, unsigned int * spin_count) { 132 (*spin_count)++; 133 } 134 135 //----------------------------------------------------------------------------- 136 // Scheduler routines 137 void thread_schedule( thread_h * thrd ) { 138 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 139 append( &systemProcessor->cltr->ready_queue, thrd ); 140 } 141 142 thread_h * nextThread(cluster * this) { 143 return pop_head( &this->ready_queue ); 144 } 145 146 //----------------------------------------------------------------------------- 147 // Kernel storage 43 148 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)] 44 149 … … 49 154 KERNEL_STORAGE(machine_context_t, mainThread_context); 50 155 51 cluster * systemCluster;52 processor * systemProcessor;53 thread_h * mainThread;54 55 void kernel_startup(void) __attribute__((constructor(101)));56 void kernel_shutdown(void) __attribute__((destructor(101)));57 58 //-----------------------------------------------------------------------------59 // Global state60 61 thread_local processor * this_processor;62 63 processor * get_this_processor() {64 return this_processor;65 }66 67 coroutine * this_coroutine(void) {68 return this_processor->current_coroutine;69 }70 71 thread_h * this_thread(void) {72 return this_processor->current_thread;73 }74 75 156 //----------------------------------------------------------------------------- 76 157 // Main thread construction 77 struct current_stack_info_t {158 struct mainThread_info_t { 78 159 machine_context_t ctx; 79 160 unsigned int size; // size of stack … … 85 166 }; 86 167 87 void ?{}( current_stack_info_t * this ) {168 void ?{}( mainThread_info_t * this ) { 88 169 CtxGet( &this->ctx ); 89 170 this->base = this->ctx.FP; … … 99 180 } 100 181 101 void ?{}( coStack_t * this, current_stack_info_t * info) {182 void ?{}( coStack_t * this, mainThread_info_t * info) { 102 183 this->size = info->size; 103 184 this->storage = info->storage; … … 109 190 } 110 191 111 void ?{}( coroutine * this, current_stack_info_t * info) {192 void ?{}( coroutine * this, mainThread_info_t * info) { 112 193 (&this->stack){ info }; 113 194 this->name = "Main Thread"; … … 117 198 } 118 199 119 void ?{}( thread_h * this, current_stack_info_t * info) {200 void ?{}( thread_h * this, mainThread_info_t * info) { 120 201 (&this->c){ info }; 121 }122 123 //-----------------------------------------------------------------------------124 // Processor coroutine125 void ?{}(processorCtx_t * this, processor * proc) {126 (&this->c){};127 this->proc = proc;128 proc->ctx = this;129 }130 131 void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) {132 (&this->c){ info };133 this->proc = proc;134 proc->ctx = this;135 }136 137 void start(processor * this);138 139 void ?{}(processor * this) {140 this{ systemCluster };141 }142 143 void ?{}(processor * this, cluster * cltr) {144 this->cltr = cltr;145 this->current_coroutine = NULL;146 this->current_thread = NULL;147 (&this->lock){};148 this->terminated = false;149 150 start( this );151 }152 153 void ?{}(processor * this, cluster * cltr, processorCtx_t * ctx) {154 this->cltr = cltr;155 this->current_coroutine = NULL;156 this->current_thread = NULL;157 (&this->lock){};158 this->terminated = false;159 160 this->ctx = ctx;161 LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", ctx);162 ctx{ this };163 }164 165 void ^?{}(processor * this) {166 if( ! this->terminated ) {167 LIB_DEBUG_PRINTF("Kernel : core %p signaling termination\n", this);168 this->terminated = true;169 lock( &this->lock );170 }171 }172 173 void ?{}(cluster * this) {174 ( &this->ready_queue ){};175 pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE );176 }177 178 void ^?{}(cluster * this) {179 pthread_spin_destroy( &this->lock );180 }181 182 //-----------------------------------------------------------------------------183 // Processor running routines184 void main(processorCtx_t * ctx);185 thread_h * nextThread(cluster * this);186 void runThread(processor * this, thread_h * dst);187 void spin(processor * this, unsigned int * spin_count);188 189 void main(processorCtx_t * ctx) {190 processor * this = ctx->proc;191 LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this);192 193 thread_h * readyThread = NULL;194 for( unsigned int spin_count = 0; ! this->terminated; spin_count++ ) {195 196 readyThread = nextThread( this->cltr );197 198 if(readyThread) {199 runThread(this, readyThread);200 spin_count = 0;201 } else {202 spin(this, &spin_count);203 }204 }205 206 LIB_DEBUG_PRINTF("Kernel : core %p unlocking thread\n", this);207 unlock( &this->lock );208 LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this);209 }210 211 void runThread(processor * this, thread_h * dst) {212 coroutine * proc_ctx = get_coroutine(this->ctx);213 coroutine * thrd_ctx = get_coroutine(dst);214 thrd_ctx->last = proc_ctx;215 216 // context switch to specified coroutine217 // Which is now the current_coroutine218 // LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);219 this->current_thread = dst;220 this->current_coroutine = thrd_ctx;221 CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );222 this->current_coroutine = proc_ctx;223 // LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, current_coroutine);224 225 // when CtxSwitch returns we are back in the processor coroutine226 }227 228 void spin(processor * this, unsigned int * spin_count) {229 (*spin_count)++;230 }231 232 void * CtxInvokeProcessor(void * arg) {233 processor * proc = (processor *) arg;234 this_processor = proc;235 // SKULLDUGGERY: We want to create a context for the processor coroutine236 // which is needed for the 2-step context switch. However, there is no reason237 // to waste the perfectly valid stack create by pthread.238 current_stack_info_t info;239 machine_context_t ctx;240 info.context = &ctx;241 processorCtx_t proc_cor_storage = { proc, &info };242 243 proc->current_coroutine = &proc->ctx->c;244 proc->current_thread = NULL;245 246 LIB_DEBUG_PRINTF("Kernel : core %p created (%p)\n", proc, proc->ctx);247 248 // LIB_DEBUG_PRINTF("Kernel : core base : %p \n", info.base );249 // LIB_DEBUG_PRINTF("Kernel : core storage : %p \n", info.storage );250 // LIB_DEBUG_PRINTF("Kernel : core size : %x \n", info.size );251 // LIB_DEBUG_PRINTF("Kernel : core limit : %p \n", info.limit );252 // LIB_DEBUG_PRINTF("Kernel : core context : %p \n", info.context );253 // LIB_DEBUG_PRINTF("Kernel : core top : %p \n", info.top );254 255 //We now have a proper context from which to schedule threads256 257 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't258 // resume it to start it like it normally would, it will just context switch259 // back to here. Instead directly call the main since we already are on the260 // appropriate stack.261 proc_cor_storage.c.state = Active;262 main( &proc_cor_storage );263 proc_cor_storage.c.state = Halt;264 proc_cor_storage.c.notHalted = false;265 266 LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->ctx);267 268 return NULL;269 }270 271 void start(processor * this) {272 LIB_DEBUG_PRINTF("Kernel : Starting core %p\n", this);273 274 pthread_attr_t attributes;275 pthread_attr_init( &attributes );276 277 pthread_create( &this->kernel_thread, &attributes, CtxInvokeProcessor, (void*)this );278 279 pthread_attr_destroy( &attributes );280 281 LIB_DEBUG_PRINTF("Kernel : core %p started\n", this);282 }283 284 //-----------------------------------------------------------------------------285 // Scheduler routines286 void thread_schedule( thread_h * thrd ) {287 assertf( thrd->next == NULL, "Expected null got %p", thrd->next );288 289 pthread_spinlock_guard guard = { &systemProcessor->cltr->lock };290 append( &systemProcessor->cltr->ready_queue, thrd );291 }292 293 thread_h * nextThread(cluster * this) {294 pthread_spinlock_guard guard = { &this->lock };295 return pop_head( &this->ready_queue );296 202 } 297 203 … … 304 210 LIB_DEBUG_PRINTF("Kernel : Starting\n"); 305 211 306 current_stack_info_t info; 307 308 // LIB_DEBUG_PRINTF("Kernel : core base : %p \n", info.base ); 309 // LIB_DEBUG_PRINTF("Kernel : core storage : %p \n", info.storage ); 310 // LIB_DEBUG_PRINTF("Kernel : core size : %x \n", info.size ); 311 // LIB_DEBUG_PRINTF("Kernel : core limit : %p \n", info.limit ); 312 // LIB_DEBUG_PRINTF("Kernel : core context : %p \n", info.context ); 313 // LIB_DEBUG_PRINTF("Kernel : core top : %p \n", info.top ); 212 mainThread_info_t ctx; 314 213 315 214 // Start by initializing the main thread 316 215 mainThread = (thread_h *)&mainThread_storage; 317 mainThread{ & info};216 mainThread{ &ctx }; 318 217 319 218 // Initialize the system cluster … … 321 220 systemCluster{}; 322 221 323 // Initialize the system processor and the system processor ctx 222 // Initialize the system processor 223 systemProcessor = (processor *)&systemProcessor_storage; 224 systemProcessor{ systemCluster }; 225 226 // Initialize the system processor ctx 324 227 // (the coroutine that contains the processing control flow) 325 systemProcessor = (processor *)&systemProcessor_storage;326 systemProcessor { systemCluster, (processorCtx_t *)&systemProcessorCtx_storage};228 systemProcessor->ctx = (processorCtx_t *)&systemProcessorCtx_storage; 229 systemProcessor->ctx{ systemProcessor }; 327 230 328 231 // Add the main thread to the ready queue … … 383 286 384 287 void lock( simple_lock * this ) { 385 { 386 pthread_spinlock_guard guard = { &systemCluster->lock }; //HUGE TEMP HACK which only works if we have a single cluster and is stupid 387 append( &this->blocked, this_thread() ); 388 } 288 append( &this->blocked, this_thread() ); 389 289 suspend(); 390 290 } -
src/libcfa/concurrency/threads
rad6343e r4a9ccc3 27 27 // Anything that implements this trait can be resumed. 28 28 // Anything that is resumed is a coroutine. 29 trait is_thread(dtype T | sized(T)) {29 trait is_thread(dtype T /*| sized(T)*/) { 30 30 void main(T* this); 31 31 thread_h* get_thread(T* this); 32 /*void ?{}(T*); 33 void ^?{}(T*);*/ 32 34 }; 33 35 34 36 #define DECL_THREAD(X) static inline thread_h* get_thread(X* this) { return &this->t; } void main(X* this); 35 37 36 forall( dtype T | sized(T)| is_thread(T) )38 forall(otype T | is_thread(T) ) 37 39 static inline coroutine* get_coroutine(T* this) { 38 40 return &get_thread(this)->c; … … 53 55 // thread runner 54 56 // Structure that actually start and stop threads 55 forall( dtype T | sized(T)| is_thread(T) )57 forall(otype T | is_thread(T) ) 56 58 struct thread { 57 59 T handle; 58 60 }; 59 61 60 forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T*); })62 forall(otype T | is_thread(T) ) 61 63 void ?{}( thread(T)* this ); 62 64 63 forall( dtype T, ttype P | sized(T)| is_thread(T) | { void ?{}(T*, P); } )65 forall(otype T, ttype P | is_thread(T) | { void ?{}(T*, P); } ) 64 66 void ?{}( thread(T)* this, P params ); 65 67 66 forall( dtype T | sized(T) | is_thread(T) | { void ^?{}(T*); })68 forall(otype T | is_thread(T) ) 67 69 void ^?{}( thread(T)* this ); 68 70 -
src/libcfa/concurrency/threads.c
rad6343e r4a9ccc3 27 27 } 28 28 29 extern processor * get_this_processor();29 /*thread_local*/ extern processor * this_processor; 30 30 31 31 //----------------------------------------------------------------------------- 32 32 // Forward declarations 33 forall( dtype T | sized(T)| is_thread(T) )33 forall(otype T | is_thread(T) ) 34 34 void start( T* this ); 35 35 36 forall( dtype T | sized(T)| is_thread(T) )36 forall(otype T | is_thread(T) ) 37 37 void stop( T* this ); 38 38 … … 42 42 void ?{}(thread_h* this) { 43 43 (&this->c){}; 44 this->c.name = "Anonymous Coroutine";45 44 (&this->lock){}; 46 45 this->next = NULL; … … 51 50 } 52 51 53 forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T*); })52 forall(otype T | is_thread(T) ) 54 53 void ?{}( thread(T)* this ) { 55 54 (&this->handle){}; … … 57 56 } 58 57 59 forall( dtype T, ttype P | sized(T)| is_thread(T) | { void ?{}(T*, P); } )58 forall(otype T, ttype P | is_thread(T) | { void ?{}(T*, P); } ) 60 59 void ?{}( thread(T)* this, P params ) { 61 60 (&this->handle){ params }; … … 63 62 } 64 63 65 forall( dtype T | sized(T) | is_thread(T) | { void ^?{}(T*); })64 forall(otype T | is_thread(T) ) 66 65 void ^?{}( thread(T)* this ) { 67 66 stop(&this->handle); … … 78 77 extern void thread_schedule( thread_h * ); 79 78 80 forall( dtype T | sized(T) | is_thread(T))79 forall(otype T | is_thread(T)) 81 80 void start( T* this ) { 82 81 coroutine* thrd_c = get_coroutine(this); 83 82 thread_h* thrd_h = get_thread (this); 84 83 thrd_c->last = this_coroutine(); 85 get_this_processor()->current_coroutine = thrd_c;84 this_processor->current_coroutine = thrd_c; 86 85 87 86 // LIB_DEBUG_PRINTF("Thread start : %p (t %p, c %p)\n", handle, thrd_c, thrd_h); … … 94 93 } 95 94 96 forall( dtype T | sized(T)| is_thread(T) )95 forall(otype T | is_thread(T) ) 97 96 void stop( T* this ) { 98 97 thread_h* thrd = get_thread(this);
Note:
See TracChangeset
for help on using the changeset viewer.