Ignore:
Timestamp:
Jul 26, 2017, 12:19:41 PM (9 years ago)
Author:
Thierry Delisle <tdelisle@…>
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, stuck-waitfor-destruct, with_gc
Children:
b947fb2
Parents:
e0a653d (diff), ea91c42 (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:software/cfa/cfa-cc

Location:
src/libcfa/concurrency
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/CtxSwitch-i386.S

    re0a653d r33218c6  
    1 //                               -*- Mode: Asm -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Dec 6 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : Tue Dec 6 12:27:26 2016
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:29:25 2017
     13// Update Count     : 1
    1514//
    1615// This  library is free  software; you  can redistribute  it and/or  modify it
     
    9998
    10099// Local Variables: //
    101 // compile-command: "make install" //
     100// mode: c //
     101// tab-width: 4 //
    102102// End: //
  • src/libcfa/concurrency/CtxSwitch-x86_64.S

    re0a653d r33218c6  
    1 //                               -*- Mode: Asm -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Mon Nov 28 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : Mon Nov 28 12:27:26 2016
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:28:11 2017
     13// Update Count     : 1
    1514//
    1615// This  library is free  software; you  can redistribute  it and/or  modify it
  • src/libcfa/concurrency/alarm.c

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Fri Jun 2 11:31:25 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:35:18 2017
     13// Update Count     : 1
    1514//
    1615
     
    3130
    3231//=============================================================================================
     32// time type
     33//=============================================================================================
     34
     35#define one_second         1_000_000_000ul
     36#define one_milisecond         1_000_000ul
     37#define one_microsecond            1_000ul
     38#define one_nanosecond                 1ul
     39
     40__cfa_time_t zero_time = { 0 };
     41
     42void ?{}( __cfa_time_t * this ) { this->val = 0; }
     43void ?{}( __cfa_time_t * this, zero_t zero ) { this->val = 0; }
     44
     45void ?{}( itimerval * this, __cfa_time_t * alarm ) {
     46        this->it_value.tv_sec = alarm->val / one_second;                        // seconds
     47        this->it_value.tv_usec = max( (alarm->val % one_second) / one_microsecond, 1000 ); // microseconds
     48        this->it_interval.tv_sec = 0;
     49        this->it_interval.tv_usec = 0;
     50}
     51
     52
     53void ?{}( __cfa_time_t * this, timespec * curr ) {
     54        uint64_t secs  = curr->tv_sec;
     55        uint64_t nsecs = curr->tv_nsec;
     56        this->val = (secs * one_second) + nsecs;
     57}
     58
     59__cfa_time_t ?=?( __cfa_time_t * this, zero_t rhs ) {
     60        this->val = 0;
     61        return *this;
     62}
     63
     64__cfa_time_t from_s ( uint64_t val ) { __cfa_time_t ret; ret.val = val * 1_000_000_000ul; return ret; }
     65__cfa_time_t from_ms( uint64_t val ) { __cfa_time_t ret; ret.val = val *     1_000_000ul; return ret; }
     66__cfa_time_t from_us( uint64_t val ) { __cfa_time_t ret; ret.val = val *         1_000ul; return ret; }
     67__cfa_time_t from_ns( uint64_t val ) { __cfa_time_t ret; ret.val = val *             1ul; return ret; }
     68
     69//=============================================================================================
    3370// Clock logic
    3471//=============================================================================================
     
    3774        timespec curr;
    3875        clock_gettime( CLOCK_REALTIME, &curr );
    39         __cfa_time_t curr_time = ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
    40         // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : current time is %lu\n", curr_time );
    41         return curr_time;
     76        return (__cfa_time_t){ &curr };
    4277}
    4378
    4479void __kernel_set_timer( __cfa_time_t alarm ) {
    45         LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : set timer to %lu\n", (__cfa_time_t)alarm );
    46         itimerval val;
    47         val.it_value.tv_sec = alarm / TIMEGRAN;                 // seconds
    48         val.it_value.tv_usec = (alarm % TIMEGRAN) / ( TIMEGRAN / 1_000_000L ); // microseconds
    49         val.it_interval.tv_sec = 0;
    50         val.it_interval.tv_usec = 0;
     80        itimerval val = { &alarm };
    5181        setitimer( ITIMER_REAL, &val, NULL );
    5282}
     
    5686//=============================================================================================
    5787
    58 void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) {
     88void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {
    5989        this->thrd = thrd;
    6090        this->alarm = alarm;
     
    6595}
    6696
    67 void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) {
     97void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {
    6898        this->proc = proc;
    6999        this->alarm = alarm;
     
    153183
    154184void register_self( alarm_node_t * this ) {
     185        alarm_list_t * alarms = &event_kernel->alarms;
     186
    155187        disable_interrupts();
    156         verify( !systemProcessor->pending_alarm );
    157         lock( &systemProcessor->alarm_lock DEBUG_CTX2 );
     188        lock( &event_kernel->lock DEBUG_CTX2 );
    158189        {
    159                 verify( validate( &systemProcessor->alarms ) );
    160                 bool first = !systemProcessor->alarms.head;
    161 
    162                 insert( &systemProcessor->alarms, this );
    163                 if( systemProcessor->pending_alarm ) {
    164                         tick_preemption();
     190                verify( validate( alarms ) );
     191                bool first = !alarms->head;
     192
     193                insert( alarms, this );
     194                if( first ) {
     195                        __kernel_set_timer( alarms->head->alarm - __kernel_get_time() );
    165196                }
    166                 if( first ) {
    167                         __kernel_set_timer( systemProcessor->alarms.head->alarm - __kernel_get_time() );
    168                 }
    169         }
    170         unlock( &systemProcessor->alarm_lock );
     197        }
     198        unlock( &event_kernel->lock );
    171199        this->set = true;
    172200        enable_interrupts( DEBUG_CTX );
     
    174202
    175203void unregister_self( alarm_node_t * this ) {
    176         // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : unregister %p start\n", this );
    177204        disable_interrupts();
    178         lock( &systemProcessor->alarm_lock DEBUG_CTX2 );
     205        lock( &event_kernel->lock DEBUG_CTX2 );
    179206        {
    180                 verify( validate( &systemProcessor->alarms ) );
    181                 remove( &systemProcessor->alarms, this );
    182         }
    183         unlock( &systemProcessor->alarm_lock );
     207                verify( validate( &event_kernel->alarms ) );
     208                remove( &event_kernel->alarms, this );
     209        }
     210        unlock( &event_kernel->lock );
    184211        enable_interrupts( DEBUG_CTX );
    185212        this->set = false;
    186         // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Kernel : unregister %p end\n", this );
    187 }
     213}
     214
     215// Local Variables: //
     216// mode: c //
     217// tab-width: 4 //
     218// End: //
  • src/libcfa/concurrency/alarm.h

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Fri Jun 2 11:31:25 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:59:27 2017
     13// Update Count     : 3
    1514//
    1615
    17 #ifndef ALARM_H
    18 #define ALARM_H
     16#pragma once
    1917
    2018#include <stdbool.h>
     19#include <stdint.h>
    2120
    22 #include "assert"
    23 
    24 typedef unsigned long int __cfa_time_t;
     21#include <assert.h>
    2522
    2623struct thread_desc;
    2724struct processor;
    2825
     26struct timespec;
     27struct itimerval;
     28
     29//=============================================================================================
     30// time type
     31//=============================================================================================
     32
     33struct __cfa_time_t {
     34        uint64_t val;
     35};
     36
     37// ctors
     38void ?{}( __cfa_time_t * this );
     39void ?{}( __cfa_time_t * this, zero_t zero );
     40void ?{}( __cfa_time_t * this, timespec * curr );
     41void ?{}( itimerval * this, __cfa_time_t * alarm );
     42
     43__cfa_time_t ?=?( __cfa_time_t * this, zero_t rhs );
     44
     45// logical ops
     46static inline bool ?==?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val == rhs.val; }
     47static inline bool ?!=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val != rhs.val; }
     48static inline bool ?>? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val >  rhs.val; }
     49static inline bool ?<? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val <  rhs.val; }
     50static inline bool ?>=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val >= rhs.val; }
     51static inline bool ?<=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val <= rhs.val; }
     52
     53static inline bool ?==?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val == rhs; }
     54static inline bool ?!=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val != rhs; }
     55static inline bool ?>? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val >  rhs; }
     56static inline bool ?<? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val <  rhs; }
     57static inline bool ?>=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val >= rhs; }
     58static inline bool ?<=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val <= rhs; }
     59
     60// addition/substract
     61static inline __cfa_time_t ?+?( __cfa_time_t lhs, __cfa_time_t rhs ) {
     62        __cfa_time_t ret;
     63        ret.val = lhs.val + rhs.val;
     64        return ret;
     65}
     66
     67static inline __cfa_time_t ?-?( __cfa_time_t lhs, __cfa_time_t rhs ) {
     68        __cfa_time_t ret;
     69        ret.val = lhs.val - rhs.val;
     70        return ret;
     71}
     72
     73__cfa_time_t from_s ( uint64_t );
     74__cfa_time_t from_ms( uint64_t );
     75__cfa_time_t from_us( uint64_t );
     76__cfa_time_t from_ns( uint64_t );
     77
     78extern __cfa_time_t zero_time;
     79
    2980//=============================================================================================
    3081// Clock logic
    3182//=============================================================================================
    32 
    33 #define TIMEGRAN 1_000_000_000L                         // nanosecond granularity, except for timeval
    3483
    3584__cfa_time_t __kernel_get_time();
     
    56105typedef alarm_node_t ** __alarm_it_t;
    57106
    58 void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = 0, __cfa_time_t period = 0 );
    59 void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 );
     107void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
     108void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
    60109void ^?{}( alarm_node_t * this );
    61110
     
    76125void unregister_self( alarm_node_t * this );
    77126
    78 #endif
    79 
    80127// Local Variables: //
    81 // mode: CFA //
     128// mode: c //
    82129// tab-width: 6 //
    83130// End: //
  • src/libcfa/concurrency/coroutine

    re0a653d r33218c6  
    1010// Author           : Thierry Delisle
    1111// Created On       : Mon Nov 28 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : Mon Nov 28 12:27:26 2016
    14 // Update Count     : 0
     12// Last Modified By : Peter A. Buhr
     13// Last Modified On : Sat Jul 22 09:57:17 2017
     14// Update Count     : 2
    1515//
    1616
    17 #ifndef COROUTINES_H
    18 #define COROUTINES_H
     17#pragma once
    1918
    20 #include "assert"
     19#include <assert.h>
    2120#include "invoke.h"
    2221
     
    6362
    6463// Get current coroutine
    65 extern volatile thread_local coroutine_desc * this_coroutine;
     64extern thread_local coroutine_desc * volatile this_coroutine;
    6665
    6766// Private wrappers for context switch and stack creation
     
    129128}
    130129
    131 #endif //COROUTINES_H
    132 
    133130// Local Variables: //
    134131// mode: c //
  • src/libcfa/concurrency/coroutine.c

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Mon Nov 28 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : Mon Nov 28 12:27:26 2016
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:34:57 2017
     13// Update Count     : 1
    1514//
    1615
     
    2625}
    2726
    28 #include "kernel"
    29 #include "libhdr.h"
     27#include "kernel_private.h"
    3028
    3129#define __CFA_INVOKE_PRIVATE__
    3230#include "invoke.h"
    3331
    34 extern volatile thread_local processor * this_processor;
    3532
    3633//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/invoke.c

    re0a653d r33218c6  
    1 //                              -*- Mode: C -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Jan 17 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:28:33 2017
     13// Update Count     : 1
    1514//
    1615
     
    142141#endif
    143142}
     143
     144// Local Variables: //
     145// mode: c //
     146// tab-width: 4 //
     147// End: //
  • src/libcfa/concurrency/invoke.h

    re0a653d r33218c6  
    1 //                              -*- Mode: C -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Jan 17 12:27:26 2016
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:28:56 2017
     13// Update Count     : 1
    1514//
    1615
     
    130129}
    131130#endif
     131
     132// Local Variables: //
     133// mode: c //
     134// tab-width: 4 //
     135// End: //
  • src/libcfa/concurrency/kernel

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Jan 17 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:58:39 2017
     13// Update Count     : 2
    1514//
    1615
    17 #ifndef KERNEL_H
    18 #define KERNEL_H
     16#pragma once
    1917
    2018#include <stdbool.h>
     
    2826//-----------------------------------------------------------------------------
    2927// Locks
    30 bool try_lock  ( spinlock * DEBUG_CTX_PARAM2 );
    31 void lock      ( spinlock * DEBUG_CTX_PARAM2 );
    32 void lock_yield( spinlock * DEBUG_CTX_PARAM2 );
    33 void unlock    ( spinlock * );
     28void lock      ( spinlock * DEBUG_CTX_PARAM2 );       // Lock the spinlock, spin if already acquired
     29void lock_yield( spinlock * DEBUG_CTX_PARAM2 );       // Lock the spinlock, yield repeatedly if already acquired
     30bool try_lock  ( spinlock * DEBUG_CTX_PARAM2 );       // Lock the spinlock, return false if already acquired
     31void unlock    ( spinlock * );                        // Unlock the spinlock
    3432
    3533struct semaphore {
     
    4846// Cluster
    4947struct cluster {
    50         __thread_queue_t ready_queue;
    51         spinlock lock;
     48        spinlock ready_queue_lock;                      // Ready queue locks
     49        __thread_queue_t ready_queue;                   // Ready queue for threads
     50        unsigned long long int preemption;              // Preemption rate on this cluster
    5251};
    5352
     
    7675static inline void ^?{}(FinishAction * this) {}
    7776
     77// Processor
     78// Wrapper around kernel threads
    7879struct processor {
    79         struct processorCtx_t * runner;
    80         cluster * cltr;
    81         pthread_t kernel_thread;
     80        // Main state
     81        struct processorCtx_t * runner;                 // Coroutine ctx who does keeps the state of the processor
     82        cluster * cltr;                                 // Cluster from which to get threads
     83        pthread_t kernel_thread;                        // Handle to pthreads
    8284
    83         semaphore terminated;
    84         volatile bool is_terminated;
     85        // Termination
     86        volatile bool do_terminate;                     // Set to true to notify the processor should terminate
     87        semaphore terminated;                           // Termination synchronisation
    8588
    86         struct FinishAction finish;
     89        // RunThread data
     90        struct FinishAction finish;                     // Action to do after a thread is ran
    8791
    88         struct alarm_node_t * preemption_alarm;
    89         unsigned int preemption;
     92        // Preemption data
     93        struct alarm_node_t * preemption_alarm;         // Node which is added in the discrete event simulaiton
     94        bool pending_preemption;                        // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible
    9095
    91         bool pending_preemption;
    92 
    93         char * last_enable;
     96#ifdef __CFA_DEBUG__
     97        char * last_enable;                             // Last function to enable preemption on this processor
     98#endif
    9499};
    95100
     
    98103void ^?{}(processor * this);
    99104
    100 #endif //KERNEL_H
    101 
    102105// Local Variables: //
    103 // mode: CFA //
    104 // tab-width: 6 //
     106// mode: c //
     107// tab-width: 4 //
    105108// End: //
  • src/libcfa/concurrency/kernel.c

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Jan 17 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:33:18 2017
     13// Update Count     : 2
    1514//
    1615
     
    4241//-----------------------------------------------------------------------------
    4342// Kernel storage
    44 #define KERNEL_STORAGE(T,X) static char X##Storage[sizeof(T)]
    45 
    46 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
    47 KERNEL_STORAGE(cluster, systemCluster);
    48 KERNEL_STORAGE(system_proc_t, systemProcessor);
    49 KERNEL_STORAGE(thread_desc, mainThread);
     43KERNEL_STORAGE(cluster,           mainCluster);
     44KERNEL_STORAGE(processor,         mainProcessor);
     45KERNEL_STORAGE(processorCtx_t,    mainProcessorCtx);
     46KERNEL_STORAGE(thread_desc,       mainThread);
    5047KERNEL_STORAGE(machine_context_t, mainThreadCtx);
    5148
    52 cluster * systemCluster;
    53 system_proc_t * systemProcessor;
     49cluster *     mainCluster;
     50processor *   mainProcessor;
    5451thread_desc * mainThread;
    5552
     
    5754// Global state
    5855
    59 volatile thread_local processor * this_processor;
    60 volatile thread_local coroutine_desc * this_coroutine;
    61 volatile thread_local thread_desc * this_thread;
     56thread_local coroutine_desc * volatile this_coroutine;
     57thread_local thread_desc *    volatile this_thread;
     58thread_local processor *      volatile this_processor;
     59
     60volatile thread_local bool preemption_in_progress = 0;
    6261volatile thread_local unsigned short disable_preempt_count = 1;
    6362
     
    8483
    8584        this->limit = (void *)(((intptr_t)this->base) - this->size);
    86         this->context = &mainThreadCtxStorage;
     85        this->context = &storage_mainThreadCtx;
    8786        this->top = this->base;
    8887}
     
    124123
    125124void ?{}(processor * this) {
    126         this{ systemCluster };
     125        this{ mainCluster };
    127126}
    128127
     
    130129        this->cltr = cltr;
    131130        (&this->terminated){ 0 };
    132         this->is_terminated = false;
     131        this->do_terminate = false;
    133132        this->preemption_alarm = NULL;
    134         this->preemption = default_preemption();
    135133        this->pending_preemption = false;
    136134
     
    141139        this->cltr = cltr;
    142140        (&this->terminated){ 0 };
    143         this->is_terminated = false;
     141        this->do_terminate = false;
    144142        this->preemption_alarm = NULL;
    145         this->preemption = default_preemption();
    146143        this->pending_preemption = false;
    147144        this->kernel_thread = pthread_self();
    148145
    149146        this->runner = runner;
    150         LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
     147        LIB_DEBUG_PRINT_SAFE("Kernel : constructing main processor context %p\n", runner);
    151148        runner{ this };
    152149}
    153150
    154 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    155 
    156 void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
    157         (&this->alarms){};
    158         (&this->alarm_lock){};
    159         this->pending_alarm = false;
    160 
    161         (&this->proc){ cltr, runner };
    162 
    163         verify( validate( &this->alarms ) );
    164 }
    165 
    166151void ^?{}(processor * this) {
    167         if( ! this->is_terminated ) {
     152        if( ! this->do_terminate ) {
    168153                LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", this);
    169                 this->is_terminated = true;
     154                this->do_terminate = true;
    170155                P( &this->terminated );
    171156                pthread_join( this->kernel_thread, NULL );
     
    175160void ?{}(cluster * this) {
    176161        ( &this->ready_queue ){};
    177         ( &this->lock ){};
     162        ( &this->ready_queue_lock ){};
     163
     164        this->preemption = default_preemption();
    178165}
    179166
     
    198185
    199186                thread_desc * readyThread = NULL;
    200                 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
     187                for( unsigned int spin_count = 0; ! this->do_terminate; spin_count++ )
    201188                {
    202189                        readyThread = nextThread( this->cltr );
     
    342329        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    343330
    344         lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 );
    345         append( &systemProcessor->proc.cltr->ready_queue, thrd );
    346         unlock( &systemProcessor->proc.cltr->lock );
     331        lock(   &this_processor->cltr->ready_queue_lock DEBUG_CTX2 );
     332        append( &this_processor->cltr->ready_queue, thrd );
     333        unlock( &this_processor->cltr->ready_queue_lock );
    347334
    348335        verify( disable_preempt_count > 0 );
     
    351338thread_desc * nextThread(cluster * this) {
    352339        verify( disable_preempt_count > 0 );
    353         lock( &this->lock DEBUG_CTX2 );
     340        lock( &this->ready_queue_lock DEBUG_CTX2 );
    354341        thread_desc * head = pop_head( &this->ready_queue );
    355         unlock( &this->lock );
     342        unlock( &this->ready_queue_lock );
    356343        verify( disable_preempt_count > 0 );
    357344        return head;
     
    451438        // Start by initializing the main thread
    452439        // SKULLDUGGERY: the mainThread steals the process main thread
    453         // which will then be scheduled by the systemProcessor normally
    454         mainThread = (thread_desc *)&mainThreadStorage;
     440        // which will then be scheduled by the mainProcessor normally
     441        mainThread = (thread_desc *)&storage_mainThread;
    455442        current_stack_info_t info;
    456443        mainThread{ &info };
     
    458445        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    459446
    460         // Initialize the system cluster
    461         systemCluster = (cluster *)&systemClusterStorage;
    462         systemCluster{};
    463 
    464         LIB_DEBUG_PRINT_SAFE("Kernel : System cluster ready\n");
    465 
    466         // Initialize the system processor and the system processor ctx
     447        // Initialize the main cluster
     448        mainCluster = (cluster *)&storage_mainCluster;
     449        mainCluster{};
     450
     451        LIB_DEBUG_PRINT_SAFE("Kernel : main cluster ready\n");
     452
     453        // Initialize the main processor and the main processor ctx
    467454        // (the coroutine that contains the processing control flow)
    468         systemProcessor = (system_proc_t *)&systemProcessorStorage;
    469         systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtxStorage };
    470 
    471         // Add the main thread to the ready queue
    472         // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    473         ScheduleThread(mainThread);
     455        mainProcessor = (processor *)&storage_mainProcessor;
     456        mainProcessor{ mainCluster, (processorCtx_t *)&storage_mainProcessorCtx };
    474457
    475458        //initialize the global state variables
    476         this_processor = &systemProcessor->proc;
     459        this_processor = mainProcessor;
    477460        this_thread = mainThread;
    478461        this_coroutine = &mainThread->cor;
    479         disable_preempt_count = 1;
    480462
    481463        // Enable preemption
    482464        kernel_start_preemption();
    483465
    484         // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
     466        // Add the main thread to the ready queue
     467        // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
     468        ScheduleThread(mainThread);
     469
     470        // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
    485471        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    486472        // mainThread is on the ready queue when this call is made.
    487         resume( systemProcessor->proc.runner );
     473        resume( mainProcessor->runner );
    488474
    489475
     
    500486        disable_interrupts();
    501487
    502         // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     488        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
    503489        // When its coroutine terminates, it return control to the mainThread
    504490        // which is currently here
    505         systemProcessor->proc.is_terminated = true;
     491        mainProcessor->do_terminate = true;
    506492        suspend();
    507493
     
    511497        kernel_stop_preemption();
    512498
    513         // Destroy the system processor and its context in reverse order of construction
     499        // Destroy the main processor and its context in reverse order of construction
    514500        // These were manually constructed so we need manually destroy them
    515         ^(systemProcessor->proc.runner){};
    516         ^(systemProcessor){};
     501        ^(mainProcessor->runner){};
     502        ^(mainProcessor){};
    517503
    518504        // Final step, destroy the main thread since it is no longer needed
     
    698684        return top;
    699685}
     686
    700687// Local Variables: //
    701688// mode: c //
  • src/libcfa/concurrency/kernel_private.h

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Mon Feb 13 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:58:09 2017
     13// Update Count     : 2
    1514//
    1615
    17 #ifndef KERNEL_PRIVATE_H
    18 #define KERNEL_PRIVATE_H
     16#pragma once
    1917
    2018#include "libhdr.h"
     
    3129extern "C" {
    3230        void disable_interrupts();
    33         void enable_interrupts_noRF();
     31        void enable_interrupts_noPoll();
    3432        void enable_interrupts( DEBUG_CTX_PARAM );
    3533}
     
    4543thread_desc * nextThread(cluster * this);
    4644
     45//Block current thread and release/wake-up the following resources
    4746void BlockInternal(void);
    4847void BlockInternal(spinlock * lock);
     
    6564void spin(processor * this, unsigned int * spin_count);
    6665
    67 struct system_proc_t {
    68         processor proc;
    69 
     66struct event_kernel_t {
    7067        alarm_list_t alarms;
    71         spinlock alarm_lock;
    72 
    73         bool pending_alarm;
     68        spinlock lock;
    7469};
    7570
    76 extern cluster * systemCluster;
    77 extern system_proc_t * systemProcessor;
    78 extern volatile thread_local processor * this_processor;
    79 extern volatile thread_local coroutine_desc * this_coroutine;
    80 extern volatile thread_local thread_desc * this_thread;
     71extern event_kernel_t * event_kernel;
     72
     73extern thread_local coroutine_desc * volatile this_coroutine;
     74extern thread_local thread_desc *    volatile this_thread;
     75extern thread_local processor *      volatile this_processor;
     76
     77extern volatile thread_local bool preemption_in_progress;
    8178extern volatile thread_local unsigned short disable_preempt_count;
    8279
     
    9087extern void ThreadCtxSwitch(coroutine_desc * src, coroutine_desc * dst);
    9188
    92 #endif //KERNEL_PRIVATE_H
     89//-----------------------------------------------------------------------------
     90// Utils
     91#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
    9392
    9493// Local Variables: //
  • src/libcfa/concurrency/monitor

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Thd Feb 23 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:59:01 2017
     13// Update Count     : 3
    1514//
    1615
    17 #ifndef MONITOR_H
    18 #define MONITOR_H
     16#pragma once
    1917
    2018#include <stddef.h>
    2119
    22 #include "assert"
     20#include <assert.h>
    2321#include "invoke.h"
    2422#include "stdlib"
     
    9997void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) );
    10098
    101 #endif //MONITOR_H
     99// Local Variables: //
     100// mode: c //
     101// tab-width: 4 //
     102// End: //
  • src/libcfa/concurrency/monitor.c

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Thd Feb 23 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:37:11 2017
     13// Update Count     : 1
    1514//
    1615
     
    528527        return head;
    529528}
     529
     530// Local Variables: //
     531// mode: c //
     532// tab-width: 4 //
     533// End: //
  • src/libcfa/concurrency/preemption.c

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Mon Jun 5 14:20:42 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:36:05 2017
     13// Update Count     : 2
    1514//
    1615
     
    3433#endif
    3534
     35//TODO move to defaults
    3636#define __CFA_DEFAULT_PREEMPTION__ 10000
    3737
     38//TODO move to defaults
    3839__attribute__((weak)) unsigned int default_preemption() {
    3940        return __CFA_DEFAULT_PREEMPTION__;
    4041}
    4142
     43// Short hands for signal context information
    4244#define __CFA_SIGCXT__ ucontext_t *
    4345#define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt
    4446
     47// FwdDeclarations : timeout handlers
    4548static void preempt( processor   * this );
    4649static void timeout( thread_desc * this );
    4750
     51// FwdDeclarations : Signal handlers
    4852void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
    49 void sigHandler_alarm    ( __CFA_SIGPARMS__ );
    5053void sigHandler_segv     ( __CFA_SIGPARMS__ );
    5154void sigHandler_abort    ( __CFA_SIGPARMS__ );
    5255
     56// FwdDeclarations : sigaction wrapper
    5357static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
    54 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    55 
     58
     59// FwdDeclarations : alarm thread main
     60void * alarm_loop( __attribute__((unused)) void * args );
     61
     62// Machine specific register name
    5663#ifdef __x86_64__
    5764#define CFA_REG_IP REG_RIP
     
    6067#endif
    6168
     69KERNEL_STORAGE(event_kernel_t, event_kernel);         // private storage for event kernel
     70event_kernel_t * event_kernel;                        // kernel public handle to even kernel
     71static pthread_t alarm_thread;                        // pthread handle to alarm thread
     72
     73void ?{}(event_kernel_t * this) {
     74        (&this->alarms){};
     75        (&this->lock){};
     76}
    6277
    6378//=============================================================================================
     
    6580//=============================================================================================
    6681
     82// Get next expired node
     83static inline alarm_node_t * get_expired( alarm_list_t * alarms, __cfa_time_t currtime ) {
     84        if( !alarms->head ) return NULL;                          // If no alarms return null
     85        if( alarms->head->alarm >= currtime ) return NULL;        // If alarms head not expired return null
     86        return pop(alarms);                                       // Otherwise just pop head
     87}
     88
     89// Tick one frame of the Discrete Event Simulation for alarms
    6790void tick_preemption() {
    68         // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ticking preemption\n" );
    69 
    70         alarm_list_t * alarms = &systemProcessor->alarms;
    71         __cfa_time_t currtime = __kernel_get_time();
    72         while( alarms->head && alarms->head->alarm < currtime ) {
    73                 alarm_node_t * node = pop(alarms);
    74                 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking %p\n", node );
    75 
     91        alarm_node_t * node = NULL;                     // Used in the while loop but cannot be declared in the while condition
     92        alarm_list_t * alarms = &event_kernel->alarms;  // Local copy for ease of reading
     93        __cfa_time_t currtime = __kernel_get_time();    // Check current time once so we everything "happens at once"
     94
     95        //Loop throught every thing expired
     96        while( node = get_expired( alarms, currtime ) ) {
     97
     98                // Check if this is a kernel
    7699                if( node->kernel_alarm ) {
    77100                        preempt( node->proc );
     
    81104                }
    82105
    83                 verify( validate( alarms ) );
    84 
    85                 if( node->period > 0 ) {
    86                         node->alarm = currtime + node->period;
    87                         insert( alarms, node );
     106                // Check if this is a periodic alarm
     107                __cfa_time_t period = node->period;
     108                if( period > 0 ) {
     109                        node->alarm = currtime + period;    // Alarm is periodic, add currtime to it (used cached current time)
     110                        insert( alarms, node );             // Reinsert the node for the next time it triggers
    88111                }
    89112                else {
    90                         node->set = false;
    91                 }
    92         }
    93 
    94         if( alarms->head ) {
    95                 __kernel_set_timer( alarms->head->alarm - currtime );
    96         }
    97 
    98         verify( validate( alarms ) );
    99         // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking preemption done\n" );
    100 }
    101 
     113                        node->set = false;                  // Node is one-shot, just mark it as not pending
     114                }
     115        }
     116
     117        // If there are still alarms pending, reset the timer
     118        if( alarms->head ) { __kernel_set_timer( alarms->head->alarm - currtime ); }
     119}
     120
     121// Update the preemption of a processor and notify interested parties
    102122void update_preemption( processor * this, __cfa_time_t duration ) {
    103         LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p updating preemption to %lu\n", this, duration );
    104 
    105123        alarm_node_t * alarm = this->preemption_alarm;
    106         duration *= 1000;
    107124
    108125        // Alarms need to be enabled
     
    134151
    135152extern "C" {
     153        // Disable interrupts by incrementing the counter
    136154        void disable_interrupts() {
    137155                __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 
     156                verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
     157        }
     158
     159        // Enable interrupts by decrementing the counter
     160        // If counter reaches 0, execute any pending CtxSwitch
    147161        void enable_interrupts( DEBUG_CTX_PARAM ) {
    148                 processor * proc   = this_processor;
    149                 thread_desc * thrd = this_thread;
     162                processor * proc   = this_processor;      // Cache the processor now since interrupts can start happening after the atomic add
     163                thread_desc * thrd = this_thread;         // Cache the thread now since interrupts can start happening after the atomic add
     164
    150165                unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    151                 verify( prev != (unsigned short) 0 );
     166                verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
     167
     168                // Check if we need to prempt the thread because an interrupt was missed
    152169                if( prev == 1 && proc->pending_preemption ) {
    153170                        proc->pending_preemption = false;
     
    155172                }
    156173
     174                // For debugging purposes : keep track of the last person to enable the interrupts
    157175                LIB_DEBUG_DO( proc->last_enable = caller; )
    158176        }
    159 }
    160 
     177
     178        // Disable interrupts by incrementint the counter
     179        // Don't execute any pending CtxSwitch even if counter reaches 0
     180        void enable_interrupts_noPoll() {
     181                __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     182                verify( prev != 0u );                     // If this triggers someone is enabled already enabled interrupts
     183        }
     184}
     185
     186// sigprocmask wrapper : unblock a single signal
    161187static inline void signal_unblock( int sig ) {
    162188        sigset_t mask;
     
    169195}
    170196
     197// sigprocmask wrapper : block a single signal
    171198static inline void signal_block( int sig ) {
    172199        sigset_t mask;
     
    179206}
    180207
    181 static inline bool preemption_ready() {
    182         return disable_preempt_count == 0;
    183 }
    184 
    185 static inline void defer_ctxSwitch() {
    186         this_processor->pending_preemption = true;
    187 }
    188 
    189 static inline void defer_alarm() {
    190         systemProcessor->pending_alarm = true;
    191 }
    192 
     208// kill wrapper : signal a processor
    193209static void preempt( processor * this ) {
    194210        pthread_kill( this->kernel_thread, SIGUSR1 );
    195211}
    196212
     213// reserved for future use
    197214static void timeout( thread_desc * this ) {
    198215        //TODO : implement waking threads
    199216}
    200217
     218
     219// Check if a CtxSwitch signal handler shoud defer
     220// If true  : preemption is safe
     221// If false : preemption is unsafe and marked as pending
     222static inline bool preemption_ready() {
     223        bool ready = disable_preempt_count == 0 && !preemption_in_progress; // Check if preemption is safe
     224        this_processor->pending_preemption = !ready;                        // Adjust the pending flag accordingly
     225        return ready;
     226}
     227
    201228//=============================================================================================
    202229// Kernel Signal Startup/Shutdown logic
    203230//=============================================================================================
    204231
    205 static pthread_t alarm_thread;
    206 void * alarm_loop( __attribute__((unused)) void * args );
    207 
     232// Startup routine to activate preemption
     233// Called from kernel_startup
    208234void kernel_start_preemption() {
    209235        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 );
     236
     237        // Start with preemption disabled until ready
     238        disable_preempt_count = 1;
     239
     240        // Initialize the event kernel
     241        event_kernel = (event_kernel_t *)&storage_event_kernel;
     242        event_kernel{};
     243
     244        // Setup proper signal handlers
     245        __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO );         // CtxSwitch handler
     246        // __kernel_sigaction( SIGSEGV, sigHandler_segv     , SA_SIGINFO );      // Failure handler
     247        // __kernel_sigaction( SIGBUS , sigHandler_segv     , SA_SIGINFO );      // Failure handler
    213248
    214249        signal_block( SIGALRM );
     
    217252}
    218253
     254// Shutdown routine to deactivate preemption
     255// Called from kernel_shutdown
    219256void kernel_stop_preemption() {
     257        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopping\n");
     258
     259        // Block all signals since we are already shutting down
    220260        sigset_t mask;
    221261        sigfillset( &mask );
    222262        sigprocmask( SIG_BLOCK, &mask, NULL );
    223263
    224         pthread_kill( alarm_thread, SIGINT );
     264        // Notify the alarm thread of the shutdown
     265        sigval val = { 1 };
     266        pthread_sigqueue( alarm_thread, SIGALRM, val );
     267
     268        // Wait for the preemption thread to finish
    225269        pthread_join( alarm_thread, NULL );
     270
     271        // Preemption is now fully stopped
     272
    226273        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
    227274}
    228275
     276// Raii ctor/dtor for the preemption_scope
     277// Used by thread to control when they want to receive preemption signals
    229278void ?{}( preemption_scope * this, processor * proc ) {
    230         (&this->alarm){ proc };
     279        (&this->alarm){ proc, zero_time, zero_time };
    231280        this->proc = proc;
    232281        this->proc->preemption_alarm = &this->alarm;
    233         update_preemption( this->proc, this->proc->preemption );
     282
     283        update_preemption( this->proc, from_us(this->proc->cltr->preemption) );
    234284}
    235285
     
    237287        disable_interrupts();
    238288
    239         update_preemption( this->proc, 0 );
     289        update_preemption( this->proc, zero_time );
    240290}
    241291
     
    244294//=============================================================================================
    245295
     296// Context switch signal handler
     297// Receives SIGUSR1 signal and causes the current thread to yield
    246298void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    247299        LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
    248         if( preemption_ready() ) {
    249                 signal_unblock( SIGUSR1 );
    250                 BlockInternal( (thread_desc*)this_thread );
    251         }
    252         else {
    253                 defer_ctxSwitch();
    254         }
    255 }
    256 
    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 
     300
     301        // Check if it is safe to preempt here
     302        if( !preemption_ready() ) { return; }
     303
     304        preemption_in_progress = true;                      // Sync flag : prevent recursive calls to the signal handler
     305        signal_unblock( SIGUSR1 );                          // We are about to CtxSwitch out of the signal handler, let other handlers in
     306        preemption_in_progress = false;                     // Clear the in progress flag
     307
     308        // Preemption can occur here
     309
     310        BlockInternal( (thread_desc*)this_thread );         // Do the actual CtxSwitch
     311}
     312
     313// Main of the alarm thread
     314// Waits on SIGALRM and send SIGUSR1 to whom ever needs it
    279315void * alarm_loop( __attribute__((unused)) void * args ) {
     316        // Block sigalrms to control when they arrive
    280317        sigset_t mask;
    281318        sigemptyset( &mask );
    282319        sigaddset( &mask, SIGALRM );
    283         sigaddset( &mask, SIGUSR2 );
    284         sigaddset( &mask, SIGINT  );
    285320
    286321        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     
    288323        }
    289324
     325        // Main loop
    290326        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 
     327                // Wait for a sigalrm
     328                siginfo_t info;
     329                int sig = sigwaitinfo( &mask, &info );
     330
     331                // If another signal arrived something went wrong
     332                assertf(sig == SIGALRM, "Kernel Internal Error, sigwait: Unexpected signal %d (%d : %d)\n", sig, info.si_code, info.si_value.sival_int);
     333
     334                LIB_DEBUG_PRINT_SAFE("Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );
     335                // Switch on the code (a.k.a. the sender) to
     336                switch( info.si_code )
     337                {
     338                // Timers can apparently be marked as sent for the kernel
     339                // In either case, tick preemption
     340                case SI_TIMER:
     341                case SI_KERNEL:
     342                        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread tick\n");
     343                        lock( &event_kernel->lock DEBUG_CTX2 );
     344                        tick_preemption();
     345                        unlock( &event_kernel->lock );
     346                        break;
     347                // Signal was not sent by the kernel but by an other thread
     348                case SI_QUEUE:
     349                        // For now, other thread only signal the alarm thread to shut it down
     350                        // If this needs to change use info.si_value and handle the case here
     351                        goto EXIT;
     352                }
     353        }
     354
     355EXIT:
     356        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread stopping\n");
     357        return NULL;
     358}
     359
     360// Sigaction wrapper : register an signal handler
    316361static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
    317362        struct sigaction act;
     
    329374}
    330375
    331 typedef void (*sa_handler_t)(int);
    332 
     376// Sigaction wrapper : restore default handler
    333377static void __kernel_sigdefault( int sig ) {
    334378        struct sigaction act;
    335379
    336         // act.sa_handler = SIG_DFL;
     380        act.sa_handler = SIG_DFL;
    337381        act.sa_flags = 0;
    338382        sigemptyset( &act.sa_mask );
     
    442486//      raise( SIGABRT );
    443487// }
     488
     489// Local Variables: //
     490// mode: c //
     491// tab-width: 4 //
     492// End: //
  • src/libcfa/concurrency/preemption.h

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Mon Jun 5 14:20:42 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:34:25 2017
     13// Update Count     : 1
    1514//
    1615
    17 #ifndef PREEMPTION_H
    18 #define PREEMPTION_H
     16#pragma once
    1917
    2018#include "alarm.h"
     
    3533void ^?{}( preemption_scope * this );
    3634
    37 #endif //PREEMPTION_H
     35// Local Variables: //
     36// mode: c //
     37// tab-width: 4 //
     38// End: //
  • src/libcfa/concurrency/thread

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Jan 17 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:59:40 2017
     13// Update Count     : 3
    1514//
    1615
    17 #ifndef THREADS_H
    18 #define THREADS_H
     16#pragma once
    1917
    20 #include "assert"
     18#include <assert.h>
    2119#include "invoke.h"
    2220
     
    5452}
    5553
    56 extern volatile thread_local thread_desc * this_thread;
     54extern thread_local thread_desc * volatile this_thread;
    5755
    5856forall( dtype T | is_thread(T) )
     
    8482void yield( unsigned times );
    8583
    86 #endif //THREADS_H
    87 
    8884// Local Variables: //
    8985// mode: c //
  • src/libcfa/concurrency/thread.c

    re0a653d r33218c6  
    1 //                              -*- Mode: CFA -*-
    21//
    32// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     
    109// Author           : Thierry Delisle
    1110// Created On       : Tue Jan 17 12:27:26 2017
    12 // Last Modified By : Thierry Delisle
    13 // Last Modified On : --
    14 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:34:46 2017
     13// Update Count     : 1
    1514//
    1615
     
    8786
    8887void yield( void ) {
    89         BlockInternal( (thread_desc *)this_thread );
     88        BlockInternal( this_thread );
    9089}
    9190
Note: See TracChangeset for help on using the changeset viewer.