Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/kernel.cfa

    r212c2187 rdeca0f5  
    3636#include "invoke.h"
    3737
     38//-----------------------------------------------------------------------------
     39// Some assembly required
     40#if   defined( __i386 )
     41        #define CtxGet( ctx )        \
     42                __asm__ volatile (     \
     43                        "movl %%esp,%0\n"\
     44                        "movl %%ebp,%1\n"\
     45                        : "=rm" (ctx.SP),\
     46                                "=rm" (ctx.FP) \
     47                )
     48
     49        // mxcr : SSE Status and Control bits (control bits are preserved across function calls)
     50        // fcw  : X87 FPU control word (preserved across function calls)
     51        #define __x87_store         \
     52                uint32_t __mxcr;      \
     53                uint16_t __fcw;       \
     54                __asm__ volatile (    \
     55                        "stmxcsr %0\n"  \
     56                        "fnstcw  %1\n"  \
     57                        : "=m" (__mxcr),\
     58                                "=m" (__fcw)  \
     59                )
     60
     61        #define __x87_load         \
     62                __asm__ volatile (   \
     63                        "fldcw  %1\n"  \
     64                        "ldmxcsr %0\n" \
     65                        ::"m" (__mxcr),\
     66                                "m" (__fcw)  \
     67                )
     68
     69#elif defined( __x86_64 )
     70        #define CtxGet( ctx )        \
     71                __asm__ volatile (     \
     72                        "movq %%rsp,%0\n"\
     73                        "movq %%rbp,%1\n"\
     74                        : "=rm" (ctx.SP),\
     75                                "=rm" (ctx.FP) \
     76                )
     77
     78        #define __x87_store         \
     79                uint32_t __mxcr;      \
     80                uint16_t __fcw;       \
     81                __asm__ volatile (    \
     82                        "stmxcsr %0\n"  \
     83                        "fnstcw  %1\n"  \
     84                        : "=m" (__mxcr),\
     85                                "=m" (__fcw)  \
     86                )
     87
     88        #define __x87_load          \
     89                __asm__ volatile (    \
     90                        "fldcw  %1\n"   \
     91                        "ldmxcsr %0\n"  \
     92                        :: "m" (__mxcr),\
     93                                "m" (__fcw)  \
     94                )
     95
     96
     97#elif defined( __ARM_ARCH )
     98#define CtxGet( ctx ) __asm__ ( \
     99                "mov %0,%%sp\n"   \
     100                "mov %1,%%r11\n"   \
     101        : "=rm" (ctx.SP), "=rm" (ctx.FP) )
     102#else
     103        #error unknown hardware architecture
     104#endif
     105
     106//-----------------------------------------------------------------------------
    38107//Start and stop routine for the kernel, declared first to make sure they run first
    39108static void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     
    42111//-----------------------------------------------------------------------------
    43112// Kernel storage
    44 KERNEL_STORAGE(cluster,           mainCluster);
    45 KERNEL_STORAGE(processor,         mainProcessor);
    46 KERNEL_STORAGE(thread_desc,       mainThread);
    47 KERNEL_STORAGE(machine_context_t, mainThreadCtx);
     113KERNEL_STORAGE(cluster,         mainCluster);
     114KERNEL_STORAGE(processor,       mainProcessor);
     115KERNEL_STORAGE(thread_desc,     mainThread);
     116KERNEL_STORAGE(__stack_t,       mainThreadCtx);
    48117
    49118cluster     * mainCluster;
     
    54123struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
    55124}
     125
     126size_t __page_size = 0;
    56127
    57128//-----------------------------------------------------------------------------
     
    66137// Struct to steal stack
    67138struct current_stack_info_t {
    68         machine_context_t ctx;
    69         unsigned int size;              // size of stack
     139        __stack_t * storage;            // pointer to stack object
    70140        void *base;                             // base of stack
    71         void *storage;                  // pointer to stack
    72141        void *limit;                    // stack grows towards stack limit
    73142        void *context;                  // address of cfa_context_t
    74         void *top;                              // address of top of storage
    75143};
    76144
    77145void ?{}( current_stack_info_t & this ) {
    78         CtxGet( this.ctx );
    79         this.base = this.ctx.FP;
    80         this.storage = this.ctx.SP;
     146        __stack_context_t ctx;
     147        CtxGet( ctx );
     148        this.base = ctx.FP;
    81149
    82150        rlimit r;
    83151        getrlimit( RLIMIT_STACK, &r);
    84         this.size = r.rlim_cur;
    85 
    86         this.limit = (void *)(((intptr_t)this.base) - this.size);
     152        size_t size = r.rlim_cur;
     153
     154        this.limit = (void *)(((intptr_t)this.base) - size);
    87155        this.context = &storage_mainThreadCtx;
    88         this.top = this.base;
    89156}
    90157
    91158//-----------------------------------------------------------------------------
    92159// Main thread construction
    93 void ?{}( coStack_t & this, current_stack_info_t * info) with( this ) {
    94         size      = info->size;
    95         storage   = info->storage;
    96         limit     = info->limit;
    97         base      = info->base;
    98         context   = info->context;
    99         top       = info->top;
    100         userStack = true;
    101 }
    102160
    103161void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) {
    104         stack{ info };
     162        stack.storage = info->storage;
     163        with(*stack.storage) {
     164                limit     = info->limit;
     165                base      = info->base;
     166        }
     167        *((intptr_t*)&stack.storage) |= 0x1;
    105168        name = "Main Thread";
    106         errno_ = 0;
    107169        state = Start;
    108170        starter = NULL;
     171        last = NULL;
     172        cancellation = NULL;
    109173}
    110174
    111175void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) {
     176        state = Start;
    112177        self_cor{ info };
    113178        curr_cor = &self_cor;
     
    240305}
    241306
     307static int * __volatile_errno() __attribute__((noinline));
     308static int * __volatile_errno() { asm(""); return &errno; }
     309
    242310// KERNEL ONLY
    243311// runThread runs a thread by context switching
    244312// from the processor coroutine to the target thread
    245 static void runThread(processor * this, thread_desc * dst) {
    246         assert(dst->curr_cor);
     313static void runThread(processor * this, thread_desc * thrd_dst) {
    247314        coroutine_desc * proc_cor = get_coroutine(this->runner);
    248         coroutine_desc * thrd_cor = dst->curr_cor;
    249315
    250316        // Reset the terminating actions here
     
    252318
    253319        // Update global state
    254         kernelTLS.this_thread = dst;
    255 
    256         // Context Switch to the thread
    257         ThreadCtxSwitch(proc_cor, thrd_cor);
    258         // when ThreadCtxSwitch returns we are back in the processor coroutine
     320        kernelTLS.this_thread = thrd_dst;
     321
     322        // set state of processor coroutine to inactive and the thread to active
     323        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     324        thrd_dst->state = Active;
     325
     326        // set context switch to the thread that the processor is executing
     327        verify( thrd_dst->context.SP );
     328        CtxSwitch( &proc_cor->context, &thrd_dst->context );
     329        // when CtxSwitch returns we are back in the processor coroutine
     330
     331        // set state of processor coroutine to active and the thread to inactive
     332        thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive;
     333        proc_cor->state = Active;
    259334}
    260335
     
    262337static void returnToKernel() {
    263338        coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
    264         coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor;
    265         ThreadCtxSwitch(thrd_cor, proc_cor);
     339        thread_desc * thrd_src = kernelTLS.this_thread;
     340
     341        // set state of current coroutine to inactive
     342        thrd_src->state = thrd_src->state == Halted ? Halted : Inactive;
     343        proc_cor->state = Active;
     344        int local_errno = *__volatile_errno();
     345        #if defined( __i386 ) || defined( __x86_64 )
     346                __x87_store;
     347        #endif
     348
     349        // set new coroutine that the processor is executing
     350        // and context switch to it
     351        verify( proc_cor->context.SP );
     352        CtxSwitch( &thrd_src->context, &proc_cor->context );
     353
     354        // set state of new coroutine to active
     355        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     356        thrd_src->state = Active;
     357
     358        #if defined( __i386 ) || defined( __x86_64 )
     359                __x87_load;
     360        #endif
     361        *__volatile_errno() = local_errno;
    266362}
    267363
     
    312408        // to waste the perfectly valid stack create by pthread.
    313409        current_stack_info_t info;
    314         machine_context_t ctx;
    315         info.context = &ctx;
     410        __stack_t ctx;
     411        info.storage = &ctx;
    316412        (proc->runner){ proc, &info };
    317413
    318         __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.base);
     414        __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
    319415
    320416        //Set global state
     
    347443
    348444// KERNEL_ONLY
    349 void kernel_first_resume(processor * this) {
    350         coroutine_desc * src = mainThread->curr_cor;
     445void kernel_first_resume( processor * this ) {
     446        thread_desc * src = mainThread;
    351447        coroutine_desc * dst = get_coroutine(this->runner);
    352448
    353449        verify( ! kernelTLS.preemption_state.enabled );
    354450
    355         create_stack(&dst->stack, dst->stack.size);
     451        __stack_prepare( &dst->stack, 65000 );
    356452        CtxStart(&this->runner, CtxInvokeCoroutine);
    357453
    358454        verify( ! kernelTLS.preemption_state.enabled );
    359455
    360         dst->last = src;
    361         dst->starter = dst->starter ? dst->starter : src;
     456        dst->last = &src->self_cor;
     457        dst->starter = dst->starter ? dst->starter : &src->self_cor;
    362458
    363459        // set state of current coroutine to inactive
    364460        src->state = src->state == Halted ? Halted : Inactive;
    365461
    366         // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch.
    367         // Therefore, when first creating a coroutine, interrupts are enable before calling the main.
    368         // This is consistent with thread creation. However, when creating the main processor coroutine,
    369         // we wan't interrupts to be disabled. Therefore, we double-disable interrupts here so they will
    370         // stay disabled.
    371         disable_interrupts();
    372 
    373462        // context switch to specified coroutine
    374         assert( src->stack.context );
    375         CtxSwitch( src->stack.context, dst->stack.context );
     463        verify( dst->context.SP );
     464        CtxSwitch( &src->context, &dst->context );
    376465        // when CtxSwitch returns we are back in the src coroutine
    377466
     
    380469
    381470        verify( ! kernelTLS.preemption_state.enabled );
     471}
     472
     473// KERNEL_ONLY
     474void kernel_last_resume( processor * this ) {
     475        coroutine_desc * src = &mainThread->self_cor;
     476        coroutine_desc * dst = get_coroutine(this->runner);
     477
     478        verify( ! kernelTLS.preemption_state.enabled );
     479        verify( dst->starter == src );
     480        verify( dst->context.SP );
     481
     482        // context switch to the processor
     483        CtxSwitch( &src->context, &dst->context );
    382484}
    383485
     
    388490void ScheduleThread( thread_desc * thrd ) {
    389491        verify( thrd );
    390         verify( thrd->self_cor.state != Halted );
     492        verify( thrd->state != Halted );
    391493
    392494        verify( ! kernelTLS.preemption_state.enabled );
     
    545647        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    546648
     649        __page_size = sysconf( _SC_PAGESIZE );
     650
    547651        __cfa_dbg_global_clusters.list{ __get };
    548652        __cfa_dbg_global_clusters.lock{};
     
    559663        mainThread = (thread_desc *)&storage_mainThread;
    560664        current_stack_info_t info;
     665        info.storage = (__stack_t*)&storage_mainThreadCtx;
    561666        (*mainThread){ &info };
    562667
     
    627732        // which is currently here
    628733        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    629         returnToKernel();
     734        kernel_last_resume( kernelTLS.this_processor );
    630735        mainThread->self_cor.state = Halted;
    631736
Note: See TracChangeset for help on using the changeset viewer.