Changes in / [9d85038:667c7da]


Ignore:
Location:
src/libcfa/concurrency
Files:
7 edited

Legend:

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

    r9d85038 r667c7da  
    1616
    1717extern "C" {
    18 #include <errno.h>
    19 #include <stdio.h>
    20 #include <string.h>
    2118#include <time.h>
    22 #include <unistd.h>
    2319#include <sys/time.h>
    2420}
     
    2622#include "alarm.h"
    2723#include "kernel_private.h"
    28 #include "libhdr.h"
    2924#include "preemption.h"
    3025
     
    3631        timespec curr;
    3732        clock_gettime( CLOCK_REALTIME, &curr );
    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;
     33        return ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
    4534}
    4635
    4736void __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 
    5537        itimerval val;
    5638        val.it_value.tv_sec = alarm / TIMEGRAN;                 // seconds
     
    146128        lock( &systemProcessor->alarm_lock );
    147129        {
    148                 bool first = !systemProcessor->alarms.head;
    149 
    150130                insert( &systemProcessor->alarms, this );
    151131                if( systemProcessor->pending_alarm ) {
    152132                        tick_preemption();
    153                 }
    154                 if( first ) {
    155                         __kernel_set_timer( systemProcessor->alarms.head->alarm - __kernel_get_time() );
    156133                }
    157134        }
  • src/libcfa/concurrency/invoke.c

    r9d85038 r667c7da  
    3030extern void __suspend_internal(void);
    3131extern void __leave_monitor_desc( struct monitor_desc * this );
    32 extern void disable_interrupts();
    33 extern void enable_interrupts();
    3432
    3533void CtxInvokeCoroutine(
     
    6967      struct monitor_desc* mon = &thrd->mon;
    7068      cor->state = Active;
    71       enable_interrupts();
    7269
    7370      // LIB_DEBUG_PRINTF("Invoke Thread : invoking main %p (args %p)\n", main, this);
    7471      main( this );
    7572
    76       disable_interrupts();
    7773      __leave_monitor_desc( mon );
    7874
  • src/libcfa/concurrency/kernel.c

    r9d85038 r667c7da  
    154154        (&this->terminated){};
    155155        this->is_terminated = false;
    156         this->preemption_alarm = NULL;
    157         this->preemption = default_preemption();
    158         this->disable_preempt_count = 1;
     156        this->disable_preempt_count = 0;
    159157        this->pending_preemption = false;
    160         this->kernel_thread = pthread_self();
    161158
    162159        this->runner = runner;
    163         LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
     160        LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
    164161        runner{ this };
    165162}
     
    243240        //Update global state
    244241        this->current_thread = dst;
    245 
    246         LIB_DEBUG_PRINT_SAFE("Kernel : running %p\n", dst);
    247242
    248243        // Context Switch to the thread
     
    327322void start(processor * this) {
    328323        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    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 
     324       
    350325        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
    358326
    359327        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
     
    379347}
    380348
    381 void BlockInternal() {
    382         disable_interrupts();
     349void ScheduleInternal() {
    383350        suspend();
    384         enable_interrupts();
    385 }
    386 
    387 void BlockInternal( spinlock * lock ) {
    388         disable_interrupts();
     351}
     352
     353void ScheduleInternal( spinlock * lock ) {
    389354        this_processor->finish.action_code = Release;
    390355        this_processor->finish.lock = lock;
    391356        suspend();
    392         enable_interrupts();
    393 }
    394 
    395 void BlockInternal( thread_desc * thrd ) {
    396         disable_interrupts();
     357}
     358
     359void ScheduleInternal( thread_desc * thrd ) {
    397360        this_processor->finish.action_code = Schedule;
    398361        this_processor->finish.thrd = thrd;
    399362        suspend();
    400         enable_interrupts();
    401 }
    402 
    403 void BlockInternal( spinlock * lock, thread_desc * thrd ) {
    404         disable_interrupts();
     363}
     364
     365void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
    405366        this_processor->finish.action_code = Release_Schedule;
    406367        this_processor->finish.lock = lock;
    407368        this_processor->finish.thrd = thrd;
    408369        suspend();
    409         enable_interrupts();
    410 }
    411 
    412 void BlockInternal(spinlock ** locks, unsigned short count) {
    413         disable_interrupts();
     370}
     371
     372void ScheduleInternal(spinlock ** locks, unsigned short count) {
    414373        this_processor->finish.action_code = Release_Multi;
    415374        this_processor->finish.locks = locks;
    416375        this_processor->finish.lock_count = count;
    417376        suspend();
    418         enable_interrupts();
    419 }
    420 
    421 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    422         disable_interrupts();
     377}
     378
     379void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    423380        this_processor->finish.action_code = Release_Multi_Schedule;
    424381        this_processor->finish.locks = locks;
     
    427384        this_processor->finish.thrd_count = thrd_count;
    428385        suspend();
    429         enable_interrupts();
    430386}
    431387
     
    447403        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    448404
     405        // Enable preemption
     406        kernel_start_preemption();
     407
    449408        // Initialize the system cluster
    450409        systemCluster = (cluster *)&systemCluster_storage;
     
    467426        this_processor->current_coroutine = &mainThread->cor;
    468427
    469         // Enable preemption
    470         kernel_start_preemption();
    471 
    472428        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    473429        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
     
    479435        // THE SYSTEM IS NOW COMPLETELY RUNNING
    480436        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
    481 
    482         enable_interrupts();
    483437}
    484438
     
    493447
    494448        // THE SYSTEM IS NOW COMPLETELY STOPPED
    495 
    496         // Disable preemption
    497         kernel_stop_preemption();
    498449
    499450        // Destroy the system processor and its context in reverse order of construction
     
    599550        if( !this->cond ) {
    600551                append( &this->blocked, this_thread() );
    601                 BlockInternal( &this->lock );
     552                ScheduleInternal( &this->lock );
    602553                lock( &this->lock );
    603554        }
  • src/libcfa/concurrency/kernel_private.h

    r9d85038 r667c7da  
    2828thread_desc * nextThread(cluster * this);
    2929
    30 void BlockInternal(void);
    31 void BlockInternal(spinlock * lock);
    32 void BlockInternal(thread_desc * thrd);
    33 void BlockInternal(spinlock * lock, thread_desc * thrd);
    34 void BlockInternal(spinlock ** locks, unsigned short count);
    35 void BlockInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);
     30void ScheduleInternal(void);
     31void ScheduleInternal(spinlock * lock);
     32void ScheduleInternal(thread_desc * thrd);
     33void ScheduleInternal(spinlock * lock, thread_desc * thrd);
     34void ScheduleInternal(spinlock ** locks, unsigned short count);
     35void ScheduleInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);
    3636
    3737//-----------------------------------------------------------------------------
     
    6060extern thread_local processor * this_processor;
    6161
    62 extern "C" {
    63         void disable_interrupts();
    64         void enable_interrupts_noRF();
    65         void enable_interrupts();
     62static 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
     67static 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
     72static 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        }
    6679}
    6780
  • src/libcfa/concurrency/monitor.c

    r9d85038 r667c7da  
    6363                        append( &this->entry_queue, thrd );
    6464                        LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);
    65                         BlockInternal( &this->lock );
    66 
    67                         //BlockInternal will unlock spinlock, no need to unlock ourselves
     65                        ScheduleInternal( &this->lock );
     66
     67                        //ScheduleInternal 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 BlockInternal
     174        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
    175175
    176176        LIB_DEBUG_PRINT_SAFE("count %i\n", count);
     
    210210
    211211        // Everything is ready to go to sleep
    212         BlockInternal( locks, count, threads, thread_count );
     212        ScheduleInternal( 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 BlockInternal
     285        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
    286286
    287287        lock_all( this->monitors, locks, count );
     
    311311
    312312        //Everything is ready to go to sleep
    313         BlockInternal( locks, count, &signallee, 1 );
     313        ScheduleInternal( 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 BlockInternal
     345        // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to ScheduleInternal
    346346
    347347        // lock_all( this->current_monitors, locks, count );
     
    352352
    353353        // // // Everything is ready to go to sleep
    354         // // BlockInternal( locks, count, threads, thread_count );
     354        // // ScheduleInternal( locks, count, threads, thread_count );
    355355
    356356
  • src/libcfa/concurrency/preemption.c

    r9d85038 r667c7da  
    1818
    1919extern "C" {
    20 #include <errno.h>
    2120#include <signal.h>
    22 #include <stdio.h>
    23 #include <string.h>
    24 #include <unistd.h>
    2521}
    2622
    27 #include "libhdr.h"
    28 
    29 #define __CFA_DEFAULT_PREEMPTION__ 10000
     23#define __CFA_DEFAULT_PREEMPTION__ 10
    3024
    3125__attribute__((weak)) unsigned int default_preemption() {
     
    3327}
    3428
    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 
    3829static void preempt( processor   * this );
    3930static void timeout( thread_desc * this );
    40 
    41 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
    42 void sigHandler_alarm    ( __CFA_SIGPARMS__ );
    43 
    44 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
    4531
    4632//=============================================================================================
     
    4935
    5036void kernel_start_preemption() {
    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 }
    5537
    56 void 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");
    6238}
    6339
    6440void 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 
    7141        alarm_list_t * alarms = &systemProcessor->alarms;
    7242        __cfa_time_t currtime = __kernel_get_time();
    7343        while( alarms->head && alarms->head->alarm < currtime ) {
    7444                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                 );
    7945                if( node->kernel_alarm ) {
    8046                        preempt( node->proc );
     
    8551
    8652                if( node->period > 0 ) {
    87                         node->alarm = currtime + node->period;
     53                        node->alarm += node->period;
    8854                        insert( alarms, node );
    8955                }
     
    9662                __kernel_set_timer( alarms->head->alarm - currtime );
    9763        }
    98 
    99         LIB_DEBUG_DO(
    100                 len = snprintf( text, 256, "Ticking preemption done\n" );
    101                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    102         );
    10364}
    10465
    10566void update_preemption( processor * this, __cfa_time_t duration ) {
    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 
     67        //     assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 );
    11268        alarm_node_t * alarm = this->preemption_alarm;
    113         duration *= 1000;
    11469
    11570        // Alarms need to be enabled
     
    13994        this->proc->preemption_alarm = &this->alarm;
    14095        update_preemption( this->proc, this->proc->preemption );
    141 
    142         // enable_interrupts();
    14396}
    14497
    14598void ^?{}( preemption_scope * this ) {
    146         disable_interrupts();
    147 
    14899        update_preemption( this->proc, 0 );
    149100}
     
    152103// Kernel Signal logic
    153104//=============================================================================================
    154 
    155 extern "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 
    181 static 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 }
    192105
    193106static inline bool preemption_ready() {
     
    203116}
    204117
    205 void 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 );
     118void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) {
    214119        if( preemption_ready() ) {
    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 );
     120                ScheduleInternal( this_processor->current_thread );
    220121        }
    221122        else {
    222                 LIB_DEBUG_DO(
    223                         len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" );
    224                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    225                 );
    226123                defer_ctxSwitch();
    227124        }
    228125}
    229126
    230 void 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 );
     127void sigHandler_alarm( __attribute__((unused)) int sig ) {
    239128        if( try_lock( &systemProcessor->alarm_lock ) ) {
    240129                tick_preemption();
     
    244133                defer_alarm();
    245134        }
    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         }
    255135}
    256136
    257137static void preempt( processor * this ) {
    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         }
     138        pthread_kill( this->kernel_thread, SIGUSR1 );
    270139}
    271140
     
    273142        //TODO : implement waking threads
    274143}
    275 
    276 static 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

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