Changeset b4d65c7 for src/libcfa


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, stuck-waitfor-destruct, 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
Files:
10 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
  • src/libcfa/containers/vector

    rc0aa336 rb4d65c7  
    118118}
    119119
    120 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
    121 static inline const T* cbegin(const vector(T, allocator_t)* this)
    122 {
    123         return data(&this->storage);
    124 }
     120// forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     121// static inline const T* cbegin(const vector(T, allocator_t)* this)
     122// {
     123//      return data(&this->storage);
     124// }
    125125
    126126forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     
    130130}
    131131
    132 forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
    133 static inline const T* cend(const vector(T, allocator_t)* this)
    134 {
    135         return data(&this->storage) + this->size;
    136 }
     132// forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
     133// static inline const T* cend(const vector(T, allocator_t)* this)
     134// {
     135//      return data(&this->storage) + this->size;
     136// }
    137137
    138138//------------------------------------------------------------------------------
  • src/libcfa/stdlib

    rc0aa336 rb4d65c7  
    2929
    3030extern "C" { void * malloc( size_t ); }                                 // use default C routine for void *
    31 forall( otype T ) T * malloc( void );
    32 forall( otype T ) T * malloc( char fill );
    33 forall( otype T ) T * malloc( T * ptr, size_t size );
    34 forall( otype T ) T * malloc( T * ptr, size_t size, unsigned char fill );
     31forall( dtype T | sized(T) ) T * malloc( void );
     32forall( dtype T | sized(T) ) T * malloc( char fill );
     33forall( dtype T | sized(T) ) T * malloc( T * ptr, size_t size );
     34forall( dtype T | sized(T) ) T * malloc( T * ptr, size_t size, unsigned char fill );
    3535extern "C" { void * calloc( size_t nmemb, size_t size ); } // use default C routine for void *
    36 forall( otype T ) T * calloc( size_t nmemb );
     36forall( dtype T | sized(T) ) T * calloc( size_t nmemb );
    3737extern "C" { void * realloc( void * ptr, size_t size ); } // use default C routine for void *
    38 forall( otype T ) T * realloc( T * ptr, size_t size );
    39 forall( otype T ) T * realloc( T * ptr, size_t size, unsigned char fill );
     38forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size );
     39forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size, unsigned char fill );
    4040
    41 forall( otype T ) T * aligned_alloc( size_t alignment );
    42 forall( otype T ) T * memalign( size_t alignment );             // deprecated
    43 forall( otype T ) int posix_memalign( T ** ptr, size_t alignment );
     41forall( dtype T | sized(T) ) T * aligned_alloc( size_t alignment );
     42forall( dtype T | sized(T) ) T * memalign( size_t alignment );          // deprecated
     43forall( dtype T | sized(T) ) int posix_memalign( T ** ptr, size_t alignment );
    4444
    4545extern "C" {
     
    4848} // extern "C"
    4949
    50 forall( otype T, ttype Params | { void ?{}(T *, Params); } ) T * new( Params p );
     50forall( dtype T, ttype Params | sized(T) | { void ?{}(T *, Params); } ) T * new( Params p );
    5151forall( dtype T | { void ^?{}(T *); } ) void delete( T * ptr );
    5252
  • src/libcfa/stdlib.c

    rc0aa336 rb4d65c7  
    2727} // extern "C"
    2828
    29 forall( otype T ) T * malloc( void ) {
     29forall( dtype T | sized(T) ) T * malloc( void ) {
    3030        //printf( "malloc1\n" );
    31     return (T *)malloc( sizeof(T) );
    32 } // malloc
    33 forall( otype T ) T * malloc( char fill ) {
     31    return (T *)(void*)malloc( (size_t)sizeof(T) );
     32} // malloc
     33forall( dtype T | sized(T) ) T * malloc( char fill ) {
    3434        //printf( "malloc3\n" );
    35         T * ptr = (T *)malloc( sizeof(T) );
     35        T * ptr = (T *)(void*)malloc( (size_t)sizeof(T) );
    3636    return memset( ptr, (int)fill, sizeof(T) );
    3737} // malloc
    3838
    39 forall( otype T ) T * calloc( size_t nmemb ) {
     39forall( dtype T | sized(T) ) T * calloc( size_t nmemb ) {
    4040        //printf( "calloc\n" );
    4141    return (T *)calloc( nmemb, sizeof(T) );
    4242} // calloc
    4343
    44 forall( otype T ) T * realloc( T * ptr, size_t size ) {
     44forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size ) {
    4545        //printf( "realloc1\n" );
    4646    return (T *)(void *)realloc( (void *)ptr, size );
    4747} // realloc
    48 forall( otype T ) T * realloc( T * ptr, size_t size, unsigned char fill ) {
     48forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size, unsigned char fill ) {
    4949        //printf( "realloc2\n" );
    5050    char * nptr = (T *)(void *)realloc( (void *)ptr, size );
     
    5454} // realloc
    5555
    56 forall( otype T ) T * malloc( T * ptr, size_t size ) {
     56forall( dtype T | sized(T) ) T * malloc( T * ptr, size_t size ) {
    5757        //printf( "malloc4\n" );
    5858    return (T *)realloc( ptr, size );
    5959} // malloc
    60 forall( otype T ) T * malloc( T * ptr, size_t size, unsigned char fill ) {
     60forall( dtype T | sized(T) ) T * malloc( T * ptr, size_t size, unsigned char fill ) {
    6161        //printf( "malloc5\n" );
    6262    return (T *)realloc( ptr, size, fill );
    6363} // malloc
    6464
    65 forall( otype T ) T * aligned_alloc( size_t alignment ) {
     65forall( dtype T | sized(T) ) T * aligned_alloc( size_t alignment ) {
    6666        //printf( "aligned_alloc\n" );
    6767    return (T *)memalign( alignment, sizeof(T) );
    6868} // aligned_alloc
    6969
    70 forall( otype T ) T * memalign( size_t alignment ) {
     70forall( dtype T | sized(T) ) T * memalign( size_t alignment ) {
    7171        //printf( "memalign\n" );
    7272    return (T *)memalign( alignment, sizeof(T) );
    7373} // memalign
    7474
    75 forall( otype T ) int posix_memalign( T ** ptr, size_t alignment ) {
     75forall( dtype T | sized(T) ) int posix_memalign( T ** ptr, size_t alignment ) {
    7676        //printf( "posix_memalign\n" );
    7777    return posix_memalign( (void **)ptr, alignment, sizeof(T) );
    7878} // posix_memalign
    7979
    80 forall( otype T, ttype Params | { void ?{}(T *, Params); } )
     80forall( dtype T, ttype Params | sized(T) | { void ?{}(T *, Params); } )
    8181T * new( Params p ) {
    8282        return ((T*)malloc()){ p };
Note: See TracChangeset for help on using the changeset viewer.