Changes in src/libcfa/concurrency/kernel.c [bd98b58:8def349]
- File:
-
- 1 edited
-
src/libcfa/concurrency/kernel.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/kernel.c
rbd98b58 r8def349 32 32 #include "invoke.h" 33 33 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 34 //----------------------------------------------------------------------------- 35 // Kernel storage 70 36 struct processorCtx_t { 71 37 processor * proc; … … 75 41 DECL_COROUTINE(processorCtx_t) 76 42 43 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)] 44 45 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx); 46 KERNEL_STORAGE(cluster, systemCluster); 47 KERNEL_STORAGE(processor, systemProcessor); 48 KERNEL_STORAGE(thread_h, mainThread); 49 KERNEL_STORAGE(machine_context_t, mainThread_context); 50 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 state 60 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 //----------------------------------------------------------------------------- 76 // Main thread construction 77 struct current_stack_info_t { 78 machine_context_t ctx; 79 unsigned int size; // size of stack 80 void *base; // base of stack 81 void *storage; // pointer to stack 82 void *limit; // stack grows towards stack limit 83 void *context; // address of cfa_context_t 84 void *top; // address of top of storage 85 }; 86 87 void ?{}( current_stack_info_t * this ) { 88 CtxGet( &this->ctx ); 89 this->base = this->ctx.FP; 90 this->storage = this->ctx.SP; 91 92 rlimit r; 93 int ret = getrlimit( RLIMIT_STACK, &r); 94 this->size = r.rlim_cur; 95 96 this->limit = (void *)(((intptr_t)this->base) - this->size); 97 this->context = &mainThread_context_storage; 98 this->top = this->base; 99 } 100 101 void ?{}( coStack_t * this, current_stack_info_t * info) { 102 this->size = info->size; 103 this->storage = info->storage; 104 this->limit = info->limit; 105 this->base = info->base; 106 this->context = info->context; 107 this->top = info->top; 108 this->userStack = true; 109 } 110 111 void ?{}( coroutine * this, current_stack_info_t * info) { 112 (&this->stack){ info }; 113 this->name = "Main Thread"; 114 this->errno_ = 0; 115 this->state = Inactive; 116 this->notHalted = true; 117 } 118 119 void ?{}( thread_h * this, current_stack_info_t * info) { 120 (&this->c){ info }; 121 } 122 123 //----------------------------------------------------------------------------- 124 // Processor coroutine 77 125 void ?{}(processorCtx_t * this, processor * proc) { 78 126 (&this->c){}; 79 127 this->proc = proc; 80 } 81 82 void CtxInvokeProcessor(processor * proc) { 83 processorCtx_t proc_cor_storage = {proc}; 84 resume( &proc_cor_storage ); 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 ); 85 180 } 86 181 … … 109 204 } 110 205 206 LIB_DEBUG_PRINTF("Kernel : core %p unlocking thread\n", this); 207 unlock( &this->lock ); 111 208 LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this); 112 209 } … … 133 230 } 134 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 coroutine 236 // which is needed for the 2-step context switch. However, there is no reason 237 // 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 threads 256 257 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 258 // resume it to start it like it normally would, it will just context switch 259 // back to here. Instead directly call the main since we already are on the 260 // 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 135 284 //----------------------------------------------------------------------------- 136 285 // Scheduler routines 137 286 void thread_schedule( thread_h * thrd ) { 138 287 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 288 289 pthread_spinlock_guard guard = { &systemProcessor->cltr->lock }; 139 290 append( &systemProcessor->cltr->ready_queue, thrd ); 140 291 } 141 292 142 293 thread_h * nextThread(cluster * this) { 294 pthread_spinlock_guard guard = { &this->lock }; 143 295 return pop_head( &this->ready_queue ); 144 }145 146 //-----------------------------------------------------------------------------147 // Kernel storage148 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]149 150 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);151 KERNEL_STORAGE(cluster, systemCluster);152 KERNEL_STORAGE(processor, systemProcessor);153 KERNEL_STORAGE(thread_h, mainThread);154 KERNEL_STORAGE(machine_context_t, mainThread_context);155 156 //-----------------------------------------------------------------------------157 // Main thread construction158 struct mainThread_info_t {159 machine_context_t ctx;160 unsigned int size; // size of stack161 void *base; // base of stack162 void *storage; // pointer to stack163 void *limit; // stack grows towards stack limit164 void *context; // address of cfa_context_t165 void *top; // address of top of storage166 };167 168 void ?{}( mainThread_info_t * this ) {169 CtxGet( &this->ctx );170 this->base = this->ctx.FP;171 this->storage = this->ctx.SP;172 173 rlimit r;174 int ret = getrlimit( RLIMIT_STACK, &r);175 this->size = r.rlim_cur;176 177 this->limit = (void *)(((intptr_t)this->base) - this->size);178 this->context = &mainThread_context_storage;179 this->top = this->base;180 }181 182 void ?{}( coStack_t * this, mainThread_info_t * info) {183 this->size = info->size;184 this->storage = info->storage;185 this->limit = info->limit;186 this->base = info->base;187 this->context = info->context;188 this->top = info->top;189 this->userStack = true;190 }191 192 void ?{}( coroutine * this, mainThread_info_t * info) {193 (&this->stack){ info };194 this->name = "Main Thread";195 this->errno_ = 0;196 this->state = Inactive;197 this->notHalted = true;198 }199 200 void ?{}( thread_h * this, mainThread_info_t * info) {201 (&this->c){ info };202 296 } 203 297 … … 210 304 LIB_DEBUG_PRINTF("Kernel : Starting\n"); 211 305 212 mainThread_info_t ctx; 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 ); 213 314 214 315 // Start by initializing the main thread 215 316 mainThread = (thread_h *)&mainThread_storage; 216 mainThread{ & ctx};317 mainThread{ &info }; 217 318 218 319 // Initialize the system cluster … … 220 321 systemCluster{}; 221 322 222 // Initialize the system processor 323 // Initialize the system processor and the system processor ctx 324 // (the coroutine that contains the processing control flow) 223 325 systemProcessor = (processor *)&systemProcessor_storage; 224 systemProcessor{ systemCluster }; 225 226 // Initialize the system processor ctx 227 // (the coroutine that contains the processing control flow) 228 systemProcessor->ctx = (processorCtx_t *)&systemProcessorCtx_storage; 229 systemProcessor->ctx{ systemProcessor }; 326 systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage }; 230 327 231 328 // Add the main thread to the ready queue … … 286 383 287 384 void lock( simple_lock * this ) { 288 append( &this->blocked, this_thread() ); 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 } 289 389 suspend(); 290 390 }
Note:
See TracChangeset
for help on using the changeset viewer.