Ignore:
Timestamp:
Aug 14, 2017, 2:03:39 PM (5 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, 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, resolv-new, with_gc
Children:
74b007ba
Parents:
fd344aa (diff), 54cd58b (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' into references

Location:
src/libcfa/concurrency
Files:
17 edited

Legend:

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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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
    6260volatile thread_local bool preemption_in_progress = 0;
    6361volatile thread_local unsigned short disable_preempt_count = 1;
     
    8583
    8684        this.limit = (void *)(((intptr_t)this.base) - this.size);
    87         this.context = &mainThreadCtxStorage;
     85        this.context = &storage_mainThreadCtx;
    8886        this.top = this.base;
    8987}
     
    125123
    126124void ?{}(processor & this) {
    127         this{ systemCluster };
     125        this{ mainCluster };
    128126}
    129127
     
    131129        this.cltr = cltr;
    132130        (this.terminated){ 0 };
    133         this.is_terminated = false;
     131        this.do_terminate = false;
    134132        this.preemption_alarm = NULL;
    135         this.preemption = default_preemption();
    136133        this.pending_preemption = false;
    137134
     
    142139        this.cltr = cltr;
    143140        (this.terminated){ 0 };
    144         this.is_terminated = false;
     141        this.do_terminate = false;
    145142        this.preemption_alarm = NULL;
    146         this.preemption = default_preemption();
    147143        this.pending_preemption = false;
    148144        this.kernel_thread = pthread_self();
    149145
    150146        this.runner = &runner;
    151         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);
    152148        runner{ &this };
    153149}
    154150
    155 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    156 
    157 void ?{}(system_proc_t & this, cluster * cltr, processorCtx_t & runner) {
    158         (this.alarms){};
    159         (this.alarm_lock){};
    160         this.pending_alarm = false;
    161 
    162         (this.proc){ cltr, runner };
    163 
    164         verify( validate( &this.alarms ) );
    165 }
    166 
    167151void ^?{}(processor & this) {
    168         if( ! this.is_terminated ) {
     152        if( ! this.do_terminate ) {
    169153                LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", &this);
    170                 this.is_terminated = true;
     154                this.do_terminate = true;
    171155                P( &this.terminated );
    172156                pthread_join( this.kernel_thread, NULL );
     
    176160void ?{}(cluster & this) {
    177161        ( this.ready_queue ){};
    178         ( this.lock ){};
     162        ( this.ready_queue_lock ){};
     163
     164        this.preemption = default_preemption();
    179165}
    180166
     
    199185
    200186                thread_desc * readyThread = NULL;
    201                 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
     187                for( unsigned int spin_count = 0; ! this->do_terminate; spin_count++ )
    202188                {
    203189                        readyThread = nextThread( this->cltr );
     
    343329        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    344330
    345         lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 );
    346         append( &systemProcessor->proc.cltr->ready_queue, thrd );
    347         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 );
    348334
    349335        verify( disable_preempt_count > 0 );
     
    352338thread_desc * nextThread(cluster * this) {
    353339        verify( disable_preempt_count > 0 );
    354         lock( &this->lock DEBUG_CTX2 );
     340        lock( &this->ready_queue_lock DEBUG_CTX2 );
    355341        thread_desc * head = pop_head( &this->ready_queue );
    356         unlock( &this->lock );
     342        unlock( &this->ready_queue_lock );
    357343        verify( disable_preempt_count > 0 );
    358344        return head;
     
    452438        // Start by initializing the main thread
    453439        // SKULLDUGGERY: the mainThread steals the process main thread
    454         // which will then be scheduled by the systemProcessor normally
    455         mainThread = (thread_desc *)&mainThreadStorage;
     440        // which will then be scheduled by the mainProcessor normally
     441        mainThread = (thread_desc *)&storage_mainThread;
    456442        current_stack_info_t info;
    457443        (*mainThread){ &info };
     
    459445        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    460446
    461         // Initialize the system cluster
    462         systemCluster = (cluster *)&systemClusterStorage;
    463         (*systemCluster){};
    464 
    465         LIB_DEBUG_PRINT_SAFE("Kernel : System cluster ready\n");
    466 
    467         // 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
    468454        // (the coroutine that contains the processing control flow)
    469         systemProcessor = (system_proc_t *)&systemProcessorStorage;
    470         (*systemProcessor){ systemCluster, *(processorCtx_t *)&systemProcessorCtxStorage };
    471 
    472         // Add the main thread to the ready queue
    473         // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    474         ScheduleThread(mainThread);
     455        mainProcessor = (processor *)&storage_mainProcessor;
     456        (*mainProcessor){ mainCluster, *(processorCtx_t *)&storage_mainProcessorCtx };
    475457
    476458        //initialize the global state variables
    477         this_processor = &systemProcessor->proc;
     459        this_processor = mainProcessor;
    478460        this_thread = mainThread;
    479461        this_coroutine = &mainThread->cor;
    480         disable_preempt_count = 1;
    481462
    482463        // Enable preemption
    483464        kernel_start_preemption();
    484465
    485         // 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
    486471        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    487472        // mainThread is on the ready queue when this call is made.
    488         resume( *systemProcessor->proc.runner );
     473        resume( *mainProcessor->runner );
    489474
    490475
     
    501486        disable_interrupts();
    502487
    503         // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     488        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
    504489        // When its coroutine terminates, it return control to the mainThread
    505490        // which is currently here
    506         systemProcessor->proc.is_terminated = true;
     491        mainProcessor->do_terminate = true;
    507492        suspend();
    508493
     
    512497        kernel_stop_preemption();
    513498
    514         // 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
    515500        // These were manually constructed so we need manually destroy them
    516         ^(*systemProcessor->proc.runner){};
    517         ^(systemProcessor){};
     501        ^(*mainProcessor->runner){};
     502        ^(mainProcessor){};
    518503
    519504        // Final step, destroy the main thread since it is no longer needed
     
    699684        return top;
    700685}
     686
    701687// Local Variables: //
    702688// mode: c //
  • src/libcfa/concurrency/kernel_private.h

    rfd344aa r9236060  
    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
    8177extern volatile thread_local bool preemption_in_progress;
    8278extern volatile thread_local unsigned short disable_preempt_count;
     
    9187extern void ThreadCtxSwitch(coroutine_desc * src, coroutine_desc * dst);
    9288
    93 #endif //KERNEL_PRIVATE_H
     89//-----------------------------------------------------------------------------
     90// Utils
     91#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
    9492
    9593// Local Variables: //
  • src/libcfa/concurrency/monitor

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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 : Mon Jul 31 14:59:05 2017
     13// Update Count     : 3
    1514//
    1615
     
    485484        if( !this->monitors ) {
    486485                // LIB_DEBUG_PRINT_SAFE("Branding\n");
    487                 assertf( thrd->current_monitors != NULL, "No current monitor to brand condition", thrd->current_monitors );
     486                assertf( thrd->current_monitors != NULL, "No current monitor to brand condition %p", thrd->current_monitors );
    488487                this->monitor_count = thrd->current_monitor_count;
    489488
     
    528527        return head;
    529528}
     529
     530// Local Variables: //
     531// mode: c //
     532// tab-width: 4 //
     533// End: //
  • src/libcfa/concurrency/preemption.c

    rfd344aa r9236060  
    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 && !preemption_in_progress;
    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() {
    220257        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopping\n");
    221258
     259        // Block all signals since we are already shutting down
    222260        sigset_t mask;
    223261        sigfillset( &mask );
    224262        sigprocmask( SIG_BLOCK, &mask, NULL );
    225263
     264        // Notify the alarm thread of the shutdown
    226265        sigval val = { 1 };
    227266        pthread_sigqueue( alarm_thread, SIGALRM, val );
     267
     268        // Wait for the preemption thread to finish
    228269        pthread_join( alarm_thread, NULL );
     270
     271        // Preemption is now fully stopped
     272
    229273        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
    230274}
    231275
     276// Raii ctor/dtor for the preemption_scope
     277// Used by thread to control when they want to receive preemption signals
    232278void ?{}( preemption_scope & this, processor * proc ) {
    233         (this.alarm){ proc };
     279        (this.alarm){ proc, zero_time, zero_time };
    234280        this.proc = proc;
    235281        this.proc->preemption_alarm = &this.alarm;
    236         update_preemption( this.proc, this.proc->preemption );
     282
     283        update_preemption( this.proc, from_us(this.proc->cltr->preemption) );
    237284}
    238285
     
    240287        disable_interrupts();
    241288
    242         update_preemption( this.proc, 0 );
     289        update_preemption( this.proc, zero_time );
    243290}
    244291
     
    247294//=============================================================================================
    248295
     296// Context switch signal handler
     297// Receives SIGUSR1 signal and causes the current thread to yield
    249298void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    250299        LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[CFA_REG_IP]); )
    251         if( preemption_ready() ) {
    252                 preemption_in_progress = true;
    253                 signal_unblock( SIGUSR1 );
    254                 this_processor->pending_preemption = false;
    255                 preemption_in_progress = false;
    256                 BlockInternal( (thread_desc*)this_thread );
    257         }
    258         else {
    259                 defer_ctxSwitch();
    260         }
    261 }
    262 
     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
    263315void * alarm_loop( __attribute__((unused)) void * args ) {
     316        // Block sigalrms to control when they arrive
    264317        sigset_t mask;
    265318        sigemptyset( &mask );
     
    270323        }
    271324
     325        // Main loop
    272326        while( true ) {
     327                // Wait for a sigalrm
    273328                siginfo_t info;
    274329                int sig = sigwaitinfo( &mask, &info );
    275                 if( sig < 0 ) {
    276                         abortf( "internal error, sigwait" );
    277                 }
    278                 else if( sig == SIGALRM )
     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 )
    279337                {
    280                         LIB_DEBUG_PRINT_SAFE("Kernel : Caught signal %d (%d)\n", sig, info.si_value.sival_int );
    281                         if( info.si_value.sival_int == 0 )
    282                         {
    283                                 LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread tick\n");
    284                                 lock( &systemProcessor->alarm_lock DEBUG_CTX2 );
    285                                 tick_preemption();
    286                                 unlock( &systemProcessor->alarm_lock );
    287                         }
    288                         else if( info.si_value.sival_int == 1 )
    289                         {
    290                                 break;
    291                         }
    292                 }
    293                 else
    294                 {
    295                         LIB_DEBUG_PRINT_SAFE("Kernel : Unexpected signal %d (%d)\n", sig, info.si_value.sival_int);
    296                 }
    297         }
    298 
     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:
    299356        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread stopping\n");
    300357        return NULL;
    301358}
    302359
     360// Sigaction wrapper : register an signal handler
    303361static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) {
    304362        struct sigaction act;
     
    316374}
    317375
    318 typedef void (*sa_handler_t)(int);
    319 
     376// Sigaction wrapper : restore default handler
    320377static void __kernel_sigdefault( int sig ) {
    321378        struct sigaction act;
    322379
    323         // act.sa_handler = SIG_DFL;
     380        act.sa_handler = SIG_DFL;
    324381        act.sa_flags = 0;
    325382        sigemptyset( &act.sa_mask );
     
    429486//      raise( SIGABRT );
    430487// }
     488
     489// Local Variables: //
     490// mode: c //
     491// tab-width: 4 //
     492// End: //
  • src/libcfa/concurrency/preemption.h

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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

    rfd344aa r9236060  
    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.