Changeset 82ff584


Ignore:
Timestamp:
Jun 8, 2017, 1:48:12 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
a724ac1
Parents:
8b8152e
Message:

First implementation of preemption, does not appear to work with scheduling

Location:
src/libcfa/concurrency
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/alarm.c

    r8b8152e r82ff584  
    1616
    1717extern "C" {
     18#include <errno.h>
     19#include <stdio.h>
     20#include <string.h>
    1821#include <time.h>
     22#include <unistd.h>
    1923#include <sys/time.h>
    2024}
     
    2226#include "alarm.h"
    2327#include "kernel_private.h"
     28#include "libhdr.h"
    2429#include "preemption.h"
    2530
     
    3136        timespec curr;
    3237        clock_gettime( CLOCK_REALTIME, &curr );
    33         return ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
     38        __cfa_time_t curr_time = ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
     39        LIB_DEBUG_DO(
     40                char text[256];
     41                __attribute__((unused)) int len = snprintf( text, 256, "Kernel : current time is %lu\n", curr_time );
     42                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     43        );
     44        return curr_time;
    3445}
    3546
    3647void __kernel_set_timer( __cfa_time_t alarm ) {
     48
     49        LIB_DEBUG_DO(
     50                char text[256];
     51                __attribute__((unused)) int len = snprintf( text, 256, "Kernel : set timer to %lu\n", (__cfa_time_t)alarm );
     52                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     53        );
     54
    3755        itimerval val;
    3856        val.it_value.tv_sec = alarm / TIMEGRAN;                 // seconds
     
    128146        lock( &systemProcessor->alarm_lock );
    129147        {
     148                bool first = !systemProcessor->alarms.head;
     149
    130150                insert( &systemProcessor->alarms, this );
    131151                if( systemProcessor->pending_alarm ) {
    132152                        tick_preemption();
     153                }
     154                if( first ) {
     155                        __kernel_set_timer( systemProcessor->alarms.head->alarm - __kernel_get_time() );
    133156                }
    134157        }
  • src/libcfa/concurrency/invoke.c

    r8b8152e r82ff584  
    3030extern void __suspend_internal(void);
    3131extern void __leave_monitor_desc( struct monitor_desc * this );
     32extern void disable_interrupts();
     33extern void enable_interrupts();
    3234
    3335void CtxInvokeCoroutine(
     
    6769      struct monitor_desc* mon = &thrd->mon;
    6870      cor->state = Active;
     71      enable_interrupts();
    6972
    7073      // LIB_DEBUG_PRINTF("Invoke Thread : invoking main %p (args %p)\n", main, this);
    7174      main( this );
    7275
     76      disable_interrupts();
    7377      __leave_monitor_desc( mon );
    7478
  • src/libcfa/concurrency/kernel.c

    r8b8152e r82ff584  
    154154        (&this->terminated){};
    155155        this->is_terminated = false;
    156         this->disable_preempt_count = 0;
     156        this->preemption_alarm = NULL;
     157        this->preemption = default_preemption();
     158        this->disable_preempt_count = 1;
    157159        this->pending_preemption = false;
     160        this->kernel_thread = pthread_self();
    158161
    159162        this->runner = runner;
    160         LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
     163        LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
    161164        runner{ this };
    162165}
     
    240243        //Update global state
    241244        this->current_thread = dst;
     245
     246        LIB_DEBUG_PRINT_SAFE("Kernel : running %p\n", dst);
    242247
    243248        // Context Switch to the thread
     
    322327void start(processor * this) {
    323328        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    324        
     329
     330        // SIGALRM must only be caught by the system processor
     331        sigset_t old_mask;
     332        bool is_system_proc = this_processor == &systemProcessor->proc;
     333        if ( is_system_proc ) {
     334                // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the
     335                // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user
     336                // processor, and toggle back (below) previous signal mask of the system processor.
     337
     338                sigset_t new_mask;
     339                sigemptyset( &new_mask );
     340                sigemptyset( &old_mask );
     341                sigaddset( &new_mask, SIGALRM );
     342
     343                if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) {
     344                        abortf( "internal error, sigprocmask" );
     345                }
     346
     347                assert( ! sigismember( &old_mask, SIGALRM ) );
     348        }
     349
    325350        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
     351
     352        // Toggle back previous signal mask of system processor.
     353        if ( is_system_proc ) {
     354                if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) {
     355                        abortf( "internal error, sigprocmask" );
     356                } // if
     357        } // if
    326358
    327359        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
     
    347379}
    348380
    349 void ScheduleInternal() {
     381void BlockInternal() {
     382        disable_interrupts();
    350383        suspend();
    351 }
    352 
    353 void ScheduleInternal( spinlock * lock ) {
     384        enable_interrupts();
     385}
     386
     387void BlockInternal( spinlock * lock ) {
     388        disable_interrupts();
    354389        this_processor->finish.action_code = Release;
    355390        this_processor->finish.lock = lock;
    356391        suspend();
    357 }
    358 
    359 void ScheduleInternal( thread_desc * thrd ) {
     392        enable_interrupts();
     393}
     394
     395void BlockInternal( thread_desc * thrd ) {
     396        disable_interrupts();
    360397        this_processor->finish.action_code = Schedule;
    361398        this_processor->finish.thrd = thrd;
    362399        suspend();
    363 }
    364 
    365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
     400        enable_interrupts();
     401}
     402
     403void BlockInternal( spinlock * lock, thread_desc * thrd ) {
     404        disable_interrupts();
    366405        this_processor->finish.action_code = Release_Schedule;
    367406        this_processor->finish.lock = lock;
    368407        this_processor->finish.thrd = thrd;
    369408        suspend();
    370 }
    371 
    372 void ScheduleInternal(spinlock ** locks, unsigned short count) {
     409        enable_interrupts();
     410}
     411
     412void BlockInternal(spinlock ** locks, unsigned short count) {
     413        disable_interrupts();
    373414        this_processor->finish.action_code = Release_Multi;
    374415        this_processor->finish.locks = locks;
    375416        this_processor->finish.lock_count = count;
    376417        suspend();
    377 }
    378 
    379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     418        enable_interrupts();
     419}
     420
     421void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     422        disable_interrupts();
    380423        this_processor->finish.action_code = Release_Multi_Schedule;
    381424        this_processor->finish.locks = locks;
     
    384427        this_processor->finish.thrd_count = thrd_count;
    385428        suspend();
     429        enable_interrupts();
    386430}
    387431
     
    403447        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    404448
    405         // Enable preemption
    406         kernel_start_preemption();
    407 
    408449        // Initialize the system cluster
    409450        systemCluster = (cluster *)&systemCluster_storage;
     
    426467        this_processor->current_coroutine = &mainThread->cor;
    427468
     469        // Enable preemption
     470        kernel_start_preemption();
     471
    428472        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    429473        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
     
    435479        // THE SYSTEM IS NOW COMPLETELY RUNNING
    436480        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
     481
     482        enable_interrupts();
    437483}
    438484
     
    447493
    448494        // THE SYSTEM IS NOW COMPLETELY STOPPED
     495
     496        // Disable preemption
     497        kernel_stop_preemption();
    449498
    450499        // Destroy the system processor and its context in reverse order of construction
     
    550599        if( !this->cond ) {
    551600                append( &this->blocked, this_thread() );
    552                 ScheduleInternal( &this->lock );
     601                BlockInternal( &this->lock );
    553602                lock( &this->lock );
    554603        }
  • src/libcfa/concurrency/kernel_private.h

    r8b8152e r82ff584  
    2828thread_desc * nextThread(cluster * this);
    2929
    30 void ScheduleInternal(void);
    31 void ScheduleInternal(spinlock * lock);
    32 void ScheduleInternal(thread_desc * thrd);
    33 void ScheduleInternal(spinlock * lock, thread_desc * thrd);
    34 void ScheduleInternal(spinlock ** locks, unsigned short count);
    35 void ScheduleInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);
     30void BlockInternal(void);
     31void BlockInternal(spinlock * lock);
     32void BlockInternal(thread_desc * thrd);
     33void BlockInternal(spinlock * lock, thread_desc * thrd);
     34void BlockInternal(spinlock ** locks, unsigned short count);
     35void BlockInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);
    3636
    3737//-----------------------------------------------------------------------------
     
    6060extern thread_local processor * this_processor;
    6161
    62 static inline void disable_interrupts() {
    63         __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST );
    64         assert( prev != (unsigned short) -1 );
    65 }
    66 
    67 static inline void enable_interrupts_noRF() {
    68         unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    69         assert( prev != (unsigned short) 0 );
    70 }
    71 
    72 static inline void enable_interrupts() {
    73         unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    74         assert( prev != (unsigned short) 0 );
    75         if( prev == 1 && this_processor->pending_preemption ) {
    76                 ScheduleInternal( this_processor->current_thread );
    77                 this_processor->pending_preemption = false;
    78         }
     62extern "C" {
     63        void disable_interrupts();
     64        void enable_interrupts_noRF();
     65        void enable_interrupts();
    7966}
    8067
  • src/libcfa/concurrency/monitor.c

    r8b8152e r82ff584  
    6363                        append( &this->entry_queue, thrd );
    6464                        LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);
    65                         ScheduleInternal( &this->lock );
    66 
    67                         //ScheduleInternal will unlock spinlock, no need to unlock ourselves
     65                        BlockInternal( &this->lock );
     66
     67                        //BlockInternal will unlock spinlock, no need to unlock ourselves
    6868                        return;
    6969                }
     
    172172        unsigned short count = this->monitor_count;
    173173        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
    174         spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
     174        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to BlockInternal
    175175
    176176        LIB_DEBUG_PRINT_SAFE("count %i\n", count);
     
    210210
    211211        // Everything is ready to go to sleep
    212         ScheduleInternal( locks, count, threads, thread_count );
     212        BlockInternal( locks, count, threads, thread_count );
    213213
    214214
     
    283283        unsigned short count = this->monitor_count;
    284284        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
    285         spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
     285        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to BlockInternal
    286286
    287287        lock_all( this->monitors, locks, count );
     
    311311
    312312        //Everything is ready to go to sleep
    313         ScheduleInternal( locks, count, &signallee, 1 );
     313        BlockInternal( locks, count, &signallee, 1 );
    314314
    315315
     
    343343        // unsigned short count = this->current_monitor_count;
    344344        // unsigned int recursions[ count ];            //Save the current recursion levels to restore them later
    345         // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to ScheduleInternal
     345        // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to BlockInternal
    346346
    347347        // lock_all( this->current_monitors, locks, count );
     
    352352
    353353        // // // Everything is ready to go to sleep
    354         // // ScheduleInternal( locks, count, threads, thread_count );
     354        // // BlockInternal( locks, count, threads, thread_count );
    355355
    356356
  • src/libcfa/concurrency/preemption.c

    r8b8152e r82ff584  
    1818
    1919extern "C" {
     20#include <errno.h>
    2021#include <signal.h>
    21 }
    22 
    23 #define __CFA_DEFAULT_PREEMPTION__ 10
     22#include <stdio.h>
     23#include <string.h>
     24#include <unistd.h>
     25}
     26
     27#include "libhdr.h"
     28
     29#define __CFA_DEFAULT_PREEMPTION__ 10000
    2430
    2531__attribute__((weak)) unsigned int default_preemption() {
     
    2733}
    2834
     35#define __CFA_SIGCXT__ ucontext_t *
     36#define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt
     37
    2938static void preempt( processor   * this );
    3039static void timeout( thread_desc * this );
    3140
     41void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
     42void sigHandler_alarm    ( __CFA_SIGPARMS__ );
     43
     44static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
     45
    3246//=============================================================================================
    3347// Kernel Preemption logic
     
    3549
    3650void kernel_start_preemption() {
    37 
     51        LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n");
     52        __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO );
     53        __kernel_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO );
     54}
     55
     56void kernel_stop_preemption() {
     57        //Block all signals, we are no longer in a position to handle them
     58        sigset_t mask;
     59        sigfillset( &mask );
     60        sigprocmask( SIG_BLOCK, &mask, NULL );
     61        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
    3862}
    3963
    4064void tick_preemption() {
     65        LIB_DEBUG_DO(
     66                char text[256];
     67                __attribute__((unused)) int len = snprintf( text, 256, "Ticking preemption\n" );
     68                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     69        );
     70
    4171        alarm_list_t * alarms = &systemProcessor->alarms;
    4272        __cfa_time_t currtime = __kernel_get_time();
    4373        while( alarms->head && alarms->head->alarm < currtime ) {
    4474                alarm_node_t * node = pop(alarms);
     75                LIB_DEBUG_DO(
     76                        len = snprintf( text, 256, "Ticking %p\n", node );
     77                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     78                );
    4579                if( node->kernel_alarm ) {
    4680                        preempt( node->proc );
     
    5185
    5286                if( node->period > 0 ) {
    53                         node->alarm += node->period;
     87                        node->alarm = currtime + node->period;
    5488                        insert( alarms, node );
    5589                }
     
    6296                __kernel_set_timer( alarms->head->alarm - currtime );
    6397        }
     98
     99        LIB_DEBUG_DO(
     100                len = snprintf( text, 256, "Ticking preemption done\n" );
     101                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     102        );
    64103}
    65104
    66105void update_preemption( processor * this, __cfa_time_t duration ) {
    67         //     assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 );
     106        LIB_DEBUG_DO(
     107                char text[256];
     108                __attribute__((unused)) int len = snprintf( text, 256, "Processor : updating preemption to %lu\n", duration );
     109                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     110        );
     111
    68112        alarm_node_t * alarm = this->preemption_alarm;
     113        duration *= 1000;
    69114
    70115        // Alarms need to be enabled
     
    94139        this->proc->preemption_alarm = &this->alarm;
    95140        update_preemption( this->proc, this->proc->preemption );
     141
     142        // enable_interrupts();
    96143}
    97144
    98145void ^?{}( preemption_scope * this ) {
     146        disable_interrupts();
     147
    99148        update_preemption( this->proc, 0 );
    100149}
     
    103152// Kernel Signal logic
    104153//=============================================================================================
     154
     155extern "C" {
     156        void disable_interrupts() {
     157                __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST );
     158                assert( prev != (unsigned short) -1 );
     159        }
     160
     161        void enable_interrupts_noRF() {
     162                unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     163                assert( prev != (unsigned short) 0 );
     164        }
     165
     166        void enable_interrupts() {
     167                unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     168                assert( prev != (unsigned short) 0 );
     169                if( prev == 1 && this_processor->pending_preemption ) {
     170                        this_processor->pending_preemption = false;
     171                        LIB_DEBUG_DO(
     172                                char text[256];
     173                                __attribute__((unused)) int len = snprintf( text, 256, "Executing deferred CtxSwitch\n" );
     174                                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     175                        );
     176                        BlockInternal( this_processor->current_thread );
     177                }
     178        }
     179}
     180
     181static inline void signal_unblock( bool alarm ) {
     182        sigset_t mask;
     183        sigemptyset( &mask );
     184        sigaddset( &mask, SIGUSR1 );
     185
     186        if( alarm ) sigaddset( &mask, SIGALRM );
     187
     188        if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
     189            abortf( "internal error, sigprocmask" );
     190        } // if
     191}
    105192
    106193static inline bool preemption_ready() {
     
    116203}
    117204
    118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) {
     205void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
     206
     207        LIB_DEBUG_DO(
     208                char text[256];
     209                __attribute__((unused)) int len = snprintf( text, 256, "Ctx Switch IRH\n" );
     210                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     211        );
     212
     213        signal_unblock( false );
    119214        if( preemption_ready() ) {
    120                 ScheduleInternal( this_processor->current_thread );
     215                LIB_DEBUG_DO(
     216                        len = snprintf( text, 256, "Ctx Switch IRH : Blocking thread\n" );
     217                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     218                );
     219                BlockInternal( this_processor->current_thread );
    121220        }
    122221        else {
     222                LIB_DEBUG_DO(
     223                        len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" );
     224                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     225                );
    123226                defer_ctxSwitch();
    124227        }
    125228}
    126229
    127 void sigHandler_alarm( __attribute__((unused)) int sig ) {
     230void sigHandler_alarm( __CFA_SIGPARMS__ ) {
     231
     232        LIB_DEBUG_DO(
     233                char text[256];
     234                __attribute__((unused)) int len = snprintf( text, 256, "\nAlarm IRH\n" );
     235                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     236        );
     237
     238        signal_unblock( true );
    128239        if( try_lock( &systemProcessor->alarm_lock ) ) {
    129240                tick_preemption();
     
    133244                defer_alarm();
    134245        }
     246
     247        if( preemption_ready() && this_processor->pending_preemption ) {
     248                LIB_DEBUG_DO(
     249                        len = snprintf( text, 256, "Alarm IRH : Blocking thread\n" );
     250                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     251                );
     252                this_processor->pending_preemption = false;
     253                BlockInternal( this_processor->current_thread );
     254        }
    135255}
    136256
    137257static void preempt( processor * this ) {
    138         pthread_kill( this->kernel_thread, SIGUSR1 );
     258        LIB_DEBUG_DO(
     259                char text[256];
     260                __attribute__((unused)) int len = snprintf( text, 256, "Processor : signalling %p\n", this );
     261                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     262        );
     263
     264        if( this != systemProcessor ) {
     265                pthread_kill( this->kernel_thread, SIGUSR1 );
     266        }
     267        else {
     268                defer_ctxSwitch();
     269        }
    139270}
    140271
     
    142273        //TODO : implement waking threads
    143274}
     275
     276static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
     277        struct sigaction act;
     278
     279        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     280        sigemptyset( &act.sa_mask );
     281        sigaddset( &act.sa_mask, SIGALRM );             // disabled during signal handler
     282        sigaddset( &act.sa_mask, SIGUSR1 );
     283
     284        act.sa_flags = flags;
     285
     286        if ( sigaction( sig, &act, NULL ) == -1 ) {
     287                // THE KERNEL IS NOT STARTED SO CALL NO uC++ ROUTINES!
     288                char helpText[256];
     289                __attribute__((unused)) int len = snprintf( helpText, 256, " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
     290                                sig, handler, flags, errno, strerror( errno ) );
     291                LIB_DEBUG_WRITE( STDERR_FILENO, helpText, len );
     292                _exit( EXIT_FAILURE );
     293        } // if
     294}
  • src/libcfa/concurrency/thread.c

    r8b8152e r82ff584  
    8484
    8585void yield( void ) {
    86         ScheduleInternal( this_processor->current_thread );
     86        BlockInternal( this_processor->current_thread );
    8787}
    8888
Note: See TracChangeset for help on using the changeset viewer.