Ignore:
File:
1 edited

Legend:

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

    r0b33412 rc5ac6d5  
    1717#include "preemption.h"
    1818
    19 
    2019extern "C" {
    21 #include <errno.h>
    22 #define __USE_GNU
    2320#include <signal.h>
    24 #undef __USE_GNU
    25 #include <stdio.h>
    26 #include <string.h>
    27 #include <unistd.h>
    2821}
    2922
    30 #include "libhdr.h"
    31 
    32 #define __CFA_DEFAULT_PREEMPTION__ 10000
     23#define __CFA_DEFAULT_PREEMPTION__ 10
    3324
    3425__attribute__((weak)) unsigned int default_preemption() {
     
    3627}
    3728
    38 #define __CFA_SIGCXT__ ucontext_t *
    39 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt
    40 
    4129static void preempt( processor   * this );
    4230static void timeout( thread_desc * this );
    43 
    44 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
    45 void sigHandler_alarm    ( __CFA_SIGPARMS__ );
    46 
    47 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
    4831
    4932//=============================================================================================
     
    5235
    5336void kernel_start_preemption() {
    54         LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n");
    55         __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO );
    56         __kernel_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO );
     37
    5738}
    5839
    59 void kernel_stop_preemption() {
    60         //Block all signals, we are no longer in a position to handle them
    61         sigset_t mask;
    62         sigfillset( &mask );
    63         sigprocmask( SIG_BLOCK, &mask, NULL );
    64         LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
    65 
    66         assert( !systemProcessor->alarms.head );
    67         assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head );
    68 }
    69 
    70 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    71 
    7240void tick_preemption() {
    73         LIB_DEBUG_DO(
    74                 char text[256];
    75                 __attribute__((unused)) int len = snprintf( text, 256, "Ticking preemption\n" );
    76                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    77         );
    78 
    7941        alarm_list_t * alarms = &systemProcessor->alarms;
    8042        __cfa_time_t currtime = __kernel_get_time();
    8143        while( alarms->head && alarms->head->alarm < currtime ) {
    8244                alarm_node_t * node = pop(alarms);
    83                 LIB_DEBUG_DO(
    84                         len = snprintf( text, 256, "Ticking %p\n", node );
    85                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    86                 );
    8745                if( node->kernel_alarm ) {
    8846                        preempt( node->proc );
     
    9250                }
    9351
    94                 LIB_DEBUG_DO( assert( validate( alarms ) ) );
    95 
    9652                if( node->period > 0 ) {
    97                         node->alarm = currtime + node->period;
     53                        node->alarm += node->period;
    9854                        insert( alarms, node );
    9955                }
     
    10662                __kernel_set_timer( alarms->head->alarm - currtime );
    10763        }
    108 
    109         verify( validate( alarms ) );
    110         LIB_DEBUG_DO(
    111                 len = snprintf( text, 256, "Ticking preemption done\n" );
    112                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    113         );
    11464}
    11565
    11666void update_preemption( processor * this, __cfa_time_t duration ) {
    117         LIB_DEBUG_DO(
    118                 char text[256];
    119                 __attribute__((unused)) int len = snprintf( text, 256, "Processor : %p updating preemption to %lu\n", this, duration );
    120                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    121         );
    122 
     67        //     assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 );
    12368        alarm_node_t * alarm = this->preemption_alarm;
    124         duration *= 1000;
    12569
    12670        // Alarms need to be enabled
     
    15397
    15498void ^?{}( preemption_scope * this ) {
    155         disable_interrupts();
    156 
    15799        update_preemption( this->proc, 0 );
    158100}
     
    162104//=============================================================================================
    163105
    164 extern "C" {
    165         void disable_interrupts() {
    166                 __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST );
    167                 verify( new_val < (unsigned short)65_000 );
    168                 verify( new_val != (unsigned short) 0 );
    169         }
    170 
    171         void enable_interrupts_noRF() {
    172                 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    173                 verify( prev != (unsigned short) 0 );
    174         }
    175 
    176         void enable_interrupts( const char * func ) {
    177                 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    178                 verify( prev != (unsigned short) 0 );
    179                 if( prev == 1 && this_processor->pending_preemption ) {
    180                         this_processor->pending_preemption = false;
    181                         LIB_DEBUG_DO(
    182                                 char text[256];
    183                                 __attribute__((unused)) int len = snprintf( text, 256, "Executing deferred CtxSwitch on %p\n", this_processor );
    184                                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    185                         );
    186                         BlockInternal( this_processor->current_thread );
    187                 }
    188 
    189                 this_processor->last_enable = func;
    190         }
    191 }
    192 
    193 static inline void signal_unblock( bool alarm ) {
    194         sigset_t mask;
    195         sigemptyset( &mask );
    196         sigaddset( &mask, SIGUSR1 );
    197 
    198         if( alarm ) sigaddset( &mask, SIGALRM );
    199 
    200         if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
    201             abortf( "internal error, sigprocmask" );
    202         } // if
    203 }
    204 
    205106static inline bool preemption_ready() {
    206         return disable_preempt_count == 0;
     107        return this_processor->disable_preempt_count == 0;
    207108}
    208109
     
    215116}
    216117
    217 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    218 
    219         LIB_DEBUG_DO(
    220                 char text[256];
    221                 __attribute__((unused)) int len = snprintf( text, 256, "Ctx Switch IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP]));
    222                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    223         );
    224 
    225         signal_unblock( false );
     118void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) {
    226119        if( preemption_ready() ) {
    227                 LIB_DEBUG_DO(
    228                         len = snprintf( text, 256, "Ctx Switch IRH : Blocking thread %p on %p\n", this_processor->current_thread, this_processor );
    229                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    230                 );
    231                 BlockInternal( this_processor->current_thread );
     120                ScheduleInternal( this_processor->current_thread );
    232121        }
    233122        else {
    234                 LIB_DEBUG_DO(
    235                         len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" );
    236                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    237                 );
    238123                defer_ctxSwitch();
    239124        }
    240125}
    241126
    242 void sigHandler_alarm( __CFA_SIGPARMS__ ) {
    243 
    244         LIB_DEBUG_DO(
    245                 char text[256];
    246                 __attribute__((unused)) int len = snprintf( text, 256, "\nAlarm IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP]) );
    247                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    248         );
    249 
    250         signal_unblock( true );
     127void sigHandler_alarm( __attribute__((unused)) int sig ) {
    251128        if( try_lock( &systemProcessor->alarm_lock ) ) {
    252129                tick_preemption();
     
    256133                defer_alarm();
    257134        }
    258 
    259         if( preemption_ready() && this_processor->pending_preemption ) {
    260                 LIB_DEBUG_DO(
    261                         len = snprintf( text, 256, "Alarm IRH : Blocking thread\n" );
    262                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    263                 );
    264                 this_processor->pending_preemption = false;
    265                 BlockInternal( this_processor->current_thread );
    266         }
    267135}
    268136
    269137static void preempt( processor * this ) {
    270         LIB_DEBUG_DO(
    271                 char text[256];
    272                 __attribute__((unused)) int len = snprintf( text, 256, "Processor : signalling %p\n", this );
    273                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    274         );
    275 
    276         if( this != systemProcessor ) {
    277                 pthread_kill( this->kernel_thread, SIGUSR1 );
    278         }
    279         else {
    280                 defer_ctxSwitch();
    281         }
     138        pthread_kill( this->kernel_thread, SIGUSR1 );
    282139}
    283140
     
    285142        //TODO : implement waking threads
    286143}
    287 
    288 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
    289         struct sigaction act;
    290 
    291         act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
    292         sigemptyset( &act.sa_mask );
    293         sigaddset( &act.sa_mask, SIGALRM );             // disabled during signal handler
    294         sigaddset( &act.sa_mask, SIGUSR1 );
    295 
    296         act.sa_flags = flags;
    297 
    298         if ( sigaction( sig, &act, NULL ) == -1 ) {
    299                 // THE KERNEL IS NOT STARTED SO CALL NO uC++ ROUTINES!
    300                 char helpText[256];
    301                 __attribute__((unused)) int len = snprintf( helpText, 256, " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
    302                                 sig, handler, flags, errno, strerror( errno ) );
    303                 LIB_DEBUG_WRITE( STDERR_FILENO, helpText, len );
    304                 _exit( EXIT_FAILURE );
    305         } // if
    306 }
Note: See TracChangeset for help on using the changeset viewer.