Ignore:
Timestamp:
Oct 29, 2019, 4:01:24 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
773db65, 9421f3d8
Parents:
7951100 (diff), 8364209 (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 plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
libcfa/src/concurrency
Files:
3 added
20 moved

Legend:

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

    r7951100 rb067d9b  
    4141#define PC_OFFSET       ( 2 * PTR_BYTE )
    4242
    43 .text
     43        .text
    4444        .align 2
    45 .globl  CtxSwitch
     45        .globl CtxSwitch
     46        .type  CtxSwitch, @function
    4647CtxSwitch:
    4748
     
    5051
    5152        movl 4(%esp),%eax
    52 
    53         // Save floating & SSE control words on the stack.
    54 
    55         sub    $8,%esp
    56         stmxcsr 0(%esp)         // 4 bytes
    57         fnstcw  4(%esp)         // 2 bytes
    5853
    5954        // Save volatile registers on the stack.
     
    6762        movl %esp,SP_OFFSET(%eax)
    6863        movl %ebp,FP_OFFSET(%eax)
    69 //      movl 4(%ebp),%ebx       // save previous eip for debugger
    70 //      movl %ebx,PC_OFFSET(%eax)
    7164
    7265        // Copy the "to" context argument from the stack to register eax
     
    7467        // argument is now at 8 + 12 = 20(%esp)
    7568
    76         movl 28(%esp),%eax
     69        movl 20(%esp),%eax
    7770
    7871        // Load new context from the "to" area.
     
    8780        popl %ebx
    8881
    89         // Load floating & SSE control words from the stack.
    90 
    91         fldcw   4(%esp)
    92         ldmxcsr 0(%esp)
    93         add    $8,%esp
    94 
    9582        // Return to thread.
    9683
    9784        ret
     85        .size  CtxSwitch, .-CtxSwitch
    9886
    9987// Local Variables: //
  • libcfa/src/concurrency/CtxSwitch-x86_64.S

    r7951100 rb067d9b  
    3939#define SP_OFFSET       ( 0 * PTR_BYTE )
    4040#define FP_OFFSET       ( 1 * PTR_BYTE )
    41 #define PC_OFFSET       ( 2 * PTR_BYTE )
    4241
    43 .text
     42//-----------------------------------------------------------------------------
     43// Regular context switch routine which enables switching from one context to anouther
     44        .text
    4445        .align 2
    45 .globl  CtxSwitch
     46        .globl CtxSwitch
     47        .type  CtxSwitch, @function
    4648CtxSwitch:
    47 
    48         // Save floating & SSE control words on the stack.
    49 
    50         subq   $8,%rsp
    51         stmxcsr 0(%rsp)         // 4 bytes
    52         fnstcw  4(%rsp)         // 2 bytes
    5349
    5450        // Save volatile registers on the stack.
     
    7874        popq %r15
    7975
    80         // Load floating & SSE control words from the stack.
    81 
    82         fldcw   4(%rsp)
    83         ldmxcsr 0(%rsp)
    84         addq   $8,%rsp
    85 
    8676        // Return to thread.
    8777
    8878        ret
     79        .size  CtxSwitch, .-CtxSwitch
    8980
    90 .text
     81//-----------------------------------------------------------------------------
     82// Stub used to create new stacks which are ready to be context switched to
     83        .text
    9184        .align 2
    92 .globl  CtxInvokeStub
     85        .globl CtxInvokeStub
     86        .type    CtxInvokeStub, @function
    9387CtxInvokeStub:
    9488        movq %rbx, %rdi
    9589        jmp *%r12
     90        .size  CtxInvokeStub, .-CtxInvokeStub
    9691
    9792// Local Variables: //
  • libcfa/src/concurrency/alarm.cfa

    r7951100 rb067d9b  
    1414//
    1515
     16#define __cforall_thread__
     17
    1618extern "C" {
    1719#include <errno.h>
     
    2224}
    2325
    24 #include "alarm.h"
    25 #include "kernel_private.h"
    26 #include "preemption.h"
     26#include "alarm.hfa"
     27#include "kernel_private.hfa"
     28#include "preemption.hfa"
    2729
    2830//=============================================================================================
  • libcfa/src/concurrency/alarm.hfa

    r7951100 rb067d9b  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // alarm.h --
     7// alarm.hfa --
    88//
    99// Author           : Thierry Delisle
     
    2121#include <assert.h>
    2222
    23 #include "time"
     23#include "time.hfa"
    2424
    2525struct thread_desc;
  • libcfa/src/concurrency/coroutine.hfa

    r7951100 rb067d9b  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 18:23:45 2018
    13 // Update Count     : 8
     12// Last Modified On : Fri Jun 21 17:49:39 2019
     13// Update Count     : 9
    1414//
    1515
     
    4646//-----------------------------------------------------------------------------
    4747// Public coroutine API
    48 static inline void suspend();
     48static inline void suspend(void);
    4949
    5050forall(dtype T | is_coroutine(T))
    51 static inline void resume(T & cor);
     51static inline T & resume(T & cor);
    5252
    5353forall(dtype T | is_coroutine(T))
    5454void prime(T & cor);
     55
     56static inline struct coroutine_desc * active_coroutine() { return TL_GET( this_thread )->curr_cor; }
    5557
    5658//-----------------------------------------------------------------------------
     
    6466      forall(dtype T | is_coroutine(T))
    6567      void CtxStart(T * this, void ( *invoke)(T *));
     68
     69        extern void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
     70
     71        extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");
    6672}
    6773
    6874// Private wrappers for context switch and stack creation
    69 extern void CoroutineCtxSwitch(coroutine_desc * src, coroutine_desc * dst);
    70 extern void create_stack( coStack_t * this, unsigned int storageSize );
     75// Wrapper for co
     76static inline void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
     77        // set state of current coroutine to inactive
     78        src->state = src->state == Halted ? Halted : Inactive;
     79
     80        // set new coroutine that task is executing
     81        TL_GET( this_thread )->curr_cor = dst;
     82
     83        // context switch to specified coroutine
     84        verify( dst->context.SP );
     85        CtxSwitch( &src->context, &dst->context );
     86        // when CtxSwitch returns we are back in the src coroutine
     87
     88        // set state of new coroutine to active
     89        src->state = Active;
     90
     91        if( unlikely(src->cancellation != NULL) ) {
     92                _CtxCoroutine_Unwind(src->cancellation, src);
     93        }
     94}
     95
     96extern void __stack_prepare   ( __stack_info_t * this, size_t size /* ignored if storage already allocated */);
    7197
    7298// Suspend implementation inlined for performance
    73 static inline void suspend() {
     99static inline void suspend(void) {
    74100        // optimization : read TLS once and reuse it
    75101        // Safety note: this is preemption safe since if
     
    77103        // will also migrate which means this value will
    78104        // stay in syn with the TLS
    79         coroutine_desc * src = TL_GET( this_coroutine );
     105        coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    80106
    81107        assertf( src->last != 0,
     
    93119// Resume implementation inlined for performance
    94120forall(dtype T | is_coroutine(T))
    95 static inline void resume(T & cor) {
     121static inline T & resume(T & cor) {
    96122        // optimization : read TLS once and reuse it
    97123        // Safety note: this is preemption safe since if
     
    99125        // will also migrate which means this value will
    100126        // stay in syn with the TLS
    101         coroutine_desc * src = TL_GET( this_coroutine );
     127        coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    102128        coroutine_desc * dst = get_coroutine(cor);
    103129
    104         if( unlikely(!dst->stack.base) ) {
    105                 create_stack(&dst->stack, dst->stack.size);
     130        if( unlikely(dst->context.SP == NULL) ) {
     131                __stack_prepare(&dst->stack, 65000);
    106132                CtxStart(&cor, CtxInvokeCoroutine);
    107133        }
     
    121147        // always done for performance testing
    122148        CoroutineCtxSwitch( src, dst );
     149
     150        return cor;
    123151}
    124152
     
    129157        // will also migrate which means this value will
    130158        // stay in syn with the TLS
    131         coroutine_desc * src = TL_GET( this_coroutine );
     159        coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    132160
    133161        // not resuming self ?
  • libcfa/src/concurrency/invoke.c

    r7951100 rb067d9b  
    1414//
    1515
     16#define __cforall_thread__
     17
    1618#include <stdbool.h>
    1719#include <stdlib.h>
    1820#include <stdio.h>
     21#include <unwind.h>
    1922
    2023#include "invoke.h"
     
    2730
    2831extern void __suspend_internal(void);
    29 extern void __leave_coroutine(void);
    30 extern void __finish_creation(void);
     32extern void __leave_coroutine( struct coroutine_desc * );
     33extern void __finish_creation( struct thread_desc * );
    3134extern void __leave_thread_monitor( struct thread_desc * this );
    32 extern void disable_interrupts();
     35extern void disable_interrupts() OPTIONAL_THREAD;
    3336extern void enable_interrupts( __cfaabi_dbg_ctx_param );
    3437
     
    4649        cor->state = Active;
    4750
    48         enable_interrupts( __cfaabi_dbg_ctx );
    49 
    5051        main( this );
    5152
    52         cor->state = Halted;
     53        //Final suspend, should never return
     54        __leave_coroutine( cor );
     55        __cabi_abort( "Resumed dead coroutine" );
     56}
    5357
    54         //Final suspend, should never return
    55         __leave_coroutine();
    56         __cabi_abort( "Resumed dead coroutine" );
     58static _Unwind_Reason_Code _CtxCoroutine_UnwindStop(
     59        __attribute((__unused__)) int version,
     60        _Unwind_Action actions,
     61        __attribute((__unused__)) _Unwind_Exception_Class exceptionClass,
     62        __attribute((__unused__)) struct _Unwind_Exception * unwind_exception,
     63        __attribute((__unused__)) struct _Unwind_Context * context,
     64        void * param
     65) {
     66        if( actions & _UA_END_OF_STACK  ) {
     67                // We finished unwinding the coroutine,
     68                // leave it
     69                __leave_coroutine( param );
     70                __cabi_abort( "Resumed dead coroutine" );
     71        }
     72        if( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON;
     73
     74        return _URC_FATAL_PHASE2_ERROR;
     75}
     76
     77void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) __attribute__ ((__noreturn__));
     78void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) {
     79        _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _CtxCoroutine_UnwindStop, cor );
     80        printf("UNWIND ERROR %d after force unwind\n", ret);
     81        abort();
    5782}
    5883
     
    6388        void *this
    6489) {
     90        // Fetch the thread handle from the user defined thread structure
     91        struct thread_desc* thrd = get_thread( this );
     92
    6593        // First suspend, once the thread arrives here,
    6694        // the function pointer to main can be invalidated without risk
    67         __finish_creation();
    68 
    69         // Fetch the thread handle from the user defined thread structure
    70         struct thread_desc* thrd = get_thread( this );
    71         thrd->self_cor.last = NULL;
     95        __finish_creation( thrd );
    7296
    7397        // Officially start the thread by enabling preemption
     
    95119        void (*invoke)(void *)
    96120) {
    97         struct coStack_t* stack = &get_coroutine( this )->stack;
     121        struct coroutine_desc * cor = get_coroutine( this );
     122        struct __stack_t * stack = cor->stack.storage;
    98123
    99124#if defined( __i386 )
    100125
    101126        struct FakeStack {
    102             void *fixedRegisters[3];                    // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant)
    103             uint32_t mxcr;                        // SSE Status and Control bits (control bits are preserved across function calls)
    104             uint16_t fcw;                         // X97 FPU control word (preserved across function calls)
     127            void *fixedRegisters[3];              // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant)
    105128            void *rturn;                          // where to go on return from uSwitch
    106             void *dummyReturn;                          // fake return compiler would have pushed on call to uInvoke
    107             void *argument[3];                          // for 16-byte ABI, 16-byte alignment starts here
    108             void *padding;                              // padding to force 16-byte alignment, as "base" is 16-byte aligned
     129            void *dummyReturn;                    // fake return compiler would have pushed on call to uInvoke
     130            void *argument[3];                    // for 16-byte ABI, 16-byte alignment starts here
     131            void *padding;                        // padding to force 16-byte alignment, as "base" is 16-byte aligned
    109132        };
    110133
    111         ((struct machine_context_t *)stack->context)->SP = (char *)stack->base - sizeof( struct FakeStack );
    112         ((struct machine_context_t *)stack->context)->FP = NULL;                // terminate stack with NULL fp
     134        cor->context.SP = (char *)stack->base - sizeof( struct FakeStack );
     135        cor->context.FP = NULL;         // terminate stack with NULL fp
    113136
    114         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
    115         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument[0] = this;     // argument to invoke
    116         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke;
    117         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520
    118         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F;  //Vol. 1 8-7
     137        struct FakeStack *fs = (struct FakeStack *)cor->context.SP;
     138
     139        fs->dummyReturn = NULL;
     140        fs->argument[0] = this;     // argument to invoke
     141        fs->rturn = invoke;
    119142
    120143#elif defined( __x86_64 )
     
    122145        struct FakeStack {
    123146                void *fixedRegisters[5];            // fixed registers rbx, r12, r13, r14, r15
    124                 uint32_t mxcr;                      // SSE Status and Control bits (control bits are preserved across function calls)
    125                 uint16_t fcw;                       // X97 FPU control word (preserved across function calls)
    126147                void *rturn;                        // where to go on return from uSwitch
    127148                void *dummyReturn;                  // NULL return address to provide proper alignment
    128149        };
    129150
    130         ((struct machine_context_t *)stack->context)->SP = (char *)stack->base - sizeof( struct FakeStack );
    131         ((struct machine_context_t *)stack->context)->FP = NULL;                // terminate stack with NULL fp
     151        cor->context.SP = (char *)stack->base - sizeof( struct FakeStack );
     152        cor->context.FP = NULL;         // terminate stack with NULL fp
    132153
    133         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->dummyReturn = NULL;
    134         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = CtxInvokeStub;
    135         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[0] = this;
    136         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = invoke;
    137         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520
    138         ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F;  //Vol. 1 8-7
     154        struct FakeStack *fs = (struct FakeStack *)cor->context.SP;
     155
     156        fs->dummyReturn = NULL;
     157        fs->rturn = CtxInvokeStub;
     158        fs->fixedRegisters[0] = this;
     159        fs->fixedRegisters[1] = invoke;
    139160
    140161#elif defined( __ARM_ARCH )
     
    146167        };
    147168
    148         ((struct machine_context_t *)stack->context)->SP = (char *)stack->base - sizeof( struct FakeStack );
    149         ((struct machine_context_t *)stack->context)->FP = NULL;
     169        cor->context.SP = (char *)stack->base - sizeof( struct FakeStack );
     170        cor->context.FP = NULL;
    150171
    151         struct FakeStack *fs = (struct FakeStack *)((struct machine_context_t *)stack->context)->SP;
     172        struct FakeStack *fs = (struct FakeStack *)cor->context.SP;
    152173
    153174        fs->intRegs[8] = CtxInvokeStub;
  • libcfa/src/concurrency/invoke.h

    r7951100 rb067d9b  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 19 08:23:21 2018
    13 // Update Count     : 31
    14 //
    15 
    16 #include "bits/containers.h"
    17 #include "bits/defs.h"
    18 #include "bits/locks.h"
     12// Last Modified On : Sat Jun 22 18:19:13 2019
     13// Update Count     : 40
     14//
     15
     16#include "bits/containers.hfa"
     17#include "bits/defs.hfa"
     18#include "bits/locks.hfa"
    1919
    2020#ifdef __cforall
     
    4646        #ifdef __cforall
    4747        extern "Cforall" {
    48                 static inline struct thread_desc             * & get_next( struct thread_desc             & this );
    49                 static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this );
    50 
    5148                extern thread_local struct KernelThreadData {
    52                         struct coroutine_desc * volatile this_coroutine;
    5349                        struct thread_desc    * volatile this_thread;
    5450                        struct processor      * volatile this_processor;
     
    5955                                volatile bool in_progress;
    6056                        } preemption_state;
    61                 } kernelTLS;
     57                } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
    6258        }
    63 
    64         static inline struct coroutine_desc * volatile active_coroutine() { return TL_GET( this_coroutine ); }
    65         static inline struct thread_desc    * volatile active_thread   () { return TL_GET( this_thread    ); }
    66         static inline struct processor      * volatile active_processor() { return TL_GET( this_processor ); } // UNSAFE
    6759        #endif
    6860
    69         struct coStack_t {
    70                 size_t size;                                                                    // size of stack
    71                 void * storage;                                                                 // pointer to stack
    72                 void * limit;                                                                   // stack grows towards stack limit
    73                 void * base;                                                                    // base of stack
    74                 void * context;                                                                 // address of cfa_context_t
    75                 void * top;                                                                             // address of top of storage
    76                 bool userStack;                                                                 // whether or not the user allocated the stack
     61        struct __stack_context_t {
     62                void * SP;
     63                void * FP;
     64        };
     65
     66        // low adresses  :           +----------------------+ <- start of allocation
     67        //                           |  optional guard page |
     68        //                           +----------------------+ <- __stack_t.limit
     69        //                           |                      |
     70        //                           |       /\ /\ /\       |
     71        //                           |       || || ||       |
     72        //                           |                      |
     73        //                           |    program  stack    |
     74        //                           |                      |
     75        // __stack_info_t.storage -> +----------------------+ <- __stack_t.base
     76        //                           |      __stack_t       |
     77        // high adresses :           +----------------------+ <- end of allocation
     78
     79        struct __stack_t {
     80                // stack grows towards stack limit
     81                void * limit;
     82
     83                // base of stack
     84                void * base;
     85        };
     86
     87        struct __stack_info_t {
     88                // pointer to stack
     89                struct __stack_t * storage;
    7790        };
    7891
     
    8093
    8194        struct coroutine_desc {
    82                 struct coStack_t stack;                                                 // stack information of the coroutine
    83                 const char * name;                                                              // textual name for coroutine/task, initialized by uC++ generated code
    84                 int errno_;                                                                             // copy of global UNIX variable errno
    85                 enum coroutine_state state;                                             // current execution status for coroutine
    86                 struct coroutine_desc * starter;                                // first coroutine to resume this one
    87                 struct coroutine_desc * last;                                   // last coroutine to resume this one
    88         };
    89 
     95                // context that is switch during a CtxSwitch
     96                struct __stack_context_t context;
     97
     98                // stack information of the coroutine
     99                struct __stack_info_t stack;
     100
     101                // textual name for coroutine/task
     102                const char * name;
     103
     104                // current execution status for coroutine
     105                enum coroutine_state state;
     106
     107                // first coroutine to resume this one
     108                struct coroutine_desc * starter;
     109
     110                // last coroutine to resume this one
     111                struct coroutine_desc * last;
     112
     113                // If non-null stack must be unwound with this exception
     114                struct _Unwind_Exception * cancellation;
     115
     116        };
     117
     118        // struct which calls the monitor is accepting
    90119        struct __waitfor_mask_t {
    91120                // the index of the accepted function, -1 if none
     
    93122
    94123                // list of acceptable functions, null if any
    95                 __small_array_t(struct __acceptable_t) __cfa_anonymous_object;
     124                __cfa_anonymous_object( __small_array_t(struct __acceptable_t) );
    96125        };
    97126
     
    121150        struct __monitor_group_t {
    122151                // currently held monitors
    123                 __small_array_t(monitor_desc*) __cfa_anonymous_object;
     152                __cfa_anonymous_object( __small_array_t(monitor_desc*) );
    124153
    125154                // last function that acquired monitors
     
    129158        struct thread_desc {
    130159                // Core threading fields
     160                // context that is switch during a CtxSwitch
     161                struct __stack_context_t context;
     162
     163                // current execution status for coroutine
     164                enum coroutine_state state;
     165
     166                //SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it
     167
    131168                // coroutine body used to store context
    132169                struct coroutine_desc  self_cor;
     
    155192                        struct thread_desc * prev;
    156193                } node;
    157      };
    158 
    159      #ifdef __cforall
    160      extern "Cforall" {
    161                 static inline thread_desc * & get_next( thread_desc & this ) {
     194        };
     195
     196        #ifdef __cforall
     197        extern "Cforall" {
     198                static inline thread_desc *& get_next( thread_desc & this ) {
    162199                        return this.next;
    163200                }
     
    166203                        return this.node.[next, prev];
    167204                }
    168 
    169                 static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this );
    170205
    171206                static inline void ?{}(__monitor_group_t & this) {
     
    216251        // assembler routines that performs the context switch
    217252        extern void CtxInvokeStub( void );
    218         void CtxSwitch( void * from, void * to ) asm ("CtxSwitch");
    219 
    220         #if   defined( __i386 )
    221         #define CtxGet( ctx ) __asm__ ( \
    222                         "movl %%esp,%0\n"   \
    223                         "movl %%ebp,%1\n"   \
    224                 : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    225         #elif defined( __x86_64 )
    226         #define CtxGet( ctx ) __asm__ ( \
    227                         "movq %%rsp,%0\n"   \
    228                         "movq %%rbp,%1\n"   \
    229                 : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    230         #elif defined( __ARM_ARCH )
    231         #define CtxGet( ctx ) __asm__ ( \
    232                         "mov %0,%%sp\n"   \
    233                         "mov %1,%%r11\n"   \
    234                 : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    235         #else
    236                 #error unknown hardware architecture
    237         #endif
     253        extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");
     254        // void CtxStore ( void * this ) asm ("CtxStore");
     255        // void CtxRet   ( void * dst  ) asm ("CtxRet");
    238256
    239257#endif //_INVOKE_PRIVATE_H_
  • libcfa/src/concurrency/kernel.cfa

    r7951100 rb067d9b  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr  9 16:11:46 2018
    13 // Update Count     : 24
     12// Last Modified On : Thu Jun 20 17:21:23 2019
     13// Update Count     : 25
    1414//
     15
     16#define __cforall_thread__
    1517
    1618//C Includes
     
    2729
    2830//CFA Includes
    29 #include "time"
    30 #include "kernel_private.h"
    31 #include "preemption.h"
    32 #include "startup.h"
     31#include "time.hfa"
     32#include "kernel_private.hfa"
     33#include "preemption.hfa"
     34#include "startup.hfa"
    3335
    3436//Private includes
     
    3638#include "invoke.h"
    3739
     40//-----------------------------------------------------------------------------
     41// Some assembly required
     42#if   defined( __i386 )
     43        #define CtxGet( ctx )        \
     44                __asm__ volatile (     \
     45                        "movl %%esp,%0\n"\
     46                        "movl %%ebp,%1\n"\
     47                        : "=rm" (ctx.SP),\
     48                                "=rm" (ctx.FP) \
     49                )
     50
     51        // mxcr : SSE Status and Control bits (control bits are preserved across function calls)
     52        // fcw  : X87 FPU control word (preserved across function calls)
     53        #define __x87_store         \
     54                uint32_t __mxcr;      \
     55                uint16_t __fcw;       \
     56                __asm__ volatile (    \
     57                        "stmxcsr %0\n"  \
     58                        "fnstcw  %1\n"  \
     59                        : "=m" (__mxcr),\
     60                                "=m" (__fcw)  \
     61                )
     62
     63        #define __x87_load         \
     64                __asm__ volatile (   \
     65                        "fldcw  %1\n"  \
     66                        "ldmxcsr %0\n" \
     67                        ::"m" (__mxcr),\
     68                                "m" (__fcw)  \
     69                )
     70
     71#elif defined( __x86_64 )
     72        #define CtxGet( ctx )        \
     73                __asm__ volatile (     \
     74                        "movq %%rsp,%0\n"\
     75                        "movq %%rbp,%1\n"\
     76                        : "=rm" (ctx.SP),\
     77                                "=rm" (ctx.FP) \
     78                )
     79
     80        #define __x87_store         \
     81                uint32_t __mxcr;      \
     82                uint16_t __fcw;       \
     83                __asm__ volatile (    \
     84                        "stmxcsr %0\n"  \
     85                        "fnstcw  %1\n"  \
     86                        : "=m" (__mxcr),\
     87                                "=m" (__fcw)  \
     88                )
     89
     90        #define __x87_load          \
     91                __asm__ volatile (    \
     92                        "fldcw  %1\n"   \
     93                        "ldmxcsr %0\n"  \
     94                        :: "m" (__mxcr),\
     95                                "m" (__fcw)  \
     96                )
     97
     98
     99#elif defined( __ARM_ARCH )
     100#define CtxGet( ctx ) __asm__ ( \
     101                "mov %0,%%sp\n"   \
     102                "mov %1,%%r11\n"   \
     103        : "=rm" (ctx.SP), "=rm" (ctx.FP) )
     104#else
     105        #error unknown hardware architecture
     106#endif
     107
     108//-----------------------------------------------------------------------------
    38109//Start and stop routine for the kernel, declared first to make sure they run first
    39 void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
    40 void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
     110static void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     111static void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
    41112
    42113//-----------------------------------------------------------------------------
    43114// 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);
     115KERNEL_STORAGE(cluster,         mainCluster);
     116KERNEL_STORAGE(processor,       mainProcessor);
     117KERNEL_STORAGE(thread_desc,     mainThread);
     118KERNEL_STORAGE(__stack_t,       mainThreadCtx);
    48119
    49120cluster     * mainCluster;
     
    55126}
    56127
     128size_t __page_size = 0;
     129
    57130//-----------------------------------------------------------------------------
    58131// Global state
    59 thread_local struct KernelThreadData kernelTLS = {
    60         NULL,
     132thread_local struct KernelThreadData kernelTLS __attribute__ ((tls_model ( "initial-exec" ))) = {
    61133        NULL,
    62134        NULL,
     
    67139// Struct to steal stack
    68140struct current_stack_info_t {
    69         machine_context_t ctx;
    70         unsigned int size;              // size of stack
     141        __stack_t * storage;            // pointer to stack object
    71142        void *base;                             // base of stack
    72         void *storage;                  // pointer to stack
    73143        void *limit;                    // stack grows towards stack limit
    74144        void *context;                  // address of cfa_context_t
    75         void *top;                              // address of top of storage
    76145};
    77146
    78147void ?{}( current_stack_info_t & this ) {
    79         CtxGet( this.ctx );
    80         this.base = this.ctx.FP;
    81         this.storage = this.ctx.SP;
     148        __stack_context_t ctx;
     149        CtxGet( ctx );
     150        this.base = ctx.FP;
    82151
    83152        rlimit r;
    84153        getrlimit( RLIMIT_STACK, &r);
    85         this.size = r.rlim_cur;
    86 
    87         this.limit = (void *)(((intptr_t)this.base) - this.size);
     154        size_t size = r.rlim_cur;
     155
     156        this.limit = (void *)(((intptr_t)this.base) - size);
    88157        this.context = &storage_mainThreadCtx;
    89         this.top = this.base;
    90158}
    91159
    92160//-----------------------------------------------------------------------------
    93161// Main thread construction
    94 void ?{}( coStack_t & this, current_stack_info_t * info) with( this ) {
    95         size      = info->size;
    96         storage   = info->storage;
    97         limit     = info->limit;
    98         base      = info->base;
    99         context   = info->context;
    100         top       = info->top;
    101         userStack = true;
    102 }
    103162
    104163void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) {
    105         stack{ info };
     164        stack.storage = info->storage;
     165        with(*stack.storage) {
     166                limit     = info->limit;
     167                base      = info->base;
     168        }
     169        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*) &stack.storage;
     170        *istorage |= 0x1;
    106171        name = "Main Thread";
    107         errno_ = 0;
    108172        state = Start;
    109173        starter = NULL;
     174        last = NULL;
     175        cancellation = NULL;
    110176}
    111177
    112178void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) {
     179        state = Start;
    113180        self_cor{ info };
    114181        curr_cor = &self_cor;
     
    133200
    134201// Construct the processor context of non-main processors
    135 void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) {
     202static void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) {
    136203        (this.__cor){ info };
    137204        this.proc = proc;
    138205}
    139206
     207static void start(processor * this);
    140208void ?{}(processor & this, const char * name, cluster & cltr) with( this ) {
    141209        this.name = name;
     
    147215        runner.proc = &this;
    148216
    149         sem_init(&idleLock, 0, 0);
     217        idleLock{};
    150218
    151219        start( &this );
     
    155223        if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) {
    156224                __cfaabi_dbg_print_safe("Kernel : core %p signaling termination\n", &this);
    157                 terminate(&this);
    158                 verify( __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
    159                 verify( kernelTLS.this_processor != &this);
     225
     226                __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED);
     227                wake( &this );
     228
    160229                P( terminated );
    161230                verify( kernelTLS.this_processor != &this);
    162                 pthread_join( kernel_thread, NULL );
    163         }
    164 
    165         sem_destroy(&idleLock);
     231        }
     232
     233        pthread_join( kernel_thread, NULL );
    166234}
    167235
     
    186254// Kernel Scheduling logic
    187255//=============================================================================================
     256static void runThread(processor * this, thread_desc * dst);
     257static void finishRunning(processor * this);
     258static void halt(processor * this);
     259
    188260//Main of the processor contexts
    189261void main(processorCtx_t & runner) {
     
    236308}
    237309
     310static int * __volatile_errno() __attribute__((noinline));
     311static int * __volatile_errno() { asm(""); return &errno; }
     312
    238313// KERNEL ONLY
    239314// runThread runs a thread by context switching
    240315// from the processor coroutine to the target thread
    241 void runThread(processor * this, thread_desc * dst) {
    242         assert(dst->curr_cor);
     316static void runThread(processor * this, thread_desc * thrd_dst) {
    243317        coroutine_desc * proc_cor = get_coroutine(this->runner);
    244         coroutine_desc * thrd_cor = dst->curr_cor;
    245318
    246319        // Reset the terminating actions here
     
    248321
    249322        // Update global state
    250         kernelTLS.this_thread = dst;
    251 
    252         // Context Switch to the thread
    253         ThreadCtxSwitch(proc_cor, thrd_cor);
    254         // when ThreadCtxSwitch returns we are back in the processor coroutine
     323        kernelTLS.this_thread = thrd_dst;
     324
     325        // set state of processor coroutine to inactive and the thread to active
     326        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     327        thrd_dst->state = Active;
     328
     329        // set context switch to the thread that the processor is executing
     330        verify( thrd_dst->context.SP );
     331        CtxSwitch( &proc_cor->context, &thrd_dst->context );
     332        // when CtxSwitch returns we are back in the processor coroutine
     333
     334        // set state of processor coroutine to active and the thread to inactive
     335        thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive;
     336        proc_cor->state = Active;
    255337}
    256338
    257339// KERNEL_ONLY
    258 void returnToKernel() {
     340static void returnToKernel() {
    259341        coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
    260         coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine;
    261         ThreadCtxSwitch(thrd_cor, proc_cor);
     342        thread_desc * thrd_src = kernelTLS.this_thread;
     343
     344        // set state of current coroutine to inactive
     345        thrd_src->state = thrd_src->state == Halted ? Halted : Inactive;
     346        proc_cor->state = Active;
     347        int local_errno = *__volatile_errno();
     348        #if defined( __i386 ) || defined( __x86_64 )
     349                __x87_store;
     350        #endif
     351
     352        // set new coroutine that the processor is executing
     353        // and context switch to it
     354        verify( proc_cor->context.SP );
     355        CtxSwitch( &thrd_src->context, &proc_cor->context );
     356
     357        // set state of new coroutine to active
     358        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     359        thrd_src->state = Active;
     360
     361        #if defined( __i386 ) || defined( __x86_64 )
     362                __x87_load;
     363        #endif
     364        *__volatile_errno() = local_errno;
    262365}
    263366
     
    265368// Once a thread has finished running, some of
    266369// its final actions must be executed from the kernel
    267 void finishRunning(processor * this) with( this->finish ) {
     370static void finishRunning(processor * this) with( this->finish ) {
    268371        verify( ! kernelTLS.preemption_state.enabled );
    269372        choose( action_code ) {
     
    295398}
    296399
    297 // Handles spinning logic
    298 // TODO : find some strategy to put cores to sleep after some time
    299 void spin(processor * this, unsigned int * spin_count) {
    300         // (*spin_count)++;
    301         halt(this);
    302 }
    303 
    304400// KERNEL_ONLY
    305401// Context invoker for processors
    306402// This is the entry point for processors (kernel threads)
    307403// It effectively constructs a coroutine by stealing the pthread stack
    308 void * CtxInvokeProcessor(void * arg) {
     404static void * CtxInvokeProcessor(void * arg) {
    309405        processor * proc = (processor *) arg;
    310406        kernelTLS.this_processor = proc;
    311         kernelTLS.this_coroutine = NULL;
    312407        kernelTLS.this_thread    = NULL;
    313408        kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
     
    316411        // to waste the perfectly valid stack create by pthread.
    317412        current_stack_info_t info;
    318         machine_context_t ctx;
    319         info.context = &ctx;
     413        __stack_t ctx;
     414        info.storage = &ctx;
    320415        (proc->runner){ proc, &info };
    321416
    322         __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.base);
     417        __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
    323418
    324419        //Set global state
    325         kernelTLS.this_coroutine = get_coroutine(proc->runner);
    326420        kernelTLS.this_thread    = NULL;
    327421
     
    343437}
    344438
    345 void start(processor * this) {
     439static void start(processor * this) {
    346440        __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", this);
    347441
     
    352446
    353447// KERNEL_ONLY
    354 void kernel_first_resume(processor * this) {
    355         coroutine_desc * src = kernelTLS.this_coroutine;
     448void kernel_first_resume( processor * this ) {
     449        thread_desc * src = mainThread;
    356450        coroutine_desc * dst = get_coroutine(this->runner);
    357451
    358452        verify( ! kernelTLS.preemption_state.enabled );
    359453
    360         create_stack(&dst->stack, dst->stack.size);
     454        __stack_prepare( &dst->stack, 65000 );
    361455        CtxStart(&this->runner, CtxInvokeCoroutine);
    362456
    363457        verify( ! kernelTLS.preemption_state.enabled );
    364458
    365         dst->last = src;
    366         dst->starter = dst->starter ? dst->starter : src;
     459        dst->last = &src->self_cor;
     460        dst->starter = dst->starter ? dst->starter : &src->self_cor;
    367461
    368462        // set state of current coroutine to inactive
    369463        src->state = src->state == Halted ? Halted : Inactive;
    370464
    371         // set new coroutine that task is executing
    372         kernelTLS.this_coroutine = dst;
    373 
    374         // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch.
    375         // Therefore, when first creating a coroutine, interrupts are enable before calling the main.
    376         // This is consistent with thread creation. However, when creating the main processor coroutine,
    377         // we wan't interrupts to be disabled. Therefore, we double-disable interrupts here so they will
    378         // stay disabled.
    379         disable_interrupts();
    380 
    381465        // context switch to specified coroutine
    382         assert( src->stack.context );
    383         CtxSwitch( src->stack.context, dst->stack.context );
     466        verify( dst->context.SP );
     467        CtxSwitch( &src->context, &dst->context );
    384468        // when CtxSwitch returns we are back in the src coroutine
    385469
     
    388472
    389473        verify( ! kernelTLS.preemption_state.enabled );
     474}
     475
     476// KERNEL_ONLY
     477void kernel_last_resume( processor * this ) {
     478        coroutine_desc * src = &mainThread->self_cor;
     479        coroutine_desc * dst = get_coroutine(this->runner);
     480
     481        verify( ! kernelTLS.preemption_state.enabled );
     482        verify( dst->starter == src );
     483        verify( dst->context.SP );
     484
     485        // context switch to the processor
     486        CtxSwitch( &src->context, &dst->context );
    390487}
    391488
     
    396493void ScheduleThread( thread_desc * thrd ) {
    397494        verify( thrd );
    398         verify( thrd->self_cor.state != Halted );
     495        verify( thrd->state != Halted );
    399496
    400497        verify( ! kernelTLS.preemption_state.enabled );
     
    408505                unlock( ready_queue_lock );
    409506
    410                 if( was_empty ) {
     507                if(was_empty) {
    411508                        lock      (proc_list_lock __cfaabi_dbg_ctx2);
    412509                        if(idles) {
    413                                 wake(idles.head);
     510                                wake_fast(idles.head);
    414511                        }
    415512                        unlock    (proc_list_lock);
    416513                }
     514                else if( struct processor * idle = idles.head ) {
     515                        wake_fast(idle);
     516                }
     517
    417518        }
    418519
     
    545646//-----------------------------------------------------------------------------
    546647// Kernel boot procedures
    547 void kernel_startup(void) {
     648static void kernel_startup(void) {
    548649        verify( ! kernelTLS.preemption_state.enabled );
    549650        __cfaabi_dbg_print_safe("Kernel : Starting\n");
     651
     652        __page_size = sysconf( _SC_PAGESIZE );
    550653
    551654        __cfa_dbg_global_clusters.list{ __get };
     
    563666        mainThread = (thread_desc *)&storage_mainThread;
    564667        current_stack_info_t info;
     668        info.storage = (__stack_t*)&storage_mainThreadCtx;
    565669        (*mainThread){ &info };
    566670
     
    597701        kernelTLS.this_processor = mainProcessor;
    598702        kernelTLS.this_thread    = mainThread;
    599         kernelTLS.this_coroutine = &mainThread->self_cor;
    600703
    601704        // Enable preemption
     
    621724}
    622725
    623 void kernel_shutdown(void) {
     726static void kernel_shutdown(void) {
    624727        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    625728
     
    632735        // which is currently here
    633736        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    634         returnToKernel();
     737        kernel_last_resume( kernelTLS.this_processor );
    635738        mainThread->self_cor.state = Halted;
    636739
     
    658761// Kernel Quiescing
    659762//=============================================================================================
    660 
    661 void halt(processor * this) with( *this ) {
    662         verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
     763static void halt(processor * this) with( *this ) {
     764        // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
    663765
    664766        with( *cltr ) {
     
    671773        __cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this);
    672774
    673         // #ifdef __CFA_WITH_VERIFY__
    674         //      int sval = 0;
    675         //      sem_getvalue(&this->idleLock, &sval);
    676         //      verifyf(sval < 200, "Binary semaphore reached value %d : \n", sval);
    677         // #endif
    678 
    679         verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
    680         int __attribute__((unused)) ret = sem_wait(&idleLock);
    681         // verifyf(ret >= 0 || errno == EINTR, "Sem_wait returned %d (errno %d : %s\n", ret, errno, strerror(errno));
    682 
    683         // wait( idleLock );
     775        wait( idleLock );
    684776
    685777        __cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this);
     
    693785}
    694786
    695 void wake(processor * this) {
    696         __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
    697         int __attribute__((unused)) ret = sem_post(&this->idleLock);
    698         // verifyf(ret >= 0 || errno == EINTR, "Sem_post returned %d (errno %d : %s\n", ret, errno, strerror(errno));
    699 
    700         // #ifdef __CFA_WITH_VERIFY__
    701         //      int sval = 0;
    702         //      sem_getvalue(&this->idleLock, &sval);
    703         //      verifyf(sval < 200, "Binary semaphore reached value %d\n", sval);
    704         // #endif
    705 
    706         // post( this->idleLock );
    707 }
    708 
    709787//=============================================================================================
    710788// Unexpected Terminating logic
    711789//=============================================================================================
    712 
    713 
    714790static __spinlock_t kernel_abort_lock;
    715791static bool kernel_abort_called = false;
     
    745821                __cfaabi_dbg_bits_write( abort_text, len );
    746822
    747                 if ( get_coroutine(thrd) != kernelTLS.this_coroutine ) {
    748                         len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine );
     823                if ( &thrd->self_cor != thrd->curr_cor ) {
     824                        len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", thrd->curr_cor->name, thrd->curr_cor );
    749825                        __cfaabi_dbg_bits_write( abort_text, len );
    750826                }
     
    833909void doregister( cluster * cltr, thread_desc & thrd ) {
    834910        lock      (cltr->thread_list_lock __cfaabi_dbg_ctx2);
     911        cltr->nthreads += 1;
    835912        push_front(cltr->threads, thrd);
    836913        unlock    (cltr->thread_list_lock);
     
    840917        lock  (cltr->thread_list_lock __cfaabi_dbg_ctx2);
    841918        remove(cltr->threads, thrd );
     919        cltr->nthreads -= 1;
    842920        unlock(cltr->thread_list_lock);
    843921}
     
    845923void doregister( cluster * cltr, processor * proc ) {
    846924        lock      (cltr->proc_list_lock __cfaabi_dbg_ctx2);
     925        cltr->nprocessors += 1;
    847926        push_front(cltr->procs, *proc);
    848927        unlock    (cltr->proc_list_lock);
     
    852931        lock  (cltr->proc_list_lock __cfaabi_dbg_ctx2);
    853932        remove(cltr->procs, *proc );
     933        cltr->nprocessors -= 1;
    854934        unlock(cltr->proc_list_lock);
    855935}
     
    858938// Debug
    859939__cfaabi_dbg_debug_do(
    860         void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {
    861                 this.prev_name = prev_name;
    862                 this.prev_thrd = kernelTLS.this_thread;
     940        extern "C" {
     941                void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {
     942                        this.prev_name = prev_name;
     943                        this.prev_thrd = kernelTLS.this_thread;
     944                }
    863945        }
    864946)
     947
     948//-----------------------------------------------------------------------------
     949// Debug
     950bool threading_enabled(void) {
     951        return true;
     952}
    865953// Local Variables: //
    866954// mode: c //
  • libcfa/src/concurrency/kernel.hfa

    r7951100 rb067d9b  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Apr 10 14:46:49 2018
    13 // Update Count     : 10
     12// Last Modified On : Sat Jun 22 11:39:17 2019
     13// Update Count     : 16
    1414//
    1515
     
    1919
    2020#include "invoke.h"
    21 #include "time_t.h"
     21#include "time_t.hfa"
    2222
    2323extern "C" {
     
    9191        this.lock = NULL;
    9292}
    93 static inline void ^?{}(FinishAction & this) {}
     93static inline void ^?{}(FinishAction &) {}
    9494
    9595// Processor
     
    113113        pthread_t kernel_thread;
    114114
     115        // RunThread data
     116        // Action to do after a thread is ran
     117        struct FinishAction finish;
     118
     119        // Preemption data
     120        // Node which is added in the discrete event simulaiton
     121        struct alarm_node_t * preemption_alarm;
     122
     123        // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible
     124        bool pending_preemption;
     125
     126        // Idle lock
     127        __bin_sem_t idleLock;
     128
    115129        // Termination
    116130        // Set to true to notify the processor should terminate
     
    119133        // Termination synchronisation
    120134        semaphore terminated;
    121 
    122         // RunThread data
    123         // Action to do after a thread is ran
    124         struct FinishAction finish;
    125 
    126         // Preemption data
    127         // Node which is added in the discrete event simulaiton
    128         struct alarm_node_t * preemption_alarm;
    129 
    130         // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible
    131         bool pending_preemption;
    132 
    133         // Idle lock
    134         sem_t idleLock;
    135         // __bin_sem_t idleLock;
    136135
    137136        // Link lists fields
     
    177176        __dllist_t(struct processor) procs;
    178177        __dllist_t(struct processor) idles;
    179 
    180         // List of processors
     178        unsigned int nprocessors;
     179
     180        // List of threads
    181181        __spinlock_t thread_list_lock;
    182182        __dllist_t(struct thread_desc) threads;
     183        unsigned int nthreads;
    183184
    184185        // Link lists fields
     
    201202}
    202203
     204static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE
     205static inline struct cluster   * active_cluster  () { return TL_GET( this_processor )->cltr; }
     206
    203207// Local Variables: //
    204208// mode: c //
  • libcfa/src/concurrency/kernel_private.hfa

    r7951100 rb067d9b  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // kernel_private.h --
     7// kernel_private.hfa --
    88//
    99// Author           : Thierry Delisle
     
    1616#pragma once
    1717
    18 #include "kernel"
    19 #include "thread"
     18#include "kernel.hfa"
     19#include "thread.hfa"
    2020
    21 #include "alarm.h"
     21#include "alarm.hfa"
    2222
    2323
     
    2626
    2727extern "C" {
    28         void disable_interrupts();
     28        void disable_interrupts() OPTIONAL_THREAD;
    2929        void enable_interrupts_noPoll();
    3030        void enable_interrupts( __cfaabi_dbg_ctx_param );
     
    3434static inline void WakeThread( thread_desc * thrd ) {
    3535        if( !thrd ) return;
     36
     37        verify(thrd->state == Inactive);
    3638
    3739        disable_interrupts();
     
    5456// Processor
    5557void main(processorCtx_t *);
    56 void start(processor * this);
    57 void runThread(processor * this, thread_desc * dst);
    58 void finishRunning(processor * this);
    59 void halt(processor * this);
    60 void wake(processor * this);
    61 void terminate(processor * this);
    62 void spin(processor * this, unsigned int * spin_count);
     58
     59static inline void wake_fast(processor * this) {
     60        __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
     61        post( this->idleLock );
     62}
     63
     64static inline void wake(processor * this) {
     65        disable_interrupts();
     66        wake_fast(this);
     67        enable_interrupts( __cfaabi_dbg_ctx );
     68}
    6369
    6470struct event_kernel_t {
     
    6975extern event_kernel_t * event_kernel;
    7076
    71 //extern thread_local coroutine_desc * volatile this_coroutine;
    72 //extern thread_local thread_desc *    volatile this_thread;
    73 //extern thread_local processor *      volatile this_processor;
    74 
    75 // extern volatile thread_local bool preemption_in_progress;
    76 // extern volatile thread_local bool preemption_enabled;
    77 // extern volatile thread_local unsigned short disable_preempt_count;
    78 
    7977struct __cfa_kernel_preemption_state_t {
    8078        bool enabled;
     
    8381};
    8482
    85 extern volatile thread_local __cfa_kernel_preemption_state_t preemption_state;
     83extern volatile thread_local __cfa_kernel_preemption_state_t preemption_state __attribute__ ((tls_model ( "initial-exec" )));
    8684
    8785//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/monitor.cfa

    r7951100 rb067d9b  
    1414//
    1515
    16 #include "monitor"
    17 
    18 #include <stdlib>
     16#define __cforall_thread__
     17
     18#include "monitor.hfa"
     19
     20#include <stdlib.hfa>
    1921#include <inttypes.h>
    2022
    21 #include "kernel_private.h"
    22 
    23 #include "bits/algorithms.h"
     23#include "kernel_private.hfa"
     24
     25#include "bits/algorithm.hfa"
    2426
    2527//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/monitor.hfa

    r7951100 rb067d9b  
    2020#include <assert.h>
    2121#include "invoke.h"
    22 #include "stdlib"
     22#include "stdlib.hfa"
    2323
    2424trait is_monitor(dtype T) {
     
    138138
    139139struct __acceptable_t {
    140         __monitor_group_t;
     140        inline struct __monitor_group_t;
    141141        bool is_dtor;
    142142};
  • libcfa/src/concurrency/mutex.cfa

    r7951100 rb067d9b  
    1616//
    1717
    18 #include "mutex"
     18#define __cforall_thread__
    1919
    20 #include "kernel_private.h"
     20#include "mutex.hfa"
     21
     22#include "kernel_private.hfa"
    2123
    2224//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/mutex.hfa

    r7951100 rb067d9b  
    2020#include <stdbool.h>
    2121
    22 #include "bits/algorithms.h"
    23 #include "bits/locks.h"
     22#include "bits/algorithm.hfa"
     23#include "bits/locks.hfa"
    2424
    2525#include "invoke.h"
    26 #include "time_t.h"
     26#include "time_t.hfa"
    2727
    2828//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/preemption.cfa

    r7951100 rb067d9b  
    1414//
    1515
    16 #include "preemption.h"
     16#define __cforall_thread__
     17
     18#include "preemption.hfa"
    1719#include <assert.h>
    1820
     
    2426}
    2527
    26 #include "bits/signal.h"
     28#include "bits/signal.hfa"
    2729
    2830#if !defined(__CFA_DEFAULT_PREEMPTION__)
     
    3941
    4042// FwdDeclarations : Signal handlers
    41 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
    42 void sigHandler_segv     ( __CFA_SIGPARMS__ );
    43 void sigHandler_ill      ( __CFA_SIGPARMS__ );
    44 void sigHandler_fpe      ( __CFA_SIGPARMS__ );
    45 void sigHandler_abort    ( __CFA_SIGPARMS__ );
     43static void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
     44static void sigHandler_segv     ( __CFA_SIGPARMS__ );
     45static void sigHandler_ill      ( __CFA_SIGPARMS__ );
     46static void sigHandler_fpe      ( __CFA_SIGPARMS__ );
     47static void sigHandler_abort    ( __CFA_SIGPARMS__ );
    4648
    4749// FwdDeclarations : alarm thread main
    48 void * alarm_loop( __attribute__((unused)) void * args );
     50static void * alarm_loop( __attribute__((unused)) void * args );
    4951
    5052// Machine specific register name
     
    6365static pthread_t alarm_thread;                        // pthread handle to alarm thread
    6466
    65 void ?{}(event_kernel_t & this) with( this ) {
     67static void ?{}(event_kernel_t & this) with( this ) {
    6668        alarms{};
    6769        lock{};
     
    8587
    8688// Tick one frame of the Discrete Event Simulation for alarms
    87 void tick_preemption() {
     89static void tick_preemption() {
    8890        alarm_node_t * node = NULL;                     // Used in the while loop but cannot be declared in the while condition
    8991        alarm_list_t * alarms = &event_kernel->alarms;  // Local copy for ease of reading
     
    263265}
    264266
    265 // kill wrapper : signal a processor
    266 void terminate(processor * this) {
    267         disable_interrupts();
    268         __atomic_store_n(&this->do_terminate, true, __ATOMIC_SEQ_CST);
    269         wake( this );
    270         sigval_t value = { PREEMPT_TERMINATE };
    271         enable_interrupts( __cfaabi_dbg_ctx );
    272         pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    273 }
    274 
    275267// reserved for future use
    276268static void timeout( thread_desc * this ) {
     
    360352// Context switch signal handler
    361353// Receives SIGUSR1 signal and causes the current thread to yield
    362 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
     354static void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    363355        __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.CFA_REG_IP); )
    364356
     
    403395// Main of the alarm thread
    404396// Waits on SIGALRM and send SIGUSR1 to whom ever needs it
    405 void * alarm_loop( __attribute__((unused)) void * args ) {
     397static void * alarm_loop( __attribute__((unused)) void * args ) {
    406398        // Block sigalrms to control when they arrive
    407399        sigset_t mask;
  • libcfa/src/concurrency/preemption.hfa

    r7951100 rb067d9b  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // preemption.h --
     7// preemption.hfa --
    88//
    99// Author           : Thierry Delisle
     
    1616#pragma once
    1717
    18 #include "alarm.h"
    19 #include "kernel_private.h"
     18#include "alarm.hfa"
     19#include "kernel_private.hfa"
    2020
    2121void kernel_start_preemption();
    2222void kernel_stop_preemption();
    2323void update_preemption( processor * this, Duration duration );
    24 void tick_preemption();
    2524
    2625struct preemption_scope {
  • libcfa/src/concurrency/thread.cfa

    r7951100 rb067d9b  
    1414//
    1515
    16 #include "thread"
     16#define __cforall_thread__
    1717
    18 #include "kernel_private.h"
     18#include "thread.hfa"
     19
     20#include "kernel_private.hfa"
    1921
    2022#define __CFA_INVOKE_PRIVATE__
     
    3133// Thread ctors and dtors
    3234void ?{}(thread_desc & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
     35        context{ NULL, NULL };
    3336        self_cor{ name, storage, storageSize };
    34         verify(&self_cor);
     37        state = Start;
    3538        curr_cor = &self_cor;
    3639        self_mon.owner = &this;
     
    7376forall( dtype T | is_thread(T) )
    7477void __thrd_start( T& this ) {
    75         coroutine_desc* thrd_c = get_coroutine(this);
    76         thread_desc   * thrd_h = get_thread   (this);
    77         thrd_c->last = TL_GET( this_coroutine );
    78 
    79         // __cfaabi_dbg_print_safe("Thread start : %p (t %p, c %p)\n", this, thrd_c, thrd_h);
     78        thread_desc * this_thrd = get_thread(this);
     79        thread_desc * curr_thrd = TL_GET( this_thread );
    8080
    8181        disable_interrupts();
    82         create_stack(&thrd_c->stack, thrd_c->stack.size);
    83         kernelTLS.this_coroutine = thrd_c;
    8482        CtxStart(&this, CtxInvokeThread);
    85         assert( thrd_c->last->stack.context );
    86         CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context );
     83        this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
     84        verify( this_thrd->context.SP );
     85        CtxSwitch( &curr_thrd->context, &this_thrd->context );
    8786
    88         ScheduleThread(thrd_h);
     87        ScheduleThread(this_thrd);
    8988        enable_interrupts( __cfaabi_dbg_ctx );
    9089}
     
    9291extern "C" {
    9392        // KERNEL ONLY
    94         void __finish_creation(void) {
    95                 coroutine_desc* thrd_c = kernelTLS.this_coroutine;
    96                 ThreadCtxSwitch( thrd_c, thrd_c->last );
     93        void __finish_creation(thread_desc * this) {
     94                // set new coroutine that the processor is executing
     95                // and context switch to it
     96                verify( kernelTLS.this_thread != this );
     97                verify( kernelTLS.this_thread->context.SP );
     98                CtxSwitch( &this->context, &kernelTLS.this_thread->context );
    9799        }
    98100}
     
    112114}
    113115
    114 // KERNEL ONLY
    115 void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    116         // set state of current coroutine to inactive
    117         src->state = src->state == Halted ? Halted : Inactive;
    118         dst->state = Active;
    119 
    120         // set new coroutine that the processor is executing
    121         // and context switch to it
    122         kernelTLS.this_coroutine = dst;
    123         assert( src->stack.context );
    124         CtxSwitch( src->stack.context, dst->stack.context );
    125         kernelTLS.this_coroutine = src;
    126 
    127         // set state of new coroutine to active
    128         dst->state = dst->state == Halted ? Halted : Inactive;
    129         src->state = Active;
    130 }
    131 
    132116// Local Variables: //
    133117// mode: c //
  • libcfa/src/concurrency/thread.hfa

    r7951100 rb067d9b  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 29 14:07:11 2018
    13 // Update Count     : 4
     12// Last Modified On : Fri Jun 21 17:51:33 2019
     13// Update Count     : 5
    1414//
    1515
     
    1919#include "invoke.h"
    2020
    21 #include "coroutine"
    22 #include "kernel"
    23 #include "monitor"
     21#include "coroutine.hfa"
     22#include "kernel.hfa"
     23#include "monitor.hfa"
    2424
    2525//-----------------------------------------------------------------------------
     
    6161void ^?{}(thread_desc & this);
    6262
    63 static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 0 }; }
     63static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 65000 }; }
    6464static inline void ?{}(thread_desc & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, NULL, stackSize }; }
    6565static inline void ?{}(thread_desc & this, void * storage, size_t storageSize )                             { this{ "Anonymous Thread", *mainCluster, storage, storageSize }; }
    66 static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 0 }; }
    67 static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, 0, stackSize }; }
     66static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 65000 }; }
     67static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, NULL, stackSize }; }
    6868static inline void ?{}(thread_desc & this, struct cluster & cl, void * storage, size_t storageSize )        { this{ "Anonymous Thread", cl, storage, storageSize }; }
    69 static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 0 }; }
    70 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 0 }; }
     69static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 65000 }; }
     70static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 65000 }; }
    7171static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, NULL, stackSize }; }
    7272
     
    9191void yield( unsigned times );
    9292
     93static inline struct thread_desc * active_thread () { return TL_GET( this_thread ); }
     94
    9395// Local Variables: //
    9496// mode: c //
Note: See TracChangeset for help on using the changeset viewer.