Ignore:
Timestamp:
Feb 6, 2017, 4:19:53 PM (9 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
424931d, fe26fbf
Parents:
c0aa336 (diff), 6a5f0e7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

Location:
src/libcfa/concurrency
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/CtxSwitch-x86_64.S

    rc0aa336 rb4d65c7  
    4949        // Save volatile registers on the stack.
    5050
     51        subq   $8,%rsp
     52        stmxcsr 0(%rsp)         // 4 bytes
     53        fnstcw  4(%rsp)         // 2 bytes
    5154        pushq %r15
    5255        pushq %r14
     
    7275        popq %r14
    7376        popq %r15
     77        fldcw   4(%rsp)
     78        ldmxcsr 0(%rsp)
     79        addq $8,%rsp
    7480
    7581        // Return to thread.
  • src/libcfa/concurrency/coroutines

    rc0aa336 rb4d65c7  
    3030};
    3131
    32 #define DECL_COROUTINE(X) static inline coroutine* get_coroutine(X* this) { return &this->c; } void main(X* this);
     32#define DECL_COROUTINE(X) static inline coroutine* get_coroutine(X* this) { return &this->c; } void main(X* this)
    3333
    3434//-----------------------------------------------------------------------------
     
    6565
    6666// Private wrappers for context switch and stack creation
    67 extern void corCxtSw(coroutine * src, coroutine * dst);
     67extern void CoroutineCtxSwitch(coroutine * src, coroutine * dst);
    6868extern void create_stack( coStack_t * this, unsigned int storageSize );
    6969
     
    8181                src->name, src, src->last->name, src->last );
    8282
    83         corCxtSw( src, src->last );
     83        CoroutineCtxSwitch( src, src->last );
    8484}
    8585
     
    107107
    108108      // always done for performance testing
    109         corCxtSw( src, dst );
     109        CoroutineCtxSwitch( src, dst );
     110}
     111
     112static inline void resume(coroutine * dst) {
     113        coroutine * src = this_coroutine();             // optimization
     114
     115      // not resuming self ?
     116        if ( src != dst ) {
     117                assertf( dst->notHalted ,
     118                        "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"
     119                        "Possible cause is terminated coroutine's main routine has already returned.",
     120                        src->name, src, dst->name, dst );
     121
     122            // set last resumer
     123                dst->last = src;
     124        } // if
     125
     126      // always done for performance testing
     127        CoroutineCtxSwitch( src, dst );
    110128}
    111129
  • src/libcfa/concurrency/coroutines.c

    rc0aa336 rb4d65c7  
    9898}
    9999
    100 // We need to call suspend from invoke.c, so we expose this wrapper that
    101 // is not inline (We can't inline Cforall in C)
    102 void suspend_no_inline(void) {
    103         suspend();
    104 }
    105 
    106 void corCxtSw(coroutine* src, coroutine* dst) {
     100// Wrapper for co
     101void CoroutineCtxSwitch(coroutine* src, coroutine* dst) {
    107102        // THREAD_GETMEM( This )->disableInterrupts();
    108103
     
    167162}
    168163
     164// We need to call suspend from invoke.c, so we expose this wrapper that
     165// is not inline (We can't inline Cforall in C)
     166extern "C" {
     167        void __suspend_internal(void) {
     168                suspend();
     169        }
     170}
     171
    169172// Local Variables: //
    170173// mode: c //
  • src/libcfa/concurrency/invoke.c

    rc0aa336 rb4d65c7  
    2828// Called from the kernel when starting a coroutine or task so must switch back to user mode.
    2929
    30 extern void __suspend_no_inline__F___1(void);
    31 extern void __signal_termination__F_P7sthread__1(struct thread*);
     30extern void __suspend_internal(void);
     31extern void __thread_signal_termination(struct thread*);
    3232
    3333void CtxInvokeCoroutine(
     
    4141
    4242      if(cor->state == Primed) {
    43             __suspend_no_inline__F___1();
     43            __suspend_internal();
    4444      }
    4545
     
    5252
    5353      //Final suspend, should never return
    54       __suspend_no_inline__F___1();
    55       assertf(false, "Resumed dead coroutine");
     54      __suspend_internal();
     55      abortf("Resumed dead coroutine");
    5656}
    5757
     
    6161      void *this
    6262) {
    63       // LIB_DEBUG_PRINTF("Invoke Thread : Received %p (main %p, get_t %p)\n", this, main, get_thread);
    64 
    65       __suspend_no_inline__F___1();
     63      __suspend_internal();
    6664
    6765      struct thread* thrd = get_thread( this );
     
    7270      main( this );
    7371
    74       __signal_termination__F_P7sthread__1(thrd);
     72      __thread_signal_termination(thrd);
    7573
    7674      //Final suspend, should never return
    77       __suspend_no_inline__F___1();
    78       assertf(false, "Resumed dead thread");
     75      __suspend_internal();
     76      abortf("Resumed dead thread");
    7977}
    8078
     
    111109      struct FakeStack {
    112110            void *fixedRegisters[5];                    // fixed registers rbx, r12, r13, r14, r15
    113             void *rturn;                                        // where to go on return from uSwitch
     111            uint32_t mxcr;                                  // SSE Status and Control bits (control bits are preserved across function calls)
     112            uint16_t fcw;                                   // X97 FPU control word (preserved across function calls)
     113            void *rturn;                                      // where to go on return from uSwitch
    114114            void *dummyReturn;                          // NULL return address to provide proper alignment
    115115      };
     
    122122      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = this;
    123123      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = invoke;
     124      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520
     125      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F;  //Vol. 1 8-7
    124126#else
    125127      #error Only __i386__ and __x86_64__ is supported for threads in cfa
  • src/libcfa/concurrency/kernel.c

    rc0aa336 rb4d65c7  
    1515//
    1616
     17//Start and stop routine for the kernel, declared first to make sure they run first
     18void kernel_startup(void)  __attribute__((constructor(101)));
     19void kernel_shutdown(void) __attribute__((destructor(101)));
     20
    1721//Header
    1822#include "kernel"
     
    3943};
    4044
    41 DECL_COROUTINE(processorCtx_t)
     45DECL_COROUTINE(processorCtx_t);
    4246
    4347#define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]
     
    5256processor * systemProcessor;
    5357thread * mainThread;
    54 
    55 void kernel_startup(void)  __attribute__((constructor(101)));
    56 void kernel_shutdown(void) __attribute__((destructor(101)));
    5758
    5859//-----------------------------------------------------------------------------
     
    184185void main(processorCtx_t * ctx);
    185186thread * nextThread(cluster * this);
    186 void runThread(processor * this, thread * dst);
     187void scheduleInternal(processor * this, thread * dst);
    187188void spin(processor * this, unsigned int * spin_count);
    188189
     
    197198
    198199                if(readyThread) {
    199                         runThread(this, readyThread);
     200                        scheduleInternal(this, readyThread);
    200201                        spin_count = 0;
    201202                } else {
     
    209210}
    210211
    211 void runThread(processor * this, thread * dst) {
     212//Declarations for scheduleInternal
     213extern void ThreadCtxSwitch(coroutine * src, coroutine * dst);
     214
     215// scheduleInternal runs a thread by context switching
     216// from the processor coroutine to the target thread
     217void scheduleInternal(processor * this, thread * dst) {
     218        // coroutine * proc_ctx = get_coroutine(this->ctx);
     219        // coroutine * thrd_ctx = get_coroutine(dst);
     220
     221        // //Update global state
     222        // this->current_thread = dst;
     223
     224        // // Context Switch to the thread
     225        // ThreadCtxSwitch(proc_ctx, thrd_ctx);
     226        // // when ThreadCtxSwitch returns we are back in the processor coroutine
     227
    212228        coroutine * proc_ctx = get_coroutine(this->ctx);
    213229        coroutine * thrd_ctx = get_coroutine(dst);
    214         thrd_ctx->last = proc_ctx;
    215 
    216         // context switch to specified coroutine
    217         // Which is now the current_coroutine
    218         // 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 coroutine
    226 }
    227 
     230      thrd_ctx->last = proc_ctx;
     231 
     232      // context switch to specified coroutine
     233      // Which is now the current_coroutine
     234      LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);
     235      this->current_thread = dst;
     236      this->current_coroutine = thrd_ctx;
     237      CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context );
     238      this->current_coroutine = proc_ctx;
     239      LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);
     240 
     241      // when CtxSwitch returns we are back in the processor coroutine
     242}
     243
     244// Handles spinning logic
     245// TODO : find some strategy to put cores to sleep after some time
    228246void spin(processor * this, unsigned int * spin_count) {
    229247        (*spin_count)++;
    230248}
    231249
     250// Context invoker for processors
     251// This is the entry point for processors (kernel threads)
     252// It effectively constructs a coroutine by stealing the pthread stack
    232253void * CtxInvokeProcessor(void * arg) {
    233254        processor * proc = (processor *) arg;
     
    241262        processorCtx_t proc_cor_storage = { proc, &info };
    242263
     264        //Set global state
    243265        proc->current_coroutine = &proc->ctx->c;
    244266        proc->current_thread = NULL;
    245267
     268        //We now have a proper context from which to schedule threads
    246269        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
    256270
    257271        // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
     
    264278      proc_cor_storage.c.notHalted = false;
    265279
     280        // Main routine of the core returned, the core is now fully terminated
    266281        LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->ctx);       
    267282
  • src/libcfa/concurrency/threads

    rc0aa336 rb4d65c7  
    2727// Anything that implements this trait can be resumed.
    2828// Anything that is resumed is a coroutine.
    29 trait is_thread(dtype T | sized(T)) {
     29trait is_thread(dtype T) {
    3030      void main(T* this);
    3131      thread* get_thread(T* this);
    3232};
    3333
    34 #define DECL_THREAD(X) static inline thread* get_thread(X* this) { return &this->t; } void main(X* this);
     34#define DECL_THREAD(X) thread* get_thread(X* this) { return &this->t; } void main(X* this)
    3535
    36 forall( dtype T | sized(T) | is_thread(T) )
     36forall( dtype T | is_thread(T) )
    3737static inline coroutine* get_coroutine(T* this) {
    3838        return &get_thread(this)->c;
  • src/libcfa/concurrency/threads.c

    rc0aa336 rb4d65c7  
    3131//-----------------------------------------------------------------------------
    3232// Forward declarations
    33 forall( dtype T | sized(T) | is_thread(T) )
     33forall( dtype T | is_thread(T) )
    3434void start( T* this );
    3535
    36 forall( dtype T | sized(T) | is_thread(T) )
     36forall( dtype T | is_thread(T) )
    3737void stop( T* this );
    3838
     
    7878extern void thread_schedule( thread * );
    7979
    80 forall( dtype T | sized(T) | is_thread(T) )
     80forall( dtype T | is_thread(T) )
    8181void start( T* this ) {
    8282        coroutine* thrd_c = get_coroutine(this);
     
    8585        get_this_processor()->current_coroutine = thrd_c;
    8686
    87         // LIB_DEBUG_PRINTF("Thread start : %p (t %p, c %p)\n", handle, thrd_c, thrd_h);
     87        LIB_DEBUG_PRINTF("Thread start : %p (t %p, c %p)\n", this, thrd_c, thrd_h);
    8888
    8989        create_stack(&thrd_c->stack, thrd_c->stack.size);
     
    9191        CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context );
    9292
     93        LIB_DEBUG_PRINTF("Thread started : %p (t %p, c %p)\n", this, thrd_c, thrd_h);
     94
    9395        thread_schedule(thrd_h);
    9496}
    9597
    96 forall( dtype T | sized(T) | is_thread(T) )
     98forall( dtype T | is_thread(T) )
    9799void stop( T* this ) {
    98100        thread*  thrd = get_thread(this);
     
    102104}
    103105
    104 void signal_termination( thread * this ) {
    105         this->c.state = Halt;
    106       this->c.notHalted = false;
    107         unlock( &this->lock );
    108 }
    109 
    110106void yield( void ) {
    111107        thread_schedule( this_thread() );
    112108        suspend();
     109}
     110
     111void ThreadCtxSwitch(coroutine* src, coroutine* dst) {
     112        dst->last = src;
     113
     114        // set state of current coroutine to inactive
     115        src->state = Inactive;
     116
     117        // set new coroutine that task is executing
     118        get_this_processor()->current_coroutine = dst; 
     119
     120        // context switch to specified coroutine
     121        CtxSwitch( src->stack.context, dst->stack.context );
     122        // when CtxSwitch returns we are back in the src coroutine
     123
     124        // set state of new coroutine to active
     125        src->state = Active;
     126}
     127
     128// C Helper to signal the termination of a thread
     129// Used in invoke.c
     130extern "C" {
     131        void __thread_signal_termination( thread * this ) {
     132                this->c.state = Halt;
     133                this->c.notHalted = false;
     134                unlock( &this->lock );
     135        }
    113136}
    114137
Note: See TracChangeset for help on using the changeset viewer.