Changes in / [e9a3b20b:1a18423]


Ignore:
Location:
src
Files:
1 added
10 edited

Legend:

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

    re9a3b20b r1a18423  
    1616
    1717extern "C" {
     18#include <errno.h>
     19#include <stdio.h>
     20#include <string.h>
    1821#include <time.h>
     22#include <unistd.h>
    1923#include <sys/time.h>
    2024}
     
    2226#include "alarm.h"
    2327#include "kernel_private.h"
     28#include "libhdr.h"
    2429#include "preemption.h"
    2530
     
    3136        timespec curr;
    3237        clock_gettime( CLOCK_REALTIME, &curr );
    33         return ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
     38        __cfa_time_t curr_time = ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
     39        LIB_DEBUG_DO(
     40                char text[256];
     41                __attribute__((unused)) int len = snprintf( text, 256, "Kernel : current time is %lu\n", curr_time );
     42                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     43        );
     44        return curr_time;
    3445}
    3546
    3647void __kernel_set_timer( __cfa_time_t alarm ) {
     48
     49        LIB_DEBUG_DO(
     50                char text[256];
     51                __attribute__((unused)) int len = snprintf( text, 256, "Kernel : set timer to %lu\n", (__cfa_time_t)alarm );
     52                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     53        );
     54
    3755        itimerval val;
    3856        val.it_value.tv_sec = alarm / TIMEGRAN;                 // seconds
     
    7189}
    7290
     91LIB_DEBUG_DO( bool validate( alarm_list_t * this ) {
     92        alarm_node_t ** it = &this->head;
     93        while( (*it) ) {
     94                it = &(*it)->next;
     95        }
     96
     97        return it == this->tail;
     98})
     99
    73100static inline void insert_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t p ) {
    74         assert( !n->next );
     101        verify( !n->next );
    75102        if( p == this->tail ) {
    76103                this->tail = &n->next;
     
    80107        }
    81108        *p = n;
     109
     110        verify( validate( this ) );
    82111}
    83112
     
    89118
    90119        insert_at( this, n, it );
     120
     121        verify( validate( this ) );
    91122}
    92123
     
    100131                head->next = NULL;
    101132        }
     133        verify( validate( this ) );
    102134        return head;
    103135}
     
    105137static inline void remove_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t it ) {
    106138        verify( it );
    107         verify( (*it)->next == n );
    108 
    109         (*it)->next = n->next;
     139        verify( (*it) == n );
     140
     141        (*it) = n->next;
    110142        if( !n-> next ) {
    111143                this->tail = it;
    112144        }
    113145        n->next = NULL;
     146
     147        verify( validate( this ) );
    114148}
    115149
    116150static inline void remove( alarm_list_t * this, alarm_node_t * n ) {
    117151        alarm_node_t ** it = &this->head;
    118         while( (*it) && (*it)->next != n ) {
     152        while( (*it) && (*it) != n ) {
    119153                it = &(*it)->next;
    120154        }
    121155
     156        verify( validate( this ) );
     157
    122158        if( *it ) { remove_at( this, n, it ); }
     159
     160        verify( validate( this ) );
    123161}
    124162
    125163void register_self( alarm_node_t * this ) {
    126164        disable_interrupts();
    127         assert( !systemProcessor->pending_alarm );
     165        verify( !systemProcessor->pending_alarm );
    128166        lock( &systemProcessor->alarm_lock );
    129167        {
     168                verify( validate( &systemProcessor->alarms ) );
     169                bool first = !systemProcessor->alarms.head;
     170
    130171                insert( &systemProcessor->alarms, this );
    131172                if( systemProcessor->pending_alarm ) {
    132173                        tick_preemption();
    133174                }
     175                if( first ) {
     176                        __kernel_set_timer( systemProcessor->alarms.head->alarm - __kernel_get_time() );
     177                }
    134178        }
    135179        unlock( &systemProcessor->alarm_lock );
    136180        this->set = true;
    137         enable_interrupts();
     181        enable_interrupts( __PRETTY_FUNCTION__ );
    138182}
    139183
    140184void unregister_self( alarm_node_t * this ) {
     185        LIB_DEBUG_DO(
     186                char text[256];
     187                __attribute__((unused)) int len = snprintf( text, 256, "Kernel : unregister %p start\n", this );
     188                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     189        );
    141190        disable_interrupts();
    142191        lock( &systemProcessor->alarm_lock );
    143         remove( &systemProcessor->alarms, this );
     192        {
     193                verify( validate( &systemProcessor->alarms ) );
     194                remove( &systemProcessor->alarms, this );
     195        }
    144196        unlock( &systemProcessor->alarm_lock );
    145197        disable_interrupts();
    146198        this->set = false;
    147 }
     199        LIB_DEBUG_DO(
     200                len = snprintf( text, 256, "Kernel : unregister %p end\n", this );
     201                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     202        );
     203}
  • src/libcfa/concurrency/coroutine.c

    re9a3b20b r1a18423  
    3232#include "invoke.h"
    3333
    34 extern thread_local processor * this_processor;
     34extern volatile thread_local processor * this_processor;
    3535
    3636//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/invoke.c

    re9a3b20b r1a18423  
    3030extern void __suspend_internal(void);
    3131extern void __leave_monitor_desc( struct monitor_desc * this );
     32extern void disable_interrupts();
     33extern void enable_interrupts( const char * );
    3234
    3335void CtxInvokeCoroutine(
     
    6769      struct monitor_desc* mon = &thrd->mon;
    6870      cor->state = Active;
     71      enable_interrupts( __PRETTY_FUNCTION__ );
    6972
    7073      // LIB_DEBUG_PRINTF("Invoke Thread : invoking main %p (args %p)\n", main, this);
    7174      main( this );
    7275
     76      disable_interrupts();
    7377      __leave_monitor_desc( mon );
    7478
  • src/libcfa/concurrency/kernel

    re9a3b20b r1a18423  
    9090        unsigned int preemption;
    9191
    92         unsigned short disable_preempt_count;
     92        bool pending_preemption;
    9393
    94         bool pending_preemption;
     94        char * last_enable;
    9595};
    9696
  • src/libcfa/concurrency/kernel.c

    re9a3b20b r1a18423  
    5959// Global state
    6060
    61 thread_local processor * this_processor;
     61volatile thread_local processor * this_processor;
     62volatile thread_local unsigned short disable_preempt_count;
    6263
    6364coroutine_desc * this_coroutine(void) {
     
    142143        this->preemption_alarm = NULL;
    143144        this->preemption = default_preemption();
    144         this->disable_preempt_count = 1;                //Start with interrupts disabled
    145145        this->pending_preemption = false;
    146146
     
    154154        (&this->terminated){};
    155155        this->is_terminated = false;
    156         this->disable_preempt_count = 0;
     156        this->preemption_alarm = NULL;
     157        this->preemption = default_preemption();
    157158        this->pending_preemption = false;
     159        this->kernel_thread = pthread_self();
    158160
    159161        this->runner = runner;
    160         LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
     162        LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
    161163        runner{ this };
    162164}
     165
     166LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    163167
    164168void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
     
    168172
    169173        (&this->proc){ cltr, runner };
     174
     175        verify( validate( &this->alarms ) );
    170176}
    171177
     
    209215                        if(readyThread)
    210216                        {
     217                                verify( disable_preempt_count > 0 );
     218
    211219                                runThread(this, readyThread);
     220
     221                                verify( disable_preempt_count > 0 );
    212222
    213223                                //Some actions need to be taken from the kernel
     
    289299        processor * proc = (processor *) arg;
    290300        this_processor = proc;
     301        disable_preempt_count = 1;
    291302        // SKULLDUGGERY: We want to create a context for the processor coroutine
    292303        // which is needed for the 2-step context switch. However, there is no reason
     
    322333void start(processor * this) {
    323334        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    324        
     335
     336        // SIGALRM must only be caught by the system processor
     337        sigset_t old_mask;
     338        bool is_system_proc = this_processor == &systemProcessor->proc;
     339        if ( is_system_proc ) {
     340                // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the
     341                // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user
     342                // processor, and toggle back (below) previous signal mask of the system processor.
     343
     344                sigset_t new_mask;
     345                sigemptyset( &new_mask );
     346                sigemptyset( &old_mask );
     347                sigaddset( &new_mask, SIGALRM );
     348
     349                if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) {
     350                        abortf( "internal error, sigprocmask" );
     351                }
     352
     353                assert( ! sigismember( &old_mask, SIGALRM ) );
     354        }
     355
    325356        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
     357
     358        // Toggle back previous signal mask of system processor.
     359        if ( is_system_proc ) {
     360                if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) {
     361                        abortf( "internal error, sigprocmask" );
     362                } // if
     363        } // if
    326364
    327365        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
     
    347385}
    348386
    349 void ScheduleInternal() {
     387void BlockInternal() {
     388        disable_interrupts();
     389        verify( disable_preempt_count > 0 );
    350390        suspend();
    351 }
    352 
    353 void ScheduleInternal( spinlock * lock ) {
     391        verify( disable_preempt_count > 0 );
     392        enable_interrupts( __PRETTY_FUNCTION__ );
     393}
     394
     395void BlockInternal( spinlock * lock ) {
     396        disable_interrupts();
    354397        this_processor->finish.action_code = Release;
    355398        this_processor->finish.lock = lock;
     399
     400        verify( disable_preempt_count > 0 );
    356401        suspend();
    357 }
    358 
    359 void ScheduleInternal( thread_desc * thrd ) {
     402        verify( disable_preempt_count > 0 );
     403
     404        enable_interrupts( __PRETTY_FUNCTION__ );
     405}
     406
     407void BlockInternal( thread_desc * thrd ) {
     408        disable_interrupts();
    360409        this_processor->finish.action_code = Schedule;
    361410        this_processor->finish.thrd = thrd;
     411
     412        verify( disable_preempt_count > 0 );
    362413        suspend();
    363 }
    364 
    365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
     414        verify( disable_preempt_count > 0 );
     415
     416        enable_interrupts( __PRETTY_FUNCTION__ );
     417}
     418
     419void BlockInternal( spinlock * lock, thread_desc * thrd ) {
     420        disable_interrupts();
    366421        this_processor->finish.action_code = Release_Schedule;
    367422        this_processor->finish.lock = lock;
    368423        this_processor->finish.thrd = thrd;
     424
     425        verify( disable_preempt_count > 0 );
    369426        suspend();
    370 }
    371 
    372 void ScheduleInternal(spinlock ** locks, unsigned short count) {
     427        verify( disable_preempt_count > 0 );
     428
     429        enable_interrupts( __PRETTY_FUNCTION__ );
     430}
     431
     432void BlockInternal(spinlock ** locks, unsigned short count) {
     433        disable_interrupts();
    373434        this_processor->finish.action_code = Release_Multi;
    374435        this_processor->finish.locks = locks;
    375436        this_processor->finish.lock_count = count;
     437
     438        verify( disable_preempt_count > 0 );
    376439        suspend();
    377 }
    378 
    379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     440        verify( disable_preempt_count > 0 );
     441
     442        enable_interrupts( __PRETTY_FUNCTION__ );
     443}
     444
     445void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     446        disable_interrupts();
    380447        this_processor->finish.action_code = Release_Multi_Schedule;
    381448        this_processor->finish.locks = locks;
     
    383450        this_processor->finish.thrds = thrds;
    384451        this_processor->finish.thrd_count = thrd_count;
     452
     453        verify( disable_preempt_count > 0 );
    385454        suspend();
     455        verify( disable_preempt_count > 0 );
     456
     457        enable_interrupts( __PRETTY_FUNCTION__ );
    386458}
    387459
     
    403475        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    404476
    405         // Enable preemption
    406         kernel_start_preemption();
    407 
    408477        // Initialize the system cluster
    409478        systemCluster = (cluster *)&systemCluster_storage;
     
    425494        this_processor->current_thread = mainThread;
    426495        this_processor->current_coroutine = &mainThread->cor;
     496        disable_preempt_count = 1;
     497
     498        // Enable preemption
     499        kernel_start_preemption();
    427500
    428501        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
     
    435508        // THE SYSTEM IS NOW COMPLETELY RUNNING
    436509        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
     510
     511        enable_interrupts( __PRETTY_FUNCTION__ );
    437512}
    438513
    439514void kernel_shutdown(void) {
    440515        LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n");
     516
     517        disable_interrupts();
    441518
    442519        // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     
    447524
    448525        // THE SYSTEM IS NOW COMPLETELY STOPPED
     526
     527        // Disable preemption
     528        kernel_stop_preemption();
    449529
    450530        // Destroy the system processor and its context in reverse order of construction
     
    550630        if( !this->cond ) {
    551631                append( &this->blocked, this_thread() );
    552                 ScheduleInternal( &this->lock );
    553                 lock( &this->lock );
    554         }
    555         unlock( &this->lock );
     632                BlockInternal( &this->lock );
     633        }
     634        else {
     635                unlock( &this->lock );
     636        }
    556637}
    557638
     
    561642                this->cond = true;
    562643
     644                disable_interrupts();
    563645                thread_desc * it;
    564646                while( it = pop_head( &this->blocked) ) {
    565647                        ScheduleThread( it );
    566648                }
     649                enable_interrupts( __PRETTY_FUNCTION__ );
    567650        }
    568651        unlock( &this->lock );
  • src/libcfa/concurrency/kernel_private.h

    re9a3b20b r1a18423  
    3030thread_desc * nextThread(cluster * this);
    3131
    32 void ScheduleInternal(void);
    33 void ScheduleInternal(spinlock * lock);
    34 void ScheduleInternal(thread_desc * thrd);
    35 void ScheduleInternal(spinlock * lock, thread_desc * thrd);
    36 void ScheduleInternal(spinlock ** locks, unsigned short count);
    37 void ScheduleInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);
     32void BlockInternal(void);
     33void BlockInternal(spinlock * lock);
     34void BlockInternal(thread_desc * thrd);
     35void BlockInternal(spinlock * lock, thread_desc * thrd);
     36void BlockInternal(spinlock ** locks, unsigned short count);
     37void BlockInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);
    3838
    3939//-----------------------------------------------------------------------------
     
    6060extern cluster * systemCluster;
    6161extern system_proc_t * systemProcessor;
    62 extern thread_local processor * this_processor;
     62extern volatile thread_local processor * this_processor;
     63extern volatile thread_local unsigned short disable_preempt_count;
    6364
    64 static inline void disable_interrupts() {
    65         __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST );
    66         assert( prev != (unsigned short) -1 );
    67 }
    68 
    69 static inline void enable_interrupts_noRF() {
    70         __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    71         verify( prev != (unsigned short) 0 );
    72 }
    73 
    74 static inline void enable_interrupts() {
    75         __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    76         verify( prev != (unsigned short) 0 );
    77         if( prev == 1 && this_processor->pending_preemption ) {
    78                 ScheduleInternal( this_processor->current_thread );
    79                 this_processor->pending_preemption = false;
    80         }
     65extern "C" {
     66        void disable_interrupts();
     67        void enable_interrupts_noRF();
     68        void enable_interrupts( const char * );
    8169}
    8270
  • src/libcfa/concurrency/monitor.c

    re9a3b20b r1a18423  
    6363                        append( &this->entry_queue, thrd );
    6464                        LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);
    65                         ScheduleInternal( &this->lock );
    66 
    67                         //ScheduleInternal will unlock spinlock, no need to unlock ourselves
     65                        BlockInternal( &this->lock );
     66
     67                        //BlockInternal will unlock spinlock, no need to unlock ourselves
    6868                        return;
    6969                }
     
    170170        unsigned short count = this->monitor_count;
    171171        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
    172         spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
     172        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to BlockInternal
    173173
    174174        LIB_DEBUG_PRINT_SAFE("count %i\n", count);
     
    208208
    209209        // Everything is ready to go to sleep
    210         ScheduleInternal( locks, count, threads, thread_count );
     210        BlockInternal( locks, count, threads, thread_count );
    211211
    212212
     
    281281        unsigned short count = this->monitor_count;
    282282        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
    283         spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
     283        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to BlockInternal
    284284
    285285        lock_all( this->monitors, locks, count );
     
    309309
    310310        //Everything is ready to go to sleep
    311         ScheduleInternal( locks, count, &signallee, 1 );
     311        BlockInternal( locks, count, &signallee, 1 );
    312312
    313313
     
    339339        // unsigned short count = this->current_monitor_count;
    340340        // unsigned int recursions[ count ];            //Save the current recursion levels to restore them later
    341         // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to ScheduleInternal
     341        // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to BlockInternal
    342342
    343343        // lock_all( this->current_monitors, locks, count );
     
    348348
    349349        // // // Everything is ready to go to sleep
    350         // // ScheduleInternal( locks, count, threads, thread_count );
     350        // // BlockInternal( locks, count, threads, thread_count );
    351351
    352352
  • src/libcfa/concurrency/preemption.c

    re9a3b20b r1a18423  
    1717#include "preemption.h"
    1818
     19
    1920extern "C" {
     21#include <errno.h>
     22#define __USE_GNU
    2023#include <signal.h>
    21 }
    22 
    23 #define __CFA_DEFAULT_PREEMPTION__ 10
     24#undef __USE_GNU
     25#include <stdio.h>
     26#include <string.h>
     27#include <unistd.h>
     28}
     29
     30#include "libhdr.h"
     31
     32#define __CFA_DEFAULT_PREEMPTION__ 10000
    2433
    2534__attribute__((weak)) unsigned int default_preemption() {
     
    2736}
    2837
     38#define __CFA_SIGCXT__ ucontext_t *
     39#define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt
     40
    2941static void preempt( processor   * this );
    3042static void timeout( thread_desc * this );
     43
     44void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
     45void sigHandler_alarm    ( __CFA_SIGPARMS__ );
     46
     47static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
    3148
    3249//=============================================================================================
     
    3552
    3653void kernel_start_preemption() {
    37 
    38 }
     54        LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n");
     55        __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO );
     56        __kernel_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO );
     57}
     58
     59void kernel_stop_preemption() {
     60        //Block all signals, we are no longer in a position to handle them
     61        sigset_t mask;
     62        sigfillset( &mask );
     63        sigprocmask( SIG_BLOCK, &mask, NULL );
     64        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
     65
     66        assert( !systemProcessor->alarms.head );
     67        assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head );
     68}
     69
     70LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    3971
    4072void tick_preemption() {
     73        LIB_DEBUG_DO(
     74                char text[256];
     75                __attribute__((unused)) int len = snprintf( text, 256, "Ticking preemption\n" );
     76                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     77        );
     78
    4179        alarm_list_t * alarms = &systemProcessor->alarms;
    4280        __cfa_time_t currtime = __kernel_get_time();
    4381        while( alarms->head && alarms->head->alarm < currtime ) {
    4482                alarm_node_t * node = pop(alarms);
     83                LIB_DEBUG_DO(
     84                        len = snprintf( text, 256, "Ticking %p\n", node );
     85                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     86                );
    4587                if( node->kernel_alarm ) {
    4688                        preempt( node->proc );
     
    5092                }
    5193
     94                LIB_DEBUG_DO( assert( validate( alarms ) ) );
     95
    5296                if( node->period > 0 ) {
    53                         node->alarm += node->period;
     97                        node->alarm = currtime + node->period;
    5498                        insert( alarms, node );
    5599                }
     
    62106                __kernel_set_timer( alarms->head->alarm - currtime );
    63107        }
     108
     109        verify( validate( alarms ) );
     110        LIB_DEBUG_DO(
     111                len = snprintf( text, 256, "Ticking preemption done\n" );
     112                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     113        );
    64114}
    65115
    66116void update_preemption( processor * this, __cfa_time_t duration ) {
    67         //     assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 );
     117        LIB_DEBUG_DO(
     118                char text[256];
     119                __attribute__((unused)) int len = snprintf( text, 256, "Processor : %p updating preemption to %lu\n", this, duration );
     120                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     121        );
     122
    68123        alarm_node_t * alarm = this->preemption_alarm;
     124        duration *= 1000;
    69125
    70126        // Alarms need to be enabled
     
    97153
    98154void ^?{}( preemption_scope * this ) {
     155        disable_interrupts();
     156
    99157        update_preemption( this->proc, 0 );
    100158}
     
    104162//=============================================================================================
    105163
     164extern "C" {
     165        void disable_interrupts() {
     166                __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST );
     167                verify( new_val < (unsigned short)65_000 );
     168                verify( new_val != (unsigned short) 0 );
     169        }
     170
     171        void enable_interrupts_noRF() {
     172                unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     173                verify( prev != (unsigned short) 0 );
     174        }
     175
     176        void enable_interrupts( const char * func ) {
     177                unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     178                verify( prev != (unsigned short) 0 );
     179                if( prev == 1 && this_processor->pending_preemption ) {
     180                        this_processor->pending_preemption = false;
     181                        LIB_DEBUG_DO(
     182                                char text[256];
     183                                __attribute__((unused)) int len = snprintf( text, 256, "Executing deferred CtxSwitch on %p\n", this_processor );
     184                                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     185                        );
     186                        BlockInternal( this_processor->current_thread );
     187                }
     188
     189                this_processor->last_enable = func;
     190        }
     191}
     192
     193static inline void signal_unblock( bool alarm ) {
     194        sigset_t mask;
     195        sigemptyset( &mask );
     196        sigaddset( &mask, SIGUSR1 );
     197
     198        if( alarm ) sigaddset( &mask, SIGALRM );
     199
     200        if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
     201            abortf( "internal error, sigprocmask" );
     202        } // if
     203}
     204
    106205static inline bool preemption_ready() {
    107         return this_processor->disable_preempt_count == 0;
     206        return disable_preempt_count == 0;
    108207}
    109208
     
    116215}
    117216
    118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) {
     217void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
     218
     219        LIB_DEBUG_DO(
     220                char text[256];
     221                __attribute__((unused)) int len = snprintf( text, 256, "Ctx Switch IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP]));
     222                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     223        );
     224
     225        signal_unblock( false );
    119226        if( preemption_ready() ) {
    120                 ScheduleInternal( this_processor->current_thread );
     227                LIB_DEBUG_DO(
     228                        len = snprintf( text, 256, "Ctx Switch IRH : Blocking thread %p on %p\n", this_processor->current_thread, this_processor );
     229                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     230                );
     231                BlockInternal( this_processor->current_thread );
    121232        }
    122233        else {
     234                LIB_DEBUG_DO(
     235                        len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" );
     236                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     237                );
    123238                defer_ctxSwitch();
    124239        }
    125240}
    126241
    127 void sigHandler_alarm( __attribute__((unused)) int sig ) {
     242void sigHandler_alarm( __CFA_SIGPARMS__ ) {
     243
     244        LIB_DEBUG_DO(
     245                char text[256];
     246                __attribute__((unused)) int len = snprintf( text, 256, "\nAlarm IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP]) );
     247                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     248        );
     249
     250        signal_unblock( true );
    128251        if( try_lock( &systemProcessor->alarm_lock ) ) {
    129252                tick_preemption();
     
    133256                defer_alarm();
    134257        }
     258
     259        if( preemption_ready() && this_processor->pending_preemption ) {
     260                LIB_DEBUG_DO(
     261                        len = snprintf( text, 256, "Alarm IRH : Blocking thread\n" );
     262                        LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     263                );
     264                this_processor->pending_preemption = false;
     265                BlockInternal( this_processor->current_thread );
     266        }
    135267}
    136268
    137269static void preempt( processor * this ) {
    138         pthread_kill( this->kernel_thread, SIGUSR1 );
     270        LIB_DEBUG_DO(
     271                char text[256];
     272                __attribute__((unused)) int len = snprintf( text, 256, "Processor : signalling %p\n", this );
     273                LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
     274        );
     275
     276        if( this != systemProcessor ) {
     277                pthread_kill( this->kernel_thread, SIGUSR1 );
     278        }
     279        else {
     280                defer_ctxSwitch();
     281        }
    139282}
    140283
     
    142285        //TODO : implement waking threads
    143286}
     287
     288static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
     289        struct sigaction act;
     290
     291        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     292        sigemptyset( &act.sa_mask );
     293        sigaddset( &act.sa_mask, SIGALRM );             // disabled during signal handler
     294        sigaddset( &act.sa_mask, SIGUSR1 );
     295
     296        act.sa_flags = flags;
     297
     298        if ( sigaction( sig, &act, NULL ) == -1 ) {
     299                // THE KERNEL IS NOT STARTED SO CALL NO uC++ ROUTINES!
     300                char helpText[256];
     301                __attribute__((unused)) int len = snprintf( helpText, 256, " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
     302                                sig, handler, flags, errno, strerror( errno ) );
     303                LIB_DEBUG_WRITE( STDERR_FILENO, helpText, len );
     304                _exit( EXIT_FAILURE );
     305        } // if
     306}
  • src/libcfa/concurrency/thread.c

    re9a3b20b r1a18423  
    2828}
    2929
    30 extern thread_local processor * this_processor;
     30extern volatile thread_local processor * this_processor;
    3131
    3232//-----------------------------------------------------------------------------
     
    8484
    8585void yield( void ) {
    86         ScheduleInternal( this_processor->current_thread );
     86        BlockInternal( this_processor->current_thread );
    8787}
    8888
  • src/libcfa/libhdr/libdebug.h

    re9a3b20b r1a18423  
    1919#ifdef __CFA_DEBUG__
    2020        #define LIB_DEBUG_DO(x) x
    21         #define LIB_NO_DEBUG_DO(x) ((void)0)
     21        #define LIB_NO_DEBUG_DO(x)
    2222#else
    23         #define LIB_DEBUG_DO(x) ((void)0)
    24         #define LIB_NO_DEBUG_DO(x) x     
     23        #define LIB_DEBUG_DO(x)
     24        #define LIB_NO_DEBUG_DO(x) x
    2525#endif
    2626
Note: See TracChangeset for help on using the changeset viewer.