Ignore:
File:
1 edited

Legend:

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

    r6011658 r09f357ec  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug 31 07:08:20 2020
    13 // Update Count     : 71
     12// Last Modified On : Thu Dec  5 16:25:52 2019
     13// Update Count     : 52
    1414//
    1515
    1616#define __cforall_thread__
    17 // #define __CFA_DEBUG_PRINT_RUNTIME_CORE__
    1817
    1918//C Includes
     19#include <stddef.h>
    2020#include <errno.h>
     21#include <string.h>
     22extern "C" {
    2123#include <stdio.h>
     24#include <fenv.h>
     25#include <sys/resource.h>
    2226#include <signal.h>
    2327#include <unistd.h>
     28#include <limits.h>                                                                             // PTHREAD_STACK_MIN
     29#include <sys/mman.h>                                                                   // mprotect
     30}
    2431
    2532//CFA Includes
     33#include "time.hfa"
    2634#include "kernel_private.hfa"
    2735#include "preemption.hfa"
     36#include "startup.hfa"
    2837
    2938//Private includes
     
    3140#include "invoke.h"
    3241
    33 
    3442//-----------------------------------------------------------------------------
    3543// Some assembly required
    3644#if defined( __i386 )
     45        #define CtxGet( ctx )        \
     46                __asm__ volatile (     \
     47                        "movl %%esp,%0\n"\
     48                        "movl %%ebp,%1\n"\
     49                        : "=rm" (ctx.SP),\
     50                                "=rm" (ctx.FP) \
     51                )
     52
    3753        // mxcr : SSE Status and Control bits (control bits are preserved across function calls)
    3854        // fcw  : X87 FPU control word (preserved across function calls)
     
    5672
    5773#elif defined( __x86_64 )
     74        #define CtxGet( ctx )        \
     75                __asm__ volatile (     \
     76                        "movq %%rsp,%0\n"\
     77                        "movq %%rbp,%1\n"\
     78                        : "=rm" (ctx.SP),\
     79                                "=rm" (ctx.FP) \
     80                )
     81
    5882        #define __x87_store         \
    5983                uint32_t __mxcr;      \
     
    7498                )
    7599
    76 #elif defined( __arm__ )
    77         #define __x87_store
    78         #define __x87_load
    79 
    80 #elif defined( __aarch64__ )
    81         #define __x87_store              \
    82                 uint32_t __fpcntl[2];    \
    83                 __asm__ volatile (    \
    84                         "mrs x9, FPCR\n" \
    85                         "mrs x10, FPSR\n"  \
    86                         "stp x9, x10, %0\n"  \
    87                         : "=m" (__fpcntl) : : "x9", "x10" \
    88                 )
    89 
    90         #define __x87_load         \
    91                 __asm__ volatile (    \
    92                         "ldp x9, x10, %0\n"  \
    93                         "msr FPSR, x10\n"  \
    94                         "msr FPCR, x9\n" \
    95                 : "=m" (__fpcntl) : : "x9", "x10" \
    96                 )
    97 
     100
     101#elif defined( __ARM_ARCH )
     102#define CtxGet( ctx ) __asm__ ( \
     103                "mov %0,%%sp\n"   \
     104                "mov %1,%%r11\n"   \
     105        : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    98106#else
    99         #error unsupported hardware architecture
     107        #error unknown hardware architecture
    100108#endif
    101109
    102 extern $thread * mainThread;
    103 extern processor * mainProcessor;
    104 
    105 //-----------------------------------------------------------------------------
    106 // Kernel Scheduling logic
    107 static $thread * __next_thread(cluster * this);
    108 static $thread * __next_thread_slow(cluster * this);
    109 static void __run_thread(processor * this, $thread * dst);
    110 static void __wake_one(cluster * cltr);
    111 
    112 static void push  (__cluster_idles & idles, processor & proc);
    113 static void remove(__cluster_idles & idles, processor & proc);
    114 static [unsigned idle, unsigned total, * processor] query( & __cluster_idles idles );
    115 
     110//-----------------------------------------------------------------------------
     111//Start and stop routine for the kernel, declared first to make sure they run first
     112static void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     113static void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
     114
     115//-----------------------------------------------------------------------------
     116// Kernel storage
     117KERNEL_STORAGE(cluster,         mainCluster);
     118KERNEL_STORAGE(processor,       mainProcessor);
     119KERNEL_STORAGE(thread_desc,     mainThread);
     120KERNEL_STORAGE(__stack_t,       mainThreadCtx);
     121
     122cluster     * mainCluster;
     123processor   * mainProcessor;
     124thread_desc * mainThread;
     125
     126extern "C" {
     127        struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
     128}
     129
     130size_t __page_size = 0;
     131
     132//-----------------------------------------------------------------------------
     133// Global state
     134thread_local struct KernelThreadData kernelTLS __attribute__ ((tls_model ( "initial-exec" ))) = {
     135        NULL,                                                                                           // cannot use 0p
     136        NULL,
     137        { 1, false, false },
     138        6u //this should be seeded better but due to a bug calling rdtsc doesn't work
     139};
     140
     141//-----------------------------------------------------------------------------
     142// Struct to steal stack
     143struct current_stack_info_t {
     144        __stack_t * storage;                                                            // pointer to stack object
     145        void * base;                                                                            // base of stack
     146        void * limit;                                                                           // stack grows towards stack limit
     147        void * context;                                                                         // address of cfa_context_t
     148};
     149
     150void ?{}( current_stack_info_t & this ) {
     151        __stack_context_t ctx;
     152        CtxGet( ctx );
     153        this.base = ctx.FP;
     154
     155        rlimit r;
     156        getrlimit( RLIMIT_STACK, &r);
     157        size_t size = r.rlim_cur;
     158
     159        this.limit = (void *)(((intptr_t)this.base) - size);
     160        this.context = &storage_mainThreadCtx;
     161}
     162
     163//-----------------------------------------------------------------------------
     164// Main thread construction
     165
     166void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) {
     167        stack.storage = info->storage;
     168        with(*stack.storage) {
     169                limit     = info->limit;
     170                base      = info->base;
     171        }
     172        __attribute__((may_alias)) intptr_t * istorage = (intptr_t*) &stack.storage;
     173        *istorage |= 0x1;
     174        name = "Main Thread";
     175        state = Start;
     176        starter = 0p;
     177        last = 0p;
     178        cancellation = 0p;
     179}
     180
     181void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) {
     182        state = Start;
     183        self_cor{ info };
     184        curr_cor = &self_cor;
     185        curr_cluster = mainCluster;
     186        self_mon.owner = &this;
     187        self_mon.recursion = 1;
     188        self_mon_p = &self_mon;
     189        next = 0p;
     190
     191        node.next = 0p;
     192        node.prev = 0p;
     193        doregister(curr_cluster, this);
     194
     195        monitors{ &self_mon_p, 1, (fptr_t)0 };
     196}
     197
     198//-----------------------------------------------------------------------------
     199// Processor coroutine
     200void ?{}(processorCtx_t & this) {
     201
     202}
     203
     204// Construct the processor context of non-main processors
     205static void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) {
     206        (this.__cor){ info };
     207        this.proc = proc;
     208}
     209
     210static void start(processor * this);
     211void ?{}(processor & this, const char * name, cluster & cltr) with( this ) {
     212        this.name = name;
     213        this.cltr = &cltr;
     214        terminated{ 0 };
     215        do_terminate = false;
     216        preemption_alarm = 0p;
     217        pending_preemption = false;
     218        runner.proc = &this;
     219
     220        idleLock{};
     221
     222        start( &this );
     223}
     224
     225void ^?{}(processor & this) with( this ){
     226        if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) {
     227                __cfaabi_dbg_print_safe("Kernel : core %p signaling termination\n", &this);
     228
     229                __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED);
     230                wake( &this );
     231
     232                P( terminated );
     233                verify( kernelTLS.this_processor != &this);
     234        }
     235
     236        pthread_join( kernel_thread, 0p );
     237        free( this.stack );
     238}
     239
     240void ?{}(cluster & this, const char * name, Duration preemption_rate) with( this ) {
     241        this.name = name;
     242        this.preemption_rate = preemption_rate;
     243        ready_queue{};
     244        ready_queue_lock{};
     245
     246        procs{ __get };
     247        idles{ __get };
     248        threads{ __get };
     249
     250        doregister(this);
     251}
     252
     253void ^?{}(cluster & this) {
     254        unregister(this);
     255}
    116256
    117257//=============================================================================================
    118258// Kernel Scheduling logic
    119259//=============================================================================================
     260static void runThread(processor * this, thread_desc * dst);
     261static void finishRunning(processor * this);
     262static void halt(processor * this);
     263
    120264//Main of the processor contexts
    121265void main(processorCtx_t & runner) {
    122266        // Because of a bug, we couldn't initialized the seed on construction
    123267        // Do it here
    124         __cfaabi_tls.rand_seed ^= rdtscl();
    125         __cfaabi_tls.ready_rng.fwd_seed = 25214903917_l64u * (rdtscl() ^ (uintptr_t)&runner);
    126         __tls_rand_advance_bck();
     268        kernelTLS.rand_seed ^= rdtscl();
    127269
    128270        processor * this = runner.proc;
    129271        verify(this);
    130272
    131         __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this);
    132         #if !defined(__CFA_NO_STATISTICS__)
    133                 if( this->print_halts ) {
    134                         __cfaabi_bits_print_safe( STDOUT_FILENO, "Processor : %d - %s (%p)\n", this->id, this->name, (void*)this);
    135                 }
    136         #endif
     273        __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this);
     274
     275        doregister(this->cltr, this);
    137276
    138277        {
     
    140279                preemption_scope scope = { this };
    141280
    142                 __cfadbg_print_safe(runtime_core, "Kernel : core %p started\n", this);
    143 
    144                 $thread * readyThread = 0p;
    145                 MAIN_LOOP:
    146                 for() {
    147                         // Try to get the next thread
    148                         readyThread = __next_thread( this->cltr );
    149 
    150                         if( !readyThread ) {
    151                                 readyThread = __next_thread_slow( this->cltr );
     281                __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);
     282
     283                thread_desc * readyThread = 0p;
     284                for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) {
     285                        readyThread = nextThread( this->cltr );
     286
     287                        if(readyThread) {
     288                                verify( ! kernelTLS.preemption_state.enabled );
     289
     290                                runThread(this, readyThread);
     291
     292                                verify( ! kernelTLS.preemption_state.enabled );
     293
     294                                //Some actions need to be taken from the kernel
     295                                finishRunning(this);
     296
     297                                spin_count = 0;
     298                        } else {
     299                                // spin(this, &spin_count);
     300                                halt(this);
    152301                        }
    153 
    154                         HALT:
    155                         if( !readyThread ) {
    156                                 // Don't block if we are done
    157                                 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
    158 
    159                                 #if !defined(__CFA_NO_STATISTICS__)
    160                                         __tls_stats()->ready.sleep.halts++;
    161                                 #endif
    162 
    163                                 // Push self to idle stack
    164                                 push(this->cltr->idles, * this);
    165 
    166                                 // Confirm the ready-queue is empty
    167                                 readyThread = __next_thread_slow( this->cltr );
    168                                 if( readyThread ) {
    169                                         // A thread was found, cancel the halt
    170                                         remove(this->cltr->idles, * this);
    171 
    172                                         #if !defined(__CFA_NO_STATISTICS__)
    173                                                 __tls_stats()->ready.sleep.cancels++;
    174                                         #endif
    175 
    176                                         // continue the mai loop
    177                                         break HALT;
    178                                 }
    179 
    180                                 #if !defined(__CFA_NO_STATISTICS__)
    181                                         if(this->print_halts) {
    182                                                 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->id, rdtscl());
    183                                         }
    184                                 #endif
    185 
    186                                 wait( this->idle );
    187 
    188                                 #if !defined(__CFA_NO_STATISTICS__)
    189                                         if(this->print_halts) {
    190                                                 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->id, rdtscl());
    191                                         }
    192                                 #endif
    193 
    194                                 // We were woken up, remove self from idle
    195                                 remove(this->cltr->idles, * this);
    196 
    197                                 // DON'T just proceed, start looking again
    198                                 continue MAIN_LOOP;
    199                         }
    200 
    201                         /* paranoid */ verify( readyThread );
    202 
    203                         // We found a thread run it
    204                         __run_thread(this, readyThread);
    205 
    206                         // Are we done?
    207                         if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
    208302                }
    209303
    210                 __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this);
    211         }
     304                __cfaabi_dbg_print_safe("Kernel : core %p stopping\n", this);
     305        }
     306
     307        unregister(this->cltr, this);
    212308
    213309        V( this->terminated );
    214310
    215         if(this == mainProcessor) {
    216                 // HACK : the coroutine context switch expects this_thread to be set
    217                 // and it make sense for it to be set in all other cases except here
    218                 // fake it
    219                 __cfaabi_tls.this_thread = mainThread;
    220         }
    221 
    222         __cfadbg_print_safe(runtime_core, "Kernel : core %p terminated\n", this);
     311        __cfaabi_dbg_print_safe("Kernel : core %p terminated\n", this);
    223312}
    224313
     
    229318// runThread runs a thread by context switching
    230319// from the processor coroutine to the target thread
    231 static void __run_thread(processor * this, $thread * thrd_dst) {
    232         /* paranoid */ verify( ! __preemption_enabled() );
    233         /* paranoid */ verifyf( thrd_dst->state == Ready || thrd_dst->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", thrd_dst->state, thrd_dst->preempted);
    234         /* paranoid */ verifyf( thrd_dst->link.next == 0p, "Expected null got %p", thrd_dst->link.next );
    235         __builtin_prefetch( thrd_dst->context.SP );
    236 
    237         $coroutine * proc_cor = get_coroutine(this->runner);
    238 
    239         // set state of processor coroutine to inactive
    240         verify(proc_cor->state == Active);
    241         proc_cor->state = Blocked;
    242 
    243         // Actually run the thread
    244         RUNNING:  while(true) {
    245                 thrd_dst->preempted = __NO_PREEMPTION;
    246                 thrd_dst->state = Active;
    247 
    248                 // Update global state
    249                 kernelTLS().this_thread = thrd_dst;
    250 
    251                 /* paranoid */ verify( ! __preemption_enabled() );
    252                 /* paranoid */ verify( kernelTLS().this_thread == thrd_dst );
    253                 /* paranoid */ verify( thrd_dst->curr_cluster == this->cltr );
    254                 /* paranoid */ verify( thrd_dst->context.SP );
    255                 /* paranoid */ verify( thrd_dst->state != Halted );
    256                 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
    257                 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
    258                 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary );
    259 
    260 
    261 
    262                 // set context switch to the thread that the processor is executing
    263                 __cfactx_switch( &proc_cor->context, &thrd_dst->context );
    264                 // when __cfactx_switch returns we are back in the processor coroutine
    265 
    266                 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary );
    267                 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst );
    268                 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst );
    269                 /* paranoid */ verify( thrd_dst->context.SP );
    270                 /* paranoid */ verify( thrd_dst->curr_cluster == this->cltr );
    271                 /* paranoid */ verify( kernelTLS().this_thread == thrd_dst );
    272                 /* paranoid */ verify( ! __preemption_enabled() );
    273 
    274                 // Reset global state
    275                 kernelTLS().this_thread = 0p;
    276 
    277                 // We just finished running a thread, there are a few things that could have happened.
    278                 // 1 - Regular case : the thread has blocked and now one has scheduled it yet.
    279                 // 2 - Racy case    : the thread has blocked but someone has already tried to schedule it.
    280                 // 4 - Preempted
    281                 // In case 1, we may have won a race so we can't write to the state again.
    282                 // In case 2, we lost the race so we now own the thread.
    283 
    284                 if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) {
    285                         // The thread was preempted, reschedule it and reset the flag
    286                         __schedule_thread( thrd_dst );
    287                         break RUNNING;
     320static void runThread(processor * this, thread_desc * thrd_dst) {
     321        coroutine_desc * proc_cor = get_coroutine(this->runner);
     322
     323        // Reset the terminating actions here
     324        this->finish.action_code = No_Action;
     325
     326        // Update global state
     327        kernelTLS.this_thread = thrd_dst;
     328
     329        // set state of processor coroutine to inactive and the thread to active
     330        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     331        thrd_dst->state = Active;
     332
     333        // set context switch to the thread that the processor is executing
     334        verify( thrd_dst->context.SP );
     335        CtxSwitch( &proc_cor->context, &thrd_dst->context );
     336        // when CtxSwitch returns we are back in the processor coroutine
     337
     338        // set state of processor coroutine to active and the thread to inactive
     339        thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive;
     340        proc_cor->state = Active;
     341}
     342
     343// KERNEL_ONLY
     344static void returnToKernel() {
     345        coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
     346        thread_desc * thrd_src = kernelTLS.this_thread;
     347
     348        // set state of current coroutine to inactive
     349        thrd_src->state = thrd_src->state == Halted ? Halted : Inactive;
     350        proc_cor->state = Active;
     351        int local_errno = *__volatile_errno();
     352        #if defined( __i386 ) || defined( __x86_64 )
     353                __x87_store;
     354        #endif
     355
     356        // set new coroutine that the processor is executing
     357        // and context switch to it
     358        verify( proc_cor->context.SP );
     359        CtxSwitch( &thrd_src->context, &proc_cor->context );
     360
     361        // set state of new coroutine to active
     362        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     363        thrd_src->state = Active;
     364
     365        #if defined( __i386 ) || defined( __x86_64 )
     366                __x87_load;
     367        #endif
     368        *__volatile_errno() = local_errno;
     369}
     370
     371// KERNEL_ONLY
     372// Once a thread has finished running, some of
     373// its final actions must be executed from the kernel
     374static void finishRunning(processor * this) with( this->finish ) {
     375        verify( ! kernelTLS.preemption_state.enabled );
     376        choose( action_code ) {
     377        case No_Action:
     378                break;
     379        case Release:
     380                unlock( *lock );
     381        case Schedule:
     382                ScheduleThread( thrd );
     383        case Release_Schedule:
     384                unlock( *lock );
     385                ScheduleThread( thrd );
     386        case Release_Multi:
     387                for(int i = 0; i < lock_count; i++) {
     388                        unlock( *locks[i] );
    288389                }
    289 
    290                 if(unlikely(thrd_dst->state == Halting)) {
    291                         // The thread has halted, it should never be scheduled/run again
    292                         // finish the thread
    293                         __thread_finish( thrd_dst );
    294                         break RUNNING;
     390        case Release_Multi_Schedule:
     391                for(int i = 0; i < lock_count; i++) {
     392                        unlock( *locks[i] );
    295393                }
    296 
    297                 /* paranoid */ verify( thrd_dst->state == Active );
    298                 thrd_dst->state = Blocked;
    299 
    300                 // set state of processor coroutine to active and the thread to inactive
    301                 int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST);
    302                 switch(old_ticket) {
    303                         case TICKET_RUNNING:
    304                                 // This is case 1, the regular case, nothing more is needed
    305                                 break RUNNING;
    306                         case TICKET_UNBLOCK:
    307                                 // This is case 2, the racy case, someone tried to run this thread before it finished blocking
    308                                 // In this case, just run it again.
    309                                 continue RUNNING;
    310                         default:
    311                                 // This makes no sense, something is wrong abort
    312                                 abort();
     394                for(int i = 0; i < thrd_count; i++) {
     395                        ScheduleThread( thrds[i] );
    313396                }
    314         }
    315 
    316         // Just before returning to the processor, set the processor coroutine to active
    317         proc_cor->state = Active;
    318 
    319         /* paranoid */ verify( ! __preemption_enabled() );
     397        case Callback:
     398                callback();
     399        default:
     400                abort("KERNEL ERROR: Unexpected action to run after thread");
     401        }
    320402}
    321403
    322404// KERNEL_ONLY
    323 void returnToKernel() {
    324         /* paranoid */ verify( ! __preemption_enabled() );
    325         $coroutine * proc_cor = get_coroutine(kernelTLS().this_processor->runner);
    326         $thread * thrd_src = kernelTLS().this_thread;
    327 
    328         #if !defined(__CFA_NO_STATISTICS__)
    329                 struct processor * last_proc = kernelTLS().this_processor;
    330         #endif
    331 
    332         // Run the thread on this processor
    333         {
    334                 int local_errno = *__volatile_errno();
    335                 #if defined( __i386 ) || defined( __x86_64 )
    336                         __x87_store;
    337                 #endif
    338                 /* paranoid */ verify( proc_cor->context.SP );
    339                 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_src->canary );
    340                 __cfactx_switch( &thrd_src->context, &proc_cor->context );
    341                 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_src->canary );
    342                 #if defined( __i386 ) || defined( __x86_64 )
    343                         __x87_load;
    344                 #endif
    345                 *__volatile_errno() = local_errno;
    346         }
    347 
    348         #if !defined(__CFA_NO_STATISTICS__)
    349                 if(last_proc != kernelTLS().this_processor) {
    350                         __tls_stats()->ready.threads.migration++;
     405// Context invoker for processors
     406// This is the entry point for processors (kernel threads)
     407// It effectively constructs a coroutine by stealing the pthread stack
     408static void * CtxInvokeProcessor(void * arg) {
     409        processor * proc = (processor *) arg;
     410        kernelTLS.this_processor = proc;
     411        kernelTLS.this_thread    = 0p;
     412        kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
     413        // SKULLDUGGERY: We want to create a context for the processor coroutine
     414        // which is needed for the 2-step context switch. However, there is no reason
     415        // to waste the perfectly valid stack create by pthread.
     416        current_stack_info_t info;
     417        __stack_t ctx;
     418        info.storage = &ctx;
     419        (proc->runner){ proc, &info };
     420
     421        __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
     422
     423        //Set global state
     424        kernelTLS.this_thread = 0p;
     425
     426        //We now have a proper context from which to schedule threads
     427        __cfaabi_dbg_print_safe("Kernel : core %p created (%p, %p)\n", proc, &proc->runner, &ctx);
     428
     429        // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
     430        // resume it to start it like it normally would, it will just context switch
     431        // back to here. Instead directly call the main since we already are on the
     432        // appropriate stack.
     433        get_coroutine(proc->runner)->state = Active;
     434        main( proc->runner );
     435        get_coroutine(proc->runner)->state = Halted;
     436
     437        // Main routine of the core returned, the core is now fully terminated
     438        __cfaabi_dbg_print_safe("Kernel : core %p main ended (%p)\n", proc, &proc->runner);
     439
     440        return 0p;
     441}
     442
     443static void Abort( int ret, const char * func ) {
     444        if ( ret ) {                                                                            // pthread routines return errno values
     445                abort( "%s : internal error, error(%d) %s.", func, ret, strerror( ret ) );
     446        } // if
     447} // Abort
     448
     449void * create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {
     450        pthread_attr_t attr;
     451
     452        Abort( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     453
     454        size_t stacksize;
     455        // default stack size, normally defined by shell limit
     456        Abort( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
     457        assert( stacksize >= PTHREAD_STACK_MIN );
     458
     459        void * stack;
     460        __cfaabi_dbg_debug_do(
     461                stack = memalign( __page_size, stacksize + __page_size );
     462                // pthread has no mechanism to create the guard page in user supplied stack.
     463                if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {
     464                        abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
     465                } // if
     466        );
     467        __cfaabi_dbg_no_debug_do(
     468                stack = malloc( stacksize );
     469        );
     470
     471        Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
     472
     473        Abort( pthread_create( pthread, &attr, start, arg ), "pthread_create" );
     474        return stack;
     475}
     476
     477static void start(processor * this) {
     478        __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", this);
     479
     480        this->stack = create_pthread( &this->kernel_thread, CtxInvokeProcessor, (void *)this );
     481
     482        __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);
     483}
     484
     485// KERNEL_ONLY
     486void kernel_first_resume( processor * this ) {
     487        thread_desc * src = mainThread;
     488        coroutine_desc * dst = get_coroutine(this->runner);
     489
     490        verify( ! kernelTLS.preemption_state.enabled );
     491
     492        kernelTLS.this_thread->curr_cor = dst;
     493        __stack_prepare( &dst->stack, 65000 );
     494        CtxStart(main, dst, this->runner, CtxInvokeCoroutine);
     495
     496        verify( ! kernelTLS.preemption_state.enabled );
     497
     498        dst->last = &src->self_cor;
     499        dst->starter = dst->starter ? dst->starter : &src->self_cor;
     500
     501        // set state of current coroutine to inactive
     502        src->state = src->state == Halted ? Halted : Inactive;
     503
     504        // context switch to specified coroutine
     505        verify( dst->context.SP );
     506        CtxSwitch( &src->context, &dst->context );
     507        // when CtxSwitch returns we are back in the src coroutine
     508
     509        mainThread->curr_cor = &mainThread->self_cor;
     510
     511        // set state of new coroutine to active
     512        src->state = Active;
     513
     514        verify( ! kernelTLS.preemption_state.enabled );
     515}
     516
     517// KERNEL_ONLY
     518void kernel_last_resume( processor * this ) {
     519        coroutine_desc * src = &mainThread->self_cor;
     520        coroutine_desc * dst = get_coroutine(this->runner);
     521
     522        verify( ! kernelTLS.preemption_state.enabled );
     523        verify( dst->starter == src );
     524        verify( dst->context.SP );
     525
     526        // context switch to the processor
     527        CtxSwitch( &src->context, &dst->context );
     528}
     529
     530//-----------------------------------------------------------------------------
     531// Scheduler routines
     532
     533// KERNEL ONLY
     534void ScheduleThread( thread_desc * thrd ) {
     535        verify( thrd );
     536        verify( thrd->state != Halted );
     537
     538        verify( ! kernelTLS.preemption_state.enabled );
     539
     540        verifyf( thrd->next == 0p, "Expected null got %p", thrd->next );
     541
     542        with( *thrd->curr_cluster ) {
     543                lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
     544                bool was_empty = !(ready_queue != 0);
     545                append( ready_queue, thrd );
     546                unlock( ready_queue_lock );
     547
     548                if(was_empty) {
     549                        lock      (proc_list_lock __cfaabi_dbg_ctx2);
     550                        if(idles) {
     551                                wake_fast(idles.head);
     552                        }
     553                        unlock    (proc_list_lock);
    351554                }
    352         #endif
    353 
    354         /* paranoid */ verify( ! __preemption_enabled() );
    355         /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) < ((uintptr_t)__get_stack(thrd_src->curr_cor)->base ), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too small.\n", thrd_src );
    356         /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) > ((uintptr_t)__get_stack(thrd_src->curr_cor)->limit), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too large.\n", thrd_src );
    357 }
    358 
    359 //-----------------------------------------------------------------------------
    360 // Scheduler routines
     555                else if( struct processor * idle = idles.head ) {
     556                        wake_fast(idle);
     557                }
     558
     559        }
     560
     561        verify( ! kernelTLS.preemption_state.enabled );
     562}
     563
    361564// KERNEL ONLY
    362 void __schedule_thread( $thread * thrd ) {
    363         /* paranoid */ verify( ! __preemption_enabled() );
    364         /* paranoid */ verify( kernelTLS().this_proc_id );
    365         /* paranoid */ verify( thrd );
    366         /* paranoid */ verify( thrd->state != Halted );
    367         /* paranoid */ verify( thrd->curr_cluster );
    368         /* paranoid */ #if defined( __CFA_WITH_VERIFY__ )
    369         /* paranoid */  if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,
    370                                         "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted );
    371         /* paranoid */  if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active,
    372                                         "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted );
    373         /* paranoid */ #endif
    374         /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next );
    375         /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd->canary );
    376 
    377 
    378         if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
    379 
    380         ready_schedule_lock();
    381                 // Dereference the thread now because once we push it, there is not guaranteed it's still valid.
    382                 struct cluster * cl = thrd->curr_cluster;
    383 
    384                 // push the thread to the cluster ready-queue
    385                 push( cl, thrd );
    386 
    387                 // variable thrd is no longer safe to use
    388 
    389                 // wake the cluster using the save variable.
    390                 __wake_one( cl );
    391         ready_schedule_unlock();
    392 
    393         /* paranoid */ verify( ! __preemption_enabled() );
     565thread_desc * nextThread(cluster * this) with( *this ) {
     566        verify( ! kernelTLS.preemption_state.enabled );
     567        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
     568        thread_desc * head = pop_head( ready_queue );
     569        unlock( ready_queue_lock );
     570        verify( ! kernelTLS.preemption_state.enabled );
     571        return head;
     572}
     573
     574void BlockInternal() {
     575        disable_interrupts();
     576        verify( ! kernelTLS.preemption_state.enabled );
     577        returnToKernel();
     578        verify( ! kernelTLS.preemption_state.enabled );
     579        enable_interrupts( __cfaabi_dbg_ctx );
     580}
     581
     582void BlockInternal( __spinlock_t * lock ) {
     583        disable_interrupts();
     584        with( *kernelTLS.this_processor ) {
     585                finish.action_code = Release;
     586                finish.lock        = lock;
     587        }
     588
     589        verify( ! kernelTLS.preemption_state.enabled );
     590        returnToKernel();
     591        verify( ! kernelTLS.preemption_state.enabled );
     592
     593        enable_interrupts( __cfaabi_dbg_ctx );
     594}
     595
     596void BlockInternal( thread_desc * thrd ) {
     597        disable_interrupts();
     598        with( * kernelTLS.this_processor ) {
     599                finish.action_code = Schedule;
     600                finish.thrd        = thrd;
     601        }
     602
     603        verify( ! kernelTLS.preemption_state.enabled );
     604        returnToKernel();
     605        verify( ! kernelTLS.preemption_state.enabled );
     606
     607        enable_interrupts( __cfaabi_dbg_ctx );
     608}
     609
     610void BlockInternal( __spinlock_t * lock, thread_desc * thrd ) {
     611        assert(thrd);
     612        disable_interrupts();
     613        with( * kernelTLS.this_processor ) {
     614                finish.action_code = Release_Schedule;
     615                finish.lock        = lock;
     616                finish.thrd        = thrd;
     617        }
     618
     619        verify( ! kernelTLS.preemption_state.enabled );
     620        returnToKernel();
     621        verify( ! kernelTLS.preemption_state.enabled );
     622
     623        enable_interrupts( __cfaabi_dbg_ctx );
     624}
     625
     626void BlockInternal(__spinlock_t * locks [], unsigned short count) {
     627        disable_interrupts();
     628        with( * kernelTLS.this_processor ) {
     629                finish.action_code = Release_Multi;
     630                finish.locks       = locks;
     631                finish.lock_count  = count;
     632        }
     633
     634        verify( ! kernelTLS.preemption_state.enabled );
     635        returnToKernel();
     636        verify( ! kernelTLS.preemption_state.enabled );
     637
     638        enable_interrupts( __cfaabi_dbg_ctx );
     639}
     640
     641void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {
     642        disable_interrupts();
     643        with( *kernelTLS.this_processor ) {
     644                finish.action_code = Release_Multi_Schedule;
     645                finish.locks       = locks;
     646                finish.lock_count  = lock_count;
     647                finish.thrds       = thrds;
     648                finish.thrd_count  = thrd_count;
     649        }
     650
     651        verify( ! kernelTLS.preemption_state.enabled );
     652        returnToKernel();
     653        verify( ! kernelTLS.preemption_state.enabled );
     654
     655        enable_interrupts( __cfaabi_dbg_ctx );
     656}
     657
     658void BlockInternal(__finish_callback_fptr_t callback) {
     659        disable_interrupts();
     660        with( *kernelTLS.this_processor ) {
     661                finish.action_code = Callback;
     662                finish.callback    = callback;
     663        }
     664
     665        verify( ! kernelTLS.preemption_state.enabled );
     666        returnToKernel();
     667        verify( ! kernelTLS.preemption_state.enabled );
     668
     669        enable_interrupts( __cfaabi_dbg_ctx );
    394670}
    395671
    396672// KERNEL ONLY
    397 static inline $thread * __next_thread(cluster * this) with( *this ) {
    398         /* paranoid */ verify( ! __preemption_enabled() );
    399         /* paranoid */ verify( kernelTLS().this_proc_id );
    400 
    401         ready_schedule_lock();
    402                 $thread * thrd = pop( this );
    403         ready_schedule_unlock();
    404 
    405         /* paranoid */ verify( kernelTLS().this_proc_id );
    406         /* paranoid */ verify( ! __preemption_enabled() );
    407         return thrd;
    408 }
    409 
    410 // KERNEL ONLY
    411 static inline $thread * __next_thread_slow(cluster * this) with( *this ) {
    412         /* paranoid */ verify( ! __preemption_enabled() );
    413         /* paranoid */ verify( kernelTLS().this_proc_id );
    414 
    415         ready_schedule_lock();
    416                 $thread * thrd = pop_slow( this );
    417         ready_schedule_unlock();
    418 
    419         /* paranoid */ verify( kernelTLS().this_proc_id );
    420         /* paranoid */ verify( ! __preemption_enabled() );
    421         return thrd;
    422 }
    423 
    424 void unpark( $thread * thrd ) {
    425         if( !thrd ) return;
    426 
    427         int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST);
    428         switch(old_ticket) {
    429                 case TICKET_RUNNING:
    430                         // Wake won the race, the thread will reschedule/rerun itself
    431                         break;
    432                 case TICKET_BLOCKED:
    433                         /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION );
    434                         /* paranoid */ verify( thrd->state == Blocked );
    435 
    436                         {
    437                                 /* paranoid */ verify( publicTLS_get(this_proc_id) );
    438                                 bool full = publicTLS_get(this_proc_id)->full_proc;
    439                                 if(full) disable_interrupts();
    440 
    441                                 /* paranoid */ verify( ! __preemption_enabled() );
    442 
    443                                 // Wake lost the race,
    444                                 __schedule_thread( thrd );
    445 
    446                                 /* paranoid */ verify( ! __preemption_enabled() );
    447 
    448                                 if(full) enable_interrupts( __cfaabi_dbg_ctx );
    449                                 /* paranoid */ verify( publicTLS_get(this_proc_id) );
    450                         }
    451 
    452                         break;
    453                 default:
    454                         // This makes no sense, something is wrong abort
    455                         abort("Thread %p (%s) has mismatch park/unpark\n", thrd, thrd->self_cor.name);
    456         }
    457 }
    458 
    459 void park( void ) {
    460         /* paranoid */ verify( __preemption_enabled() );
     673void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
     674        verify( ! kernelTLS.preemption_state.enabled );
     675        with( * kernelTLS.this_processor ) {
     676                finish.action_code = thrd ? Release_Schedule : Release;
     677                finish.lock        = lock;
     678                finish.thrd        = thrd;
     679        }
     680
     681        returnToKernel();
     682}
     683
     684//=============================================================================================
     685// Kernel Setup logic
     686//=============================================================================================
     687//-----------------------------------------------------------------------------
     688// Kernel boot procedures
     689static void kernel_startup(void) {
     690        verify( ! kernelTLS.preemption_state.enabled );
     691        __cfaabi_dbg_print_safe("Kernel : Starting\n");
     692
     693        __page_size = sysconf( _SC_PAGESIZE );
     694
     695        __cfa_dbg_global_clusters.list{ __get };
     696        __cfa_dbg_global_clusters.lock{};
     697
     698        // Initialize the main cluster
     699        mainCluster = (cluster *)&storage_mainCluster;
     700        (*mainCluster){"Main Cluster"};
     701
     702        __cfaabi_dbg_print_safe("Kernel : Main cluster ready\n");
     703
     704        // Start by initializing the main thread
     705        // SKULLDUGGERY: the mainThread steals the process main thread
     706        // which will then be scheduled by the mainProcessor normally
     707        mainThread = (thread_desc *)&storage_mainThread;
     708        current_stack_info_t info;
     709        info.storage = (__stack_t*)&storage_mainThreadCtx;
     710        (*mainThread){ &info };
     711
     712        __cfaabi_dbg_print_safe("Kernel : Main thread ready\n");
     713
     714
     715
     716        // Construct the processor context of the main processor
     717        void ?{}(processorCtx_t & this, processor * proc) {
     718                (this.__cor){ "Processor" };
     719                this.__cor.starter = 0p;
     720                this.proc = proc;
     721        }
     722
     723        void ?{}(processor & this) with( this ) {
     724                name = "Main Processor";
     725                cltr = mainCluster;
     726                terminated{ 0 };
     727                do_terminate = false;
     728                preemption_alarm = 0p;
     729                pending_preemption = false;
     730                kernel_thread = pthread_self();
     731
     732                runner{ &this };
     733                __cfaabi_dbg_print_safe("Kernel : constructed main processor context %p\n", &runner);
     734        }
     735
     736        // Initialize the main processor and the main processor ctx
     737        // (the coroutine that contains the processing control flow)
     738        mainProcessor = (processor *)&storage_mainProcessor;
     739        (*mainProcessor){};
     740
     741        //initialize the global state variables
     742        kernelTLS.this_processor = mainProcessor;
     743        kernelTLS.this_thread    = mainThread;
     744
     745        // Enable preemption
     746        kernel_start_preemption();
     747
     748        // Add the main thread to the ready queue
     749        // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
     750        ScheduleThread(mainThread);
     751
     752        // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
     753        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
     754        // mainThread is on the ready queue when this call is made.
     755        kernel_first_resume( kernelTLS.this_processor );
     756
     757
     758
     759        // THE SYSTEM IS NOW COMPLETELY RUNNING
     760        __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n");
     761
     762        verify( ! kernelTLS.preemption_state.enabled );
     763        enable_interrupts( __cfaabi_dbg_ctx );
     764        verify( TL_GET( preemption_state.enabled ) );
     765}
     766
     767static void kernel_shutdown(void) {
     768        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
     769
     770        verify( TL_GET( preemption_state.enabled ) );
    461771        disable_interrupts();
    462         /* paranoid */ verify( ! __preemption_enabled() );
    463         /* paranoid */ verify( kernelTLS().this_thread->preempted == __NO_PREEMPTION );
    464 
    465         returnToKernel();
    466 
    467         /* paranoid */ verify( ! __preemption_enabled() );
    468         enable_interrupts( __cfaabi_dbg_ctx );
    469         /* paranoid */ verify( __preemption_enabled() );
    470 
    471 }
    472 
    473 extern "C" {
    474         // Leave the thread monitor
    475         // last routine called by a thread.
    476         // Should never return
    477         void __cfactx_thrd_leave() {
    478                 $thread * thrd = active_thread();
    479                 $monitor * this = &thrd->self_mon;
    480 
    481                 // Lock the monitor now
    482                 lock( this->lock __cfaabi_dbg_ctx2 );
    483 
    484                 disable_interrupts();
    485 
    486                 /* paranoid */ verify( ! __preemption_enabled() );
    487                 /* paranoid */ verify( thrd->state == Active );
    488                 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd->canary );
    489                 /* paranoid */ verify( kernelTLS().this_thread == thrd );
    490                 /* paranoid */ verify( thrd->context.SP );
    491                 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) > ((uintptr_t)__get_stack(thrd->curr_cor)->limit), "ERROR : $thread %p has been corrupted.\n StackPointer too large.\n", thrd );
    492                 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) < ((uintptr_t)__get_stack(thrd->curr_cor)->base ), "ERROR : $thread %p has been corrupted.\n StackPointer too small.\n", thrd );
    493 
    494                 thrd->state = Halting;
    495                 if( TICKET_RUNNING != thrd->ticket ) { abort( "Thread terminated with pending unpark" ); }
    496                 if( thrd != this->owner ) { abort( "Thread internal monitor has incorrect owner" ); }
    497                 if( this->recursion != 1) { abort( "Thread internal monitor has unbalanced recursion" ); }
    498 
    499                 // Leave the thread
    500                 returnToKernel();
    501 
    502                 // Control flow should never reach here!
    503                 abort();
    504         }
    505 }
    506 
    507 // KERNEL ONLY
    508 bool force_yield( __Preemption_Reason reason ) {
    509         /* paranoid */ verify( __preemption_enabled() );
    510         disable_interrupts();
    511         /* paranoid */ verify( ! __preemption_enabled() );
    512 
    513         $thread * thrd = kernelTLS().this_thread;
    514         /* paranoid */ verify(thrd->state == Active);
    515 
    516         // SKULLDUGGERY: It is possible that we are preempting this thread just before
    517         // it was going to park itself. If that is the case and it is already using the
    518         // intrusive fields then we can't use them to preempt the thread
    519         // If that is the case, abandon the preemption.
    520         bool preempted = false;
    521         if(thrd->link.next == 0p) {
    522                 preempted = true;
    523                 thrd->preempted = reason;
    524                 returnToKernel();
    525         }
    526 
    527         /* paranoid */ verify( ! __preemption_enabled() );
    528         enable_interrupts_noPoll();
    529         /* paranoid */ verify( __preemption_enabled() );
    530 
    531         return preempted;
     772        verify( ! kernelTLS.preemption_state.enabled );
     773
     774        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
     775        // When its coroutine terminates, it return control to the mainThread
     776        // which is currently here
     777        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
     778        kernel_last_resume( kernelTLS.this_processor );
     779        mainThread->self_cor.state = Halted;
     780
     781        // THE SYSTEM IS NOW COMPLETELY STOPPED
     782
     783        // Disable preemption
     784        kernel_stop_preemption();
     785
     786        // Destroy the main processor and its context in reverse order of construction
     787        // These were manually constructed so we need manually destroy them
     788        ^(mainProcessor->runner){};
     789        ^(mainProcessor){};
     790
     791        // Final step, destroy the main thread since it is no longer needed
     792        // Since we provided a stack to this taxk it will not destroy anything
     793        ^(mainThread){};
     794
     795        ^(__cfa_dbg_global_clusters.list){};
     796        ^(__cfa_dbg_global_clusters.lock){};
     797
     798        __cfaabi_dbg_print_safe("Kernel : Shutdown complete\n");
    532799}
    533800
    534801//=============================================================================================
    535 // Kernel Idle Sleep
     802// Kernel Quiescing
    536803//=============================================================================================
    537 // Wake a thread from the front if there are any
    538 static void __wake_one(cluster * this) {
    539         /* paranoid */ verify( ! __preemption_enabled() );
    540         /* paranoid */ verify( ready_schedule_islocked() );
    541 
    542         // Check if there is a sleeping processor
    543         processor * p;
    544         unsigned idle;
    545         unsigned total;
    546         [idle, total, p] = query(this->idles);
    547 
    548         // If no one is sleeping, we are done
    549         if( idle == 0 ) return;
    550 
    551         // We found a processor, wake it up
    552         post( p->idle );
    553 
    554         #if !defined(__CFA_NO_STATISTICS__)
    555                 __tls_stats()->ready.sleep.wakes++;
    556         #endif
    557 
    558         /* paranoid */ verify( ready_schedule_islocked() );
    559         /* paranoid */ verify( ! __preemption_enabled() );
    560 
    561         return;
    562 }
    563 
    564 // Unconditionnaly wake a thread
    565 void __wake_proc(processor * this) {
    566         __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this);
    567 
    568         disable_interrupts();
    569                 /* paranoid */ verify( ! __preemption_enabled() );
    570                 post( this->idle );
    571         enable_interrupts( __cfaabi_dbg_ctx );
    572 }
    573 
    574 static void push  (__cluster_idles & this, processor & proc) {
    575         /* paranoid */ verify( ! __preemption_enabled() );
    576         lock( this );
    577                 this.idle++;
    578                 /* paranoid */ verify( this.idle <= this.total );
    579 
    580                 insert_first(this.list, proc);
    581         unlock( this );
    582         /* paranoid */ verify( ! __preemption_enabled() );
    583 }
    584 
    585 static void remove(__cluster_idles & this, processor & proc) {
    586         /* paranoid */ verify( ! __preemption_enabled() );
    587         lock( this );
    588                 this.idle--;
    589                 /* paranoid */ verify( this.idle >= 0 );
    590 
    591                 remove(proc);
    592         unlock( this );
    593         /* paranoid */ verify( ! __preemption_enabled() );
    594 }
    595 
    596 static [unsigned idle, unsigned total, * processor] query( & __cluster_idles this ) {
    597         for() {
    598                 uint64_t l = __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST);
    599                 if( 1 == (l % 2) ) { Pause(); continue; }
    600                 unsigned idle    = this.idle;
    601                 unsigned total   = this.total;
    602                 processor * proc = &this.list`first;
    603                 // Compiler fence is unnecessary, but gcc-8 and older incorrectly reorder code without it
    604                 asm volatile("": : :"memory");
    605                 if(l != __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST)) { Pause(); continue; }
    606                 return [idle, total, proc];
     804static void halt(processor * this) with( *this ) {
     805        // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
     806
     807        with( *cltr ) {
     808                lock      (proc_list_lock __cfaabi_dbg_ctx2);
     809                remove    (procs, *this);
     810                push_front(idles, *this);
     811                unlock    (proc_list_lock);
     812        }
     813
     814        __cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this);
     815
     816        wait( idleLock );
     817
     818        __cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this);
     819
     820        with( *cltr ) {
     821                lock      (proc_list_lock __cfaabi_dbg_ctx2);
     822                remove    (idles, *this);
     823                push_front(procs, *this);
     824                unlock    (proc_list_lock);
    607825        }
    608826}
     
    619837        lock( kernel_abort_lock __cfaabi_dbg_ctx2 );
    620838
    621         // disable interrupts, it no longer makes sense to try to interrupt this processor
    622         disable_interrupts();
    623 
    624839        // first task to abort ?
    625840        if ( kernel_abort_called ) {                    // not first task to abort ?
     
    629844                sigemptyset( &mask );
    630845                sigaddset( &mask, SIGALRM );            // block SIGALRM signals
    631                 sigaddset( &mask, SIGUSR1 );            // block SIGALRM signals
    632                 sigsuspend( &mask );                            // block the processor to prevent further damage during abort
    633                 _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
     846                sigsuspend( &mask );                    // block the processor to prevent further damage during abort
     847                _exit( EXIT_FAILURE );                  // if processor unblocks before it is killed, terminate it
    634848        }
    635849        else {
     
    638852        }
    639853
    640         return __cfaabi_tls.this_thread;
     854        return kernelTLS.this_thread;
    641855}
    642856
    643857void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) {
    644         $thread * thrd = ( $thread * ) kernel_data;
     858        thread_desc * thrd = kernel_data;
    645859
    646860        if(thrd) {
     
    663877
    664878int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) {
    665         return get_coroutine(kernelTLS().this_thread) == get_coroutine(mainThread) ? 4 : 2;
     879        return get_coroutine(kernelTLS.this_thread) == get_coroutine(mainThread) ? 4 : 2;
    666880}
    667881
     
    690904void ^?{}(semaphore & this) {}
    691905
    692 bool P(semaphore & this) with( this ){
     906void P(semaphore & this) with( this ){
    693907        lock( lock __cfaabi_dbg_ctx2 );
    694908        count -= 1;
    695909        if ( count < 0 ) {
    696910                // queue current task
    697                 append( waiting, active_thread() );
     911                append( waiting, kernelTLS.this_thread );
    698912
    699913                // atomically release spin lock and block
    700                 unlock( lock );
    701                 park();
    702                 return true;
     914                BlockInternal( &lock );
    703915        }
    704916        else {
    705917            unlock( lock );
    706             return false;
    707         }
    708 }
    709 
    710 bool V(semaphore & this) with( this ) {
    711         $thread * thrd = 0p;
     918        }
     919}
     920
     921void V(semaphore & this) with( this ) {
     922        thread_desc * thrd = 0p;
    712923        lock( lock __cfaabi_dbg_ctx2 );
    713924        count += 1;
     
    720931
    721932        // make new owner
    722         unpark( thrd );
    723 
    724         return thrd != 0p;
    725 }
    726 
    727 bool V(semaphore & this, unsigned diff) with( this ) {
    728         $thread * thrd = 0p;
    729         lock( lock __cfaabi_dbg_ctx2 );
    730         int release = max(-count, (int)diff);
    731         count += diff;
    732         for(release) {
    733                 unpark( pop_head( waiting ) );
    734         }
    735 
    736         unlock( lock );
    737 
    738         return thrd != 0p;
     933        WakeThread( thrd );
     934}
     935
     936//-----------------------------------------------------------------------------
     937// Global Queues
     938void doregister( cluster     & cltr ) {
     939        lock      ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);
     940        push_front( __cfa_dbg_global_clusters.list, cltr );
     941        unlock    ( __cfa_dbg_global_clusters.lock );
     942}
     943
     944void unregister( cluster     & cltr ) {
     945        lock  ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);
     946        remove( __cfa_dbg_global_clusters.list, cltr );
     947        unlock( __cfa_dbg_global_clusters.lock );
     948}
     949
     950void doregister( cluster * cltr, thread_desc & thrd ) {
     951        lock      (cltr->thread_list_lock __cfaabi_dbg_ctx2);
     952        cltr->nthreads += 1;
     953        push_front(cltr->threads, thrd);
     954        unlock    (cltr->thread_list_lock);
     955}
     956
     957void unregister( cluster * cltr, thread_desc & thrd ) {
     958        lock  (cltr->thread_list_lock __cfaabi_dbg_ctx2);
     959        remove(cltr->threads, thrd );
     960        cltr->nthreads -= 1;
     961        unlock(cltr->thread_list_lock);
     962}
     963
     964void doregister( cluster * cltr, processor * proc ) {
     965        lock      (cltr->proc_list_lock __cfaabi_dbg_ctx2);
     966        cltr->nprocessors += 1;
     967        push_front(cltr->procs, *proc);
     968        unlock    (cltr->proc_list_lock);
     969}
     970
     971void unregister( cluster * cltr, processor * proc ) {
     972        lock  (cltr->proc_list_lock __cfaabi_dbg_ctx2);
     973        remove(cltr->procs, *proc );
     974        cltr->nprocessors -= 1;
     975        unlock(cltr->proc_list_lock);
    739976}
    740977
     
    743980__cfaabi_dbg_debug_do(
    744981        extern "C" {
    745                 void __cfaabi_dbg_record_lock(__spinlock_t & this, const char prev_name[]) {
     982                void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {
    746983                        this.prev_name = prev_name;
    747                         this.prev_thrd = kernelTLS().this_thread;
     984                        this.prev_thrd = kernelTLS.this_thread;
    748985                }
    749986        }
     
    752989//-----------------------------------------------------------------------------
    753990// Debug
    754 bool threading_enabled(void) __attribute__((const)) {
     991bool threading_enabled(void) {
    755992        return true;
    756993}
    757 
    758 //-----------------------------------------------------------------------------
    759 // Statistics
    760 #if !defined(__CFA_NO_STATISTICS__)
    761         void print_halts( processor & this ) {
    762                 this.print_halts = true;
    763         }
    764 
    765         void print_stats_now( cluster & this, int flags ) {
    766                 __print_stats( this.stats, this.print_stats, "Cluster", this.name, (void*)&this );
    767         }
    768 
    769         extern int __print_alarm_stats;
    770         void print_alarm_stats() {
    771                 __print_alarm_stats = -1;
    772         }
    773 #endif
    774994// Local Variables: //
    775995// mode: c //
Note: See TracChangeset for help on using the changeset viewer.