Ignore:
File:
1 edited

Legend:

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

    rd0a045c7 r65deb18  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jan 23 17:59:30 2018
    13 // Update Count     : 7
     12// Last Modified On : Fri Jul 21 22:36:05 2017
     13// Update Count     : 2
    1414//
    1515
    1616#include "preemption.h"
    1717
    18 #define ftype `ftype`
    1918extern "C" {
    2019#include <errno.h>
     20#include <execinfo.h>
     21#define __USE_GNU
     22#include <signal.h>
     23#undef __USE_GNU
    2124#include <stdio.h>
    2225#include <string.h>
    2326#include <unistd.h>
    2427}
    25 #undef ftype
    26 
    27 #include "bits/signal.h"
     28
     29
     30#ifdef __USE_STREAM__
     31#include "fstream"
     32#endif
    2833
    2934//TODO move to defaults
     
    3439        return __CFA_DEFAULT_PREEMPTION__;
    3540}
     41
     42// Short hands for signal context information
     43#define __CFA_SIGCXT__ ucontext_t *
     44#define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt
    3645
    3746// FwdDeclarations : timeout handlers
     
    4453void sigHandler_abort    ( __CFA_SIGPARMS__ );
    4554
     55// FwdDeclarations : sigaction wrapper
     56static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
     57
    4658// FwdDeclarations : alarm thread main
    4759void * alarm_loop( __attribute__((unused)) void * args );
    4860
    4961// Machine specific register name
    50 #if   defined(__x86_64__)
    51 #define CFA_REG_IP gregs[REG_RIP]
    52 #elif defined(__i386__)
    53 #define CFA_REG_IP gregs[REG_EIP]
    54 #elif defined(__ARM_ARCH__)
    55 #define CFA_REG_IP arm_pc
     62#ifdef __x86_64__
     63#define CFA_REG_IP REG_RIP
     64#else
     65#define CFA_REG_IP REG_EIP
    5666#endif
    5767
     
    142152        // Disable interrupts by incrementing the counter
    143153        void disable_interrupts() {
    144                 preemption_enabled = false;
    145                 __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1;
    146                 disable_preempt_count = new_val;
     154                __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST );
    147155                verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    148156        }
     
    154162                thread_desc * thrd = this_thread;         // Cache the thread now since interrupts can start happening after the atomic add
    155163
    156                 unsigned short prev = disable_preempt_count;
    157                 disable_preempt_count -= 1;
     164                unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    158165                verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
    159166
    160167                // Check if we need to prempt the thread because an interrupt was missed
    161                 if( prev == 1 ) {
    162                         preemption_enabled = true;
    163                         if( proc->pending_preemption ) {
    164                                 proc->pending_preemption = false;
    165                                 BlockInternal( thrd );
    166                         }
     168                if( prev == 1 && proc->pending_preemption ) {
     169                        proc->pending_preemption = false;
     170                        BlockInternal( thrd );
    167171                }
    168172
     
    174178        // Don't execute any pending CtxSwitch even if counter reaches 0
    175179        void enable_interrupts_noPoll() {
    176                 unsigned short prev = disable_preempt_count;
    177                 disable_preempt_count -= 1;
    178                 verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    179                 if( prev == 1 ) {
    180                         preemption_enabled = true;
    181                 }
     180                __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     181                verify( prev != 0u );                     // If this triggers someone is enabled already enabled interrupts
    182182        }
    183183}
     
    220220// If false : preemption is unsafe and marked as pending
    221221static inline bool preemption_ready() {
    222         bool ready = preemption_enabled && !preemption_in_progress; // Check if preemption is safe
     222        bool ready = disable_preempt_count == 0 && !preemption_in_progress; // Check if preemption is safe
    223223        this_processor->pending_preemption = !ready;                        // Adjust the pending flag accordingly
    224224        return ready;
     
    235235
    236236        // Start with preemption disabled until ready
    237         preemption_enabled = false;
    238237        disable_preempt_count = 1;
    239238
     
    244243        // Setup proper signal handlers
    245244        __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART );         // CtxSwitch handler
     245        // __kernel_sigaction( SIGSEGV, sigHandler_segv     , SA_SIGINFO );      // Failure handler
     246        // __kernel_sigaction( SIGBUS , sigHandler_segv     , SA_SIGINFO );      // Failure handler
    246247
    247248        signal_block( SIGALRM );
     
    295296// Receives SIGUSR1 signal and causes the current thread to yield
    296297void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    297         __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.CFA_REG_IP); )
     298        __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
    298299
    299300        // Check if it is safe to preempt here
    300301        if( !preemption_ready() ) { return; }
    301 
    302         __cfaabi_dbg_print_buffer_decl(" KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
    303302
    304303        preemption_in_progress = true;                      // Sync flag : prevent recursive calls to the signal handler
     
    372371}
    373372
     373// Sigaction wrapper : register an signal handler
     374static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
     375        struct sigaction act;
     376
     377        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     378        act.sa_flags = flags;
     379
     380        if ( sigaction( sig, &act, NULL ) == -1 ) {
     381                __cfaabi_dbg_print_buffer_decl(
     382                        " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
     383                        sig, handler, flags, errno, strerror( errno )
     384                );
     385                _exit( EXIT_FAILURE );
     386        }
     387}
     388
     389// Sigaction wrapper : restore default handler
     390static void __kernel_sigdefault( int sig ) {
     391        struct sigaction act;
     392
     393        act.sa_handler = SIG_DFL;
     394        act.sa_flags = 0;
     395        sigemptyset( &act.sa_mask );
     396
     397        if ( sigaction( sig, &act, NULL ) == -1 ) {
     398                __cfaabi_dbg_print_buffer_decl(
     399                        " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n",
     400                        sig, errno, strerror( errno )
     401                );
     402                _exit( EXIT_FAILURE );
     403        }
     404}
     405
     406//=============================================================================================
     407// Terminating Signals logic
     408//=============================================================================================
     409
     410__cfaabi_dbg_debug_do(
     411        static void __kernel_backtrace( int start ) {
     412                // skip first N stack frames
     413
     414                enum { Frames = 50 };
     415                void * array[Frames];
     416                int size = backtrace( array, Frames );
     417                char ** messages = backtrace_symbols( array, size );
     418
     419                // find executable name
     420                *index( messages[0], '(' ) = '\0';
     421                #ifdef __USE_STREAM__
     422                serr | "Stack back trace for:" | messages[0] | endl;
     423                #else
     424                fprintf( stderr, "Stack back trace for: %s\n", messages[0]);
     425                #endif
     426
     427                // skip last 2 stack frames after main
     428                for ( int i = start; i < size && messages != NULL; i += 1 ) {
     429                        char * name = NULL;
     430                        char * offset_begin = NULL;
     431                        char * offset_end = NULL;
     432
     433                        for ( char *p = messages[i]; *p; ++p ) {
     434                                // find parantheses and +offset
     435                                if ( *p == '(' ) {
     436                                        name = p;
     437                                }
     438                                else if ( *p == '+' ) {
     439                                        offset_begin = p;
     440                                }
     441                                else if ( *p == ')' ) {
     442                                        offset_end = p;
     443                                        break;
     444                                }
     445                        }
     446
     447                        // if line contains symbol print it
     448                        int frameNo = i - start;
     449                        if ( name && offset_begin && offset_end && name < offset_begin ) {
     450                                // delimit strings
     451                                *name++ = '\0';
     452                                *offset_begin++ = '\0';
     453                                *offset_end++ = '\0';
     454
     455                                #ifdef __USE_STREAM__
     456                                serr    | "("  | frameNo | ")" | messages[i] | ":"
     457                                        | name | "+" | offset_begin | offset_end | endl;
     458                                #else
     459                                fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
     460                                #endif
     461                        }
     462                        // otherwise, print the whole line
     463                        else {
     464                                #ifdef __USE_STREAM__
     465                                serr | "(" | frameNo | ")" | messages[i] | endl;
     466                                #else
     467                                fprintf( stderr, "(%i) %s\n", frameNo, messages[i] );
     468                                #endif
     469                        }
     470                }
     471
     472                free( messages );
     473        }
     474)
     475
     476// void sigHandler_segv( __CFA_SIGPARMS__ ) {
     477//      __cfaabi_dbg_debug_do(
     478//              #ifdef __USE_STREAM__
     479//              serr    | "*CFA runtime error* program cfa-cpp terminated with"
     480//                      | (sig == SIGSEGV ? "segment fault." : "bus error.")
     481//                      | endl;
     482//              #else
     483//              fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." );
     484//              #endif
     485
     486//              // skip first 2 stack frames
     487//              __kernel_backtrace( 1 );
     488//      )
     489//      exit( EXIT_FAILURE );
     490// }
     491
     492// void sigHandler_abort( __CFA_SIGPARMS__ ) {
     493//      // skip first 6 stack frames
     494//      __cfaabi_dbg_debug_do( __kernel_backtrace( 6 ); )
     495
     496//      // reset default signal handler
     497//      __kernel_sigdefault( SIGABRT );
     498
     499//      raise( SIGABRT );
     500// }
     501
    374502// Local Variables: //
    375503// mode: c //
Note: See TracChangeset for help on using the changeset viewer.