Ignore:
Timestamp:
Jul 4, 2017, 4:48:46 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
11dbfe1
Parents:
47ecf2b
Message:

Preemption now uses an oracle kernel thread

Location:
src/libcfa/concurrency
Files:
2 edited

Legend:

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

    r47ecf2b rcd17862  
    324324        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    325325
    326         // SIGALRM must only be caught by the system processor
    327         sigset_t old_mask;
    328         bool is_system_proc = this_processor == &systemProcessor->proc;
    329         if ( is_system_proc ) {
    330                 // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the
    331                 // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user
    332                 // processor, and toggle back (below) previous signal mask of the system processor.
    333 
    334                 sigset_t new_mask;
    335                 sigemptyset( &new_mask );
    336                 sigemptyset( &old_mask );
    337                 sigaddset( &new_mask, SIGALRM );
    338 
    339                 if ( pthread_sigmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) {
    340                         abortf( "internal error, pthread_sigmask" );
    341                 }
    342 
    343                 assert( ! sigismember( &old_mask, SIGALRM ) );
    344         }
    345 
    346326        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    347 
    348         // Toggle back previous signal mask of system processor.
    349         if ( is_system_proc ) {
    350                 if ( pthread_sigmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) {
    351                         abortf( "internal error, pthread_sigmask" );
    352                 } // if
    353         } // if
    354327
    355328        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);
  • src/libcfa/concurrency/preemption.c

    r47ecf2b rcd17862  
    5252
    5353static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
     54LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
     55
     56#ifdef __x86_64__
     57#define CFA_REG_IP REG_RIP
     58#else
     59#define CFA_REG_IP REG_EIP
     60#endif
     61
    5462
    5563//=============================================================================================
    5664// Kernel Preemption logic
    5765//=============================================================================================
    58 
    59 void kernel_start_preemption() {
    60         LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n");
    61         __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO );
    62         __kernel_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO );
    63         __kernel_sigaction( SIGSEGV, sigHandler_segv     , SA_SIGINFO );
    64         __kernel_sigaction( SIGBUS , sigHandler_segv     , SA_SIGINFO );
    65         // __kernel_sigaction( SIGABRT, sigHandler_abort    , SA_SIGINFO );
    66 }
    67 
    68 void kernel_stop_preemption() {
    69         //Block all signals, we are no longer in a position to handle them
    70         sigset_t mask;
    71         sigfillset( &mask );
    72         sigprocmask( SIG_BLOCK, &mask, NULL );
    73         LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
    74 
    75         // assert( !systemProcessor->alarms.head );
    76         // assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head );
    77 }
    78 
    79 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    8066
    8167void tick_preemption() {
     
    141127}
    142128
    143 void ?{}( preemption_scope * this, processor * proc ) {
    144         (&this->alarm){ proc };
    145         this->proc = proc;
    146         this->proc->preemption_alarm = &this->alarm;
    147         update_preemption( this->proc, this->proc->preemption );
    148 }
    149 
    150 void ^?{}( preemption_scope * this ) {
    151         disable_interrupts();
    152 
    153         update_preemption( this->proc, 0 );
    154 }
    155 
    156 //=============================================================================================
    157 // Kernel Signal logic
     129//=============================================================================================
     130// Kernel Signal Tools
    158131//=============================================================================================
    159132
     
    187160
    188161static inline void signal_unblock( int sig ) {
    189         LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Unblock %d on %p\n", sig, this_processor );
    190 
    191162        sigset_t mask;
    192163        sigemptyset( &mask );
     
    195166        if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
    196167            abortf( "internal error, pthread_sigmask" );
    197         } // if
    198 }
    199 
    200 // static inline void signal_block( int sig ) {
    201 //      sigset_t mask;
    202 //      sigemptyset( &mask );
    203 //      sigaddset( &mask, sig );
    204 
    205 //      if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
    206 //          abortf( "internal error, pthread_sigmask" );
    207 //      } // if
    208 // }
     168        }
     169}
     170
     171static inline void signal_block( int sig ) {
     172        sigset_t mask;
     173        sigemptyset( &mask );
     174        sigaddset( &mask, sig );
     175
     176        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     177            abortf( "internal error, pthread_sigmask" );
     178        }
     179}
    209180
    210181static inline bool preemption_ready() {
     
    220191}
    221192
    222 extern "C" {
    223         __attribute__((noinline)) void __debug_break() {
    224                 pthread_kill( pthread_self(), SIGTRAP );
    225         }
    226 }
    227 
    228 #ifdef __x86_64__
    229 #define CFA_REG_IP REG_RIP
    230 #else
    231 #define CFA_REG_IP REG_EIP
    232 #endif
     193static void preempt( processor * this ) {
     194        pthread_kill( this->kernel_thread, SIGUSR1 );
     195}
     196
     197static void timeout( thread_desc * this ) {
     198        //TODO : implement waking threads
     199}
     200
     201//=============================================================================================
     202// Kernel Signal Startup/Shutdown logic
     203//=============================================================================================
     204
     205static pthread_t alarm_thread;
     206void * alarm_loop( __attribute__((unused)) void * args );
     207
     208void kernel_start_preemption() {
     209        LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n");
     210        __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO );
     211        __kernel_sigaction( SIGSEGV, sigHandler_segv     , SA_SIGINFO );
     212        __kernel_sigaction( SIGBUS , sigHandler_segv     , SA_SIGINFO );
     213
     214        signal_block( SIGALRM );
     215
     216        pthread_create( &alarm_thread, NULL, alarm_loop, NULL );
     217}
     218
     219void kernel_stop_preemption() {
     220        sigset_t mask;
     221        sigfillset( &mask );
     222        sigprocmask( SIG_BLOCK, &mask, NULL );
     223
     224        pthread_kill( alarm_thread, SIGINT );
     225        pthread_join( alarm_thread, NULL );
     226        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
     227}
     228
     229void ?{}( preemption_scope * this, processor * proc ) {
     230        (&this->alarm){ proc };
     231        this->proc = proc;
     232        this->proc->preemption_alarm = &this->alarm;
     233        update_preemption( this->proc, this->proc->preemption );
     234}
     235
     236void ^?{}( preemption_scope * this ) {
     237        disable_interrupts();
     238
     239        update_preemption( this->proc, 0 );
     240}
     241
     242//=============================================================================================
     243// Kernel Signal Handlers
     244//=============================================================================================
    233245
    234246void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    235247        LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
    236         verify( this_processor != systemProcessor );
    237 
    238248        if( preemption_ready() ) {
    239249                signal_unblock( SIGUSR1 );
     
    245255}
    246256
    247 void sigHandler_alarm( __CFA_SIGPARMS__ ) {
    248         LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
    249         verify( this_processor == systemProcessor );
    250 
    251         if( try_lock( &systemProcessor->alarm_lock DEBUG_CTX2 ) ) {
    252                 tick_preemption();
    253                 systemProcessor->pending_alarm = false;
    254                 unlock( &systemProcessor->alarm_lock );
    255         }
    256         else {
    257                 defer_alarm();
    258         }
    259 
    260         signal_unblock( SIGALRM );
    261 
    262         if( preemption_ready() && this_processor->pending_preemption ) {
    263 
    264                 this_processor->pending_preemption = false;
    265                 BlockInternal( (thread_desc*)this_thread );
    266         }
    267 }
    268 
    269 static void preempt( processor * this ) {
    270         if( this != systemProcessor ) {
    271                 pthread_kill( this->kernel_thread, SIGUSR1 );
    272         }
    273         else {
    274                 defer_ctxSwitch();
    275         }
    276 }
    277 
    278 static void timeout( thread_desc * this ) {
    279         //TODO : implement waking threads
     257// void sigHandler_alarm( __CFA_SIGPARMS__ ) {
     258//      LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
     259//      verify( this_processor == systemProcessor );
     260
     261//      if( try_lock( &systemProcessor->alarm_lock DEBUG_CTX2 ) ) {
     262//              tick_preemption();
     263//              systemProcessor->pending_alarm = false;
     264//              unlock( &systemProcessor->alarm_lock );
     265//      }
     266//      else {
     267//              defer_alarm();
     268//      }
     269
     270//      signal_unblock( SIGALRM );
     271
     272//      if( preemption_ready() && this_processor->pending_preemption ) {
     273
     274//              this_processor->pending_preemption = false;
     275//              BlockInternal( (thread_desc*)this_thread );
     276//      }
     277// }
     278
     279void * alarm_loop( __attribute__((unused)) void * args ) {
     280        sigset_t mask;
     281        sigemptyset( &mask );
     282        sigaddset( &mask, SIGALRM );
     283        sigaddset( &mask, SIGUSR2 );
     284        sigaddset( &mask, SIGINT  );
     285
     286        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     287            abortf( "internal error, pthread_sigmask" );
     288        }
     289
     290        while( true ) {
     291                int sig;
     292                if( sigwait( &mask, &sig ) != 0  ) {
     293                        abortf( "internal error, sigwait" );
     294                }
     295
     296                switch( sig) {
     297                        case SIGALRM:
     298                                LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread tick\n");
     299                                lock( &systemProcessor->alarm_lock DEBUG_CTX2 );
     300                                tick_preemption();
     301                                unlock( &systemProcessor->alarm_lock );
     302                                break;
     303                        case SIGUSR2:
     304                                //TODO other actions
     305                                break;
     306                        case SIGINT:
     307                                LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread stopping\n");
     308                                return NULL;
     309                        default:
     310                                abortf( "internal error, sigwait returned sig %d", sig );
     311                                break;
     312                }
     313        }
    280314}
    281315
Note: See TracChangeset for help on using the changeset viewer.