Ignore:
Timestamp:
Jul 13, 2017, 3:57:04 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
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:
0720e049, 9a1e509
Parents:
55a68c3 (diff), d6ff3ff (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 plg.uwaterloo.ca:/u/cforall/software/cfa/cfa-cc

File:
1 edited

Legend:

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

    r55a68c3 r3d4b23fa  
    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 && !preemption_in_progress;
     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        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopping\n");
     221
     222        sigset_t mask;
     223        sigfillset( &mask );
     224        sigprocmask( SIG_BLOCK, &mask, NULL );
     225
     226        sigval val = { 1 };
     227        pthread_sigqueue( alarm_thread, SIGALRM, val );
     228        pthread_join( alarm_thread, NULL );
     229        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
     230}
     231
    91232void ?{}( preemption_scope * this, processor * proc ) {
    92233        (&this->alarm){ proc };
     
    97238
    98239void ^?{}( preemption_scope * this ) {
     240        disable_interrupts();
     241
    99242        update_preemption( this->proc, 0 );
    100243}
    101244
    102245//=============================================================================================
    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 ) {
     246// Kernel Signal Handlers
     247//=============================================================================================
     248
     249void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
     250        LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
    119251        if( preemption_ready() ) {
    120                 ScheduleInternal( this_processor->current_thread );
     252                preemption_in_progress = true;
     253                signal_unblock( SIGUSR1 );
     254                this_processor->pending_preemption = false;
     255                preemption_in_progress = false;
     256                BlockInternal( (thread_desc*)this_thread );
    121257        }
    122258        else {
     
    125261}
    126262
    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 }
     263void * alarm_loop( __attribute__((unused)) void * args ) {
     264        sigset_t mask;
     265        sigemptyset( &mask );
     266        sigaddset( &mask, SIGALRM );
     267
     268        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     269            abortf( "internal error, pthread_sigmask" );
     270        }
     271
     272        while( true ) {
     273                siginfo_t info;
     274                int sig = sigwaitinfo( &mask, &info );
     275                if( sig < 0 ) {
     276                        abortf( "internal error, sigwait" );
     277                }
     278                else if( sig == SIGALRM )
     279                {
     280                        LIB_DEBUG_PRINT_SAFE("Kernel : Caught signal %d (%d)\n", sig, info.si_value.sival_int );
     281                        if( info.si_value.sival_int == 0 )
     282                        {
     283                                LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread tick\n");
     284                                lock( &systemProcessor->alarm_lock DEBUG_CTX2 );
     285                                tick_preemption();
     286                                unlock( &systemProcessor->alarm_lock );
     287                        }
     288                        else if( info.si_value.sival_int == 1 )
     289                        {
     290                                break;
     291                        }
     292                }
     293                else
     294                {
     295                        LIB_DEBUG_PRINT_SAFE("Kernel : Unexpected signal %d (%d)\n", sig, info.si_value.sival_int);
     296                }
     297        }
     298
     299        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread stopping\n");
     300        return NULL;
     301}
     302
     303static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
     304        struct sigaction act;
     305
     306        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     307        act.sa_flags = flags;
     308
     309        if ( sigaction( sig, &act, NULL ) == -1 ) {
     310                LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO,
     311                        " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
     312                        sig, handler, flags, errno, strerror( errno )
     313                );
     314                _exit( EXIT_FAILURE );
     315        }
     316}
     317
     318typedef void (*sa_handler_t)(int);
     319
     320static void __kernel_sigdefault( int sig ) {
     321        struct sigaction act;
     322
     323        // act.sa_handler = SIG_DFL;
     324        act.sa_flags = 0;
     325        sigemptyset( &act.sa_mask );
     326
     327        if ( sigaction( sig, &act, NULL ) == -1 ) {
     328                LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO,
     329                        " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n",
     330                        sig, errno, strerror( errno )
     331                );
     332                _exit( EXIT_FAILURE );
     333        }
     334}
     335
     336//=============================================================================================
     337// Terminating Signals logic
     338//=============================================================================================
     339
     340LIB_DEBUG_DO(
     341        static void __kernel_backtrace( int start ) {
     342                // skip first N stack frames
     343
     344                enum { Frames = 50 };
     345                void * array[Frames];
     346                int size = backtrace( array, Frames );
     347                char ** messages = backtrace_symbols( array, size );
     348
     349                // find executable name
     350                *index( messages[0], '(' ) = '\0';
     351                #ifdef __USE_STREAM__
     352                serr | "Stack back trace for:" | messages[0] | endl;
     353                #else
     354                fprintf( stderr, "Stack back trace for: %s\n", messages[0]);
     355                #endif
     356
     357                // skip last 2 stack frames after main
     358                for ( int i = start; i < size && messages != NULL; i += 1 ) {
     359                        char * name = NULL;
     360                        char * offset_begin = NULL;
     361                        char * offset_end = NULL;
     362
     363                        for ( char *p = messages[i]; *p; ++p ) {
     364                                // find parantheses and +offset
     365                                if ( *p == '(' ) {
     366                                        name = p;
     367                                }
     368                                else if ( *p == '+' ) {
     369                                        offset_begin = p;
     370                                }
     371                                else if ( *p == ')' ) {
     372                                        offset_end = p;
     373                                        break;
     374                                }
     375                        }
     376
     377                        // if line contains symbol print it
     378                        int frameNo = i - start;
     379                        if ( name && offset_begin && offset_end && name < offset_begin ) {
     380                                // delimit strings
     381                                *name++ = '\0';
     382                                *offset_begin++ = '\0';
     383                                *offset_end++ = '\0';
     384
     385                                #ifdef __USE_STREAM__
     386                                serr    | "("  | frameNo | ")" | messages[i] | ":"
     387                                        | name | "+" | offset_begin | offset_end | endl;
     388                                #else
     389                                fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
     390                                #endif
     391                        }
     392                        // otherwise, print the whole line
     393                        else {
     394                                #ifdef __USE_STREAM__
     395                                serr | "(" | frameNo | ")" | messages[i] | endl;
     396                                #else
     397                                fprintf( stderr, "(%i) %s\n", frameNo, messages[i] );
     398                                #endif
     399                        }
     400                }
     401
     402                free( messages );
     403        }
     404)
     405
     406// void sigHandler_segv( __CFA_SIGPARMS__ ) {
     407//      LIB_DEBUG_DO(
     408//              #ifdef __USE_STREAM__
     409//              serr    | "*CFA runtime error* program cfa-cpp terminated with"
     410//                      | (sig == SIGSEGV ? "segment fault." : "bus error.")
     411//                      | endl;
     412//              #else
     413//              fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." );
     414//              #endif
     415
     416//              // skip first 2 stack frames
     417//              __kernel_backtrace( 1 );
     418//      )
     419//      exit( EXIT_FAILURE );
     420// }
     421
     422// void sigHandler_abort( __CFA_SIGPARMS__ ) {
     423//      // skip first 6 stack frames
     424//      LIB_DEBUG_DO( __kernel_backtrace( 6 ); )
     425
     426//      // reset default signal handler
     427//      __kernel_sigdefault( SIGABRT );
     428
     429//      raise( SIGABRT );
     430// }
Note: See TracChangeset for help on using the changeset viewer.