Ignore:
File:
1 edited

Legend:

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

    r381fdee rb69ea6b  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  9 14:42:34 2018
    13 // Update Count     : 25
     12// Last Modified On : Fri Feb  9 16:38:13 2018
     13// Update Count     : 14
    1414//
    1515
     
    6767}
    6868
     69enum {
     70        PREEMPT_NORMAL    = 0,
     71        PREEMPT_TERMINATE = 1,
     72};
     73
    6974//=============================================================================================
    7075// Kernel Preemption logic
     
    144149        // Disable interrupts by incrementing the counter
    145150        void disable_interrupts() {
    146                 preemption_enabled = false;
    147                 __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1;
    148                 disable_preempt_count = new_val;
     151                preemption.enabled = false;
     152                __attribute__((unused)) unsigned short new_val = preemption.disable_count + 1;
     153                preemption.disable_count = new_val;
    149154                verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    150155        }
     
    156161                thread_desc * thrd = this_thread;         // Cache the thread now since interrupts can start happening after the atomic add
    157162
    158                 unsigned short prev = disable_preempt_count;
    159                 disable_preempt_count -= 1;
     163                unsigned short prev = preemption.disable_count;
     164                preemption.disable_count -= 1;
    160165                verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
    161166
    162167                // Check if we need to prempt the thread because an interrupt was missed
    163168                if( prev == 1 ) {
    164                         preemption_enabled = true;
     169                        preemption.enabled = true;
    165170                        if( proc->pending_preemption ) {
    166171                                proc->pending_preemption = false;
     
    176181        // Don't execute any pending CtxSwitch even if counter reaches 0
    177182        void enable_interrupts_noPoll() {
    178                 unsigned short prev = disable_preempt_count;
    179                 disable_preempt_count -= 1;
     183                unsigned short prev = preemption.disable_count;
     184                preemption.disable_count -= 1;
    180185                verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    181186                if( prev == 1 ) {
    182                         preemption_enabled = true;
     187                        preemption.enabled = true;
    183188                }
    184189        }
     
    192197
    193198        if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
    194             abortf( "internal error, pthread_sigmask" );
     199            abort( "internal error, pthread_sigmask" );
    195200        }
    196201}
     
    203208
    204209        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
    205             abortf( "internal error, pthread_sigmask" );
     210            abort( "internal error, pthread_sigmask" );
    206211        }
    207212}
     
    209214// kill wrapper : signal a processor
    210215static void preempt( processor * this ) {
    211         pthread_kill( this->kernel_thread, SIGUSR1 );
     216        sigval_t value = { PREEMPT_NORMAL };
     217        pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
     218}
     219
     220// kill wrapper : signal a processor
     221void terminate(processor * this) {
     222        this->do_terminate = true;
     223        sigval_t value = { PREEMPT_TERMINATE };
     224        pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    212225}
    213226
     
    222235// If false : preemption is unsafe and marked as pending
    223236static inline bool preemption_ready() {
    224         bool ready = preemption_enabled && !preemption_in_progress; // Check if preemption is safe
     237        bool ready = preemption.enabled && !preemption.in_progress; // Check if preemption is safe
    225238        this_processor->pending_preemption = !ready;                        // Adjust the pending flag accordingly
    226239        return ready;
     
    234247// Called from kernel_startup
    235248void kernel_start_preemption() {
    236         __cfaabi_dbg_print_safe("Kernel : Starting preemption\n");
     249        __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n" );
    237250
    238251        // Start with preemption disabled until ready
    239         preemption_enabled = false;
    240         disable_preempt_count = 1;
     252        preemption.enabled = false;
     253        preemption.disable_count = 1;
    241254
    242255        // Initialize the event kernel
     
    255268// Called from kernel_shutdown
    256269void kernel_stop_preemption() {
    257         __cfaabi_dbg_print_safe("Kernel : Preemption stopping\n");
     270        __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n" );
    258271
    259272        // Block all signals since we are already shutting down
     
    271284        // Preemption is now fully stopped
    272285
    273         __cfaabi_dbg_print_safe("Kernel : Preemption stopped\n");
     286        __cfaabi_dbg_print_safe( "Kernel : Preemption stopped\n" );
    274287}
    275288
     
    277290// Used by thread to control when they want to receive preemption signals
    278291void ?{}( preemption_scope & this, processor * proc ) {
    279         (this.alarm){ proc, zero_time, zero_time };
     292        (this.alarm){ proc, 0`cfa_s, 0`cfa_s };
    280293        this.proc = proc;
    281294        this.proc->preemption_alarm = &this.alarm;
     
    287300        disable_interrupts();
    288301
    289         update_preemption( this.proc, zero_time );
     302        update_preemption( this.proc, 0`cfa_s );
    290303}
    291304
     
    299312        __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.CFA_REG_IP); )
    300313
     314        // SKULLDUGGERY: if a thread creates a processor and the immediately deletes it,
     315        // the interrupt that is supposed to force the kernel thread to preempt might arrive
     316        // before the kernel thread has even started running. When that happens an iterrupt
     317        // we a null 'this_processor' will be caught, just ignore it.
     318        if(!this_processor) return;
     319
     320        choose(sfp->si_value.sival_int) {
     321                case PREEMPT_NORMAL   : ;// Normal case, nothing to do here
     322                case PREEMPT_TERMINATE: verify(this_processor->do_terminate);
     323                default:
     324                        abort( "internal error, signal value is %d", sfp->si_value.sival_int );
     325        }
     326
    301327        // Check if it is safe to preempt here
    302328        if( !preemption_ready() ) { return; }
    303329
    304         __cfaabi_dbg_print_buffer_decl(" KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
    305 
    306         preemption_in_progress = true;                      // Sync flag : prevent recursive calls to the signal handler
     330        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
     331
     332        preemption.in_progress = true;                      // Sync flag : prevent recursive calls to the signal handler
    307333        signal_unblock( SIGUSR1 );                          // We are about to CtxSwitch out of the signal handler, let other handlers in
    308         preemption_in_progress = false;                     // Clear the in progress flag
     334        preemption.in_progress = false;                     // Clear the in progress flag
    309335
    310336        // Preemption can occur here
     
    322348
    323349        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
    324             abortf( "internal error, pthread_sigmask" );
     350            abort( "internal error, pthread_sigmask" );
    325351        }
    326352
     
    339365                                        continue;
    340366                        case EINVAL :
    341                                         abortf("Timeout was invalid.");
     367                                        abort( "Timeout was invalid." );
    342368                                default:
    343                                         abortf("Unhandled error %d", err);
     369                                        abort( "Unhandled error %d", err);
    344370                        }
    345371                }
     
    348374                assertf(sig == SIGALRM, "Kernel Internal Error, sigwait: Unexpected signal %d (%d : %d)\n", sig, info.si_code, info.si_value.sival_int);
    349375
    350                 // __cfaabi_dbg_print_safe("Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );
     376                // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );
    351377                // Switch on the code (a.k.a. the sender) to
    352378                switch( info.si_code )
     
    356382                case SI_TIMER:
    357383                case SI_KERNEL:
    358                         // __cfaabi_dbg_print_safe("Kernel : Preemption thread tick\n");
     384                        // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" );
    359385                        lock( event_kernel->lock __cfaabi_dbg_ctx2 );
    360386                        tick_preemption();
     
    370396
    371397EXIT:
    372         __cfaabi_dbg_print_safe("Kernel : Preemption thread stopping\n");
     398        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
    373399        return NULL;
    374400}
Note: See TracChangeset for help on using the changeset viewer.