Ignore:
Timestamp:
Jul 12, 2017, 9:50:58 PM (4 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
1a6e855
Parents:
8b47e50 (diff), acb89ed (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

File:
1 edited

Legend:

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

    r8b47e50 ref6851a  
    1515//
    1616
     17#include "libhdr.h"
    1718#include "preemption.h"
    1819
    1920extern "C" {
     21#include <errno.h>
     22#include <execinfo.h>
     23#define __USE_GNU
    2024#include <signal.h>
    21 }
    22 
    23 #define __CFA_DEFAULT_PREEMPTION__ 10
     25#undef __USE_GNU
     26#include <stdio.h>
     27#include <string.h>
     28#include <unistd.h>
     29}
     30
     31
     32#ifdef __USE_STREAM__
     33#include "fstream"
     34#endif
     35
     36#define __CFA_DEFAULT_PREEMPTION__ 10000
    2437
    2538__attribute__((weak)) unsigned int default_preemption() {
     
    2740}
    2841
     42#define __CFA_SIGCXT__ ucontext_t *
     43#define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt
     44
    2945static void preempt( processor   * this );
    3046static void timeout( thread_desc * this );
    3147
     48void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
     49void sigHandler_alarm    ( __CFA_SIGPARMS__ );
     50void sigHandler_segv     ( __CFA_SIGPARMS__ );
     51void sigHandler_abort    ( __CFA_SIGPARMS__ );
     52
     53static 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
     62
    3263//=============================================================================================
    3364// Kernel Preemption logic
    3465//=============================================================================================
    3566
    36 void kernel_start_preemption() {
    37 
    38 }
    39 
    4067void tick_preemption() {
     68        // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ticking preemption\n" );
     69
    4170        alarm_list_t * alarms = &systemProcessor->alarms;
    4271        __cfa_time_t currtime = __kernel_get_time();
    4372        while( alarms->head && alarms->head->alarm < currtime ) {
    4473                alarm_node_t * node = pop(alarms);
     74                // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking %p\n", node );
     75
    4576                if( node->kernel_alarm ) {
    4677                        preempt( node->proc );
     
    5081                }
    5182
     83                verify( validate( alarms ) );
     84
    5285                if( node->period > 0 ) {
    53                         node->alarm += node->period;
     86                        node->alarm = currtime + node->period;
    5487                        insert( alarms, node );
    5588                }
     
    6295                __kernel_set_timer( alarms->head->alarm - currtime );
    6396        }
     97
     98        verify( validate( alarms ) );
     99        // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking preemption done\n" );
    64100}
    65101
    66102void update_preemption( processor * this, __cfa_time_t duration ) {
    67         //     assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 );
     103        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p updating preemption to %lu\n", this, duration );
     104
    68105        alarm_node_t * alarm = this->preemption_alarm;
     106        duration *= 1000;
    69107
    70108        // Alarms need to be enabled
     
    89127}
    90128
     129//=============================================================================================
     130// Kernel Signal Tools
     131//=============================================================================================
     132
     133LIB_DEBUG_DO( static thread_local void * last_interrupt = 0; )
     134
     135extern "C" {
     136        void disable_interrupts() {
     137                __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST );
     138                verify( new_val < (unsigned short)65_000 );
     139                verify( new_val != (unsigned short) 0 );
     140        }
     141
     142        void enable_interrupts_noRF() {
     143                __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     144                verify( prev != (unsigned short) 0 );
     145        }
     146
     147        void enable_interrupts( DEBUG_CTX_PARAM ) {
     148                processor * proc   = this_processor;
     149                thread_desc * thrd = this_thread;
     150                unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     151                verify( prev != (unsigned short) 0 );
     152                if( prev == 1 && proc->pending_preemption ) {
     153                        proc->pending_preemption = false;
     154                        BlockInternal( thrd );
     155                }
     156
     157                LIB_DEBUG_DO( proc->last_enable = caller; )
     158        }
     159}
     160
     161static inline void signal_unblock( int sig ) {
     162        sigset_t mask;
     163        sigemptyset( &mask );
     164        sigaddset( &mask, sig );
     165
     166        if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
     167            abortf( "internal error, pthread_sigmask" );
     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}
     180
     181static inline bool preemption_ready() {
     182        return disable_preempt_count == 0;
     183}
     184
     185static inline void defer_ctxSwitch() {
     186        this_processor->pending_preemption = true;
     187}
     188
     189static inline void defer_alarm() {
     190        systemProcessor->pending_alarm = true;
     191}
     192
     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
    91229void ?{}( preemption_scope * this, processor * proc ) {
    92230        (&this->alarm){ proc };
     
    97235
    98236void ^?{}( preemption_scope * this ) {
     237        disable_interrupts();
     238
    99239        update_preemption( this->proc, 0 );
    100240}
    101241
    102242//=============================================================================================
    103 // Kernel Signal logic
    104 //=============================================================================================
    105 
    106 static inline bool preemption_ready() {
    107         return this_processor->disable_preempt_count == 0;
    108 }
    109 
    110 static inline void defer_ctxSwitch() {
    111         this_processor->pending_preemption = true;
    112 }
    113 
    114 static inline void defer_alarm() {
    115         systemProcessor->pending_alarm = true;
    116 }
    117 
    118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) {
     243// Kernel Signal Handlers
     244//=============================================================================================
     245
     246void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
     247        LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
    119248        if( preemption_ready() ) {
    120                 ScheduleInternal( this_processor->current_thread );
     249                signal_unblock( SIGUSR1 );
     250                BlockInternal( (thread_desc*)this_thread );
    121251        }
    122252        else {
     
    125255}
    126256
    127 void sigHandler_alarm( __attribute__((unused)) int sig ) {
    128         if( try_lock( &systemProcessor->alarm_lock ) ) {
    129                 tick_preemption();
    130                 unlock( &systemProcessor->alarm_lock );
    131         }
    132         else {
    133                 defer_alarm();
    134         }
    135 }
    136 
    137 static void preempt( processor * this ) {
    138         pthread_kill( this->kernel_thread, SIGUSR1 );
    139 }
    140 
    141 static void timeout( thread_desc * this ) {
    142         //TODO : implement waking threads
    143 }
     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        }
     314}
     315
     316static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
     317        struct sigaction act;
     318
     319        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     320        act.sa_flags = flags;
     321
     322        if ( sigaction( sig, &act, NULL ) == -1 ) {
     323                LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO,
     324                        " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
     325                        sig, handler, flags, errno, strerror( errno )
     326                );
     327                _exit( EXIT_FAILURE );
     328        }
     329}
     330
     331typedef void (*sa_handler_t)(int);
     332
     333static void __kernel_sigdefault( int sig ) {
     334        struct sigaction act;
     335
     336        // act.sa_handler = SIG_DFL;
     337        act.sa_flags = 0;
     338        sigemptyset( &act.sa_mask );
     339
     340        if ( sigaction( sig, &act, NULL ) == -1 ) {
     341                LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO,
     342                        " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n",
     343                        sig, errno, strerror( errno )
     344                );
     345                _exit( EXIT_FAILURE );
     346        }
     347}
     348
     349//=============================================================================================
     350// Terminating Signals logic
     351//=============================================================================================
     352
     353LIB_DEBUG_DO(
     354        static void __kernel_backtrace( int start ) {
     355                // skip first N stack frames
     356
     357                enum { Frames = 50 };
     358                void * array[Frames];
     359                int size = backtrace( array, Frames );
     360                char ** messages = backtrace_symbols( array, size );
     361
     362                // find executable name
     363                *index( messages[0], '(' ) = '\0';
     364                #ifdef __USE_STREAM__
     365                serr | "Stack back trace for:" | messages[0] | endl;
     366                #else
     367                fprintf( stderr, "Stack back trace for: %s\n", messages[0]);
     368                #endif
     369
     370                // skip last 2 stack frames after main
     371                for ( int i = start; i < size && messages != NULL; i += 1 ) {
     372                        char * name = NULL;
     373                        char * offset_begin = NULL;
     374                        char * offset_end = NULL;
     375
     376                        for ( char *p = messages[i]; *p; ++p ) {
     377                                // find parantheses and +offset
     378                                if ( *p == '(' ) {
     379                                        name = p;
     380                                }
     381                                else if ( *p == '+' ) {
     382                                        offset_begin = p;
     383                                }
     384                                else if ( *p == ')' ) {
     385                                        offset_end = p;
     386                                        break;
     387                                }
     388                        }
     389
     390                        // if line contains symbol print it
     391                        int frameNo = i - start;
     392                        if ( name && offset_begin && offset_end && name < offset_begin ) {
     393                                // delimit strings
     394                                *name++ = '\0';
     395                                *offset_begin++ = '\0';
     396                                *offset_end++ = '\0';
     397
     398                                #ifdef __USE_STREAM__
     399                                serr    | "("  | frameNo | ")" | messages[i] | ":"
     400                                        | name | "+" | offset_begin | offset_end | endl;
     401                                #else
     402                                fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
     403                                #endif
     404                        }
     405                        // otherwise, print the whole line
     406                        else {
     407                                #ifdef __USE_STREAM__
     408                                serr | "(" | frameNo | ")" | messages[i] | endl;
     409                                #else
     410                                fprintf( stderr, "(%i) %s\n", frameNo, messages[i] );
     411                                #endif
     412                        }
     413                }
     414
     415                free( messages );
     416        }
     417)
     418
     419// void sigHandler_segv( __CFA_SIGPARMS__ ) {
     420//      LIB_DEBUG_DO(
     421//              #ifdef __USE_STREAM__
     422//              serr    | "*CFA runtime error* program cfa-cpp terminated with"
     423//                      | (sig == SIGSEGV ? "segment fault." : "bus error.")
     424//                      | endl;
     425//              #else
     426//              fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." );
     427//              #endif
     428
     429//              // skip first 2 stack frames
     430//              __kernel_backtrace( 1 );
     431//      )
     432//      exit( EXIT_FAILURE );
     433// }
     434
     435// void sigHandler_abort( __CFA_SIGPARMS__ ) {
     436//      // skip first 6 stack frames
     437//      LIB_DEBUG_DO( __kernel_backtrace( 6 ); )
     438
     439//      // reset default signal handler
     440//      __kernel_sigdefault( SIGABRT );
     441
     442//      raise( SIGABRT );
     443// }
Note: See TracChangeset for help on using the changeset viewer.