Changeset c81ebf9


Ignore:
Timestamp:
Jun 6, 2017, 11:45:13 AM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
c5ac6d5
Parents:
7b13aeb
Message:

More work done on preemption in cforall, next step disabling interrupts at the correct places

Location:
src/libcfa/concurrency
Files:
1 added
8 edited

Legend:

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

    r7b13aeb rc81ebf9  
    1515//
    1616
     17extern "C" {
     18#include <time.h>
     19#include <sys/time.h>
     20}
     21
    1722#include "alarm.h"
    1823#include "kernel_private.h"
     24#include "preemption.h"
    1925
    20 static void register_self( alarm_node_t * this ) {
    21         lock( &systemProcessor->alarm_lock );
    22         insert( &systemProcessor->alarms, this );
    23         unlock( &systemProcessor->alarm_lock );
     26//=============================================================================================
     27// Clock logic
     28//=============================================================================================
     29
     30__cfa_time_t __kernel_get_time() {
     31        timespec curr;
     32        clock_gettime( CLOCK_REALTIME, &curr );
     33        return ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
    2434}
    2535
    26 void ?{}( alarm_node_t * this, thread_desc * thrd, cfa_time_t alarm, cfa_time_t period = 0 ) {
     36void __kernel_set_timer( __cfa_time_t alarm ) {
     37        itimerval val;
     38        val.it_value.tv_sec = alarm / TIMEGRAN;                 // seconds
     39        val.it_value.tv_usec = (alarm % TIMEGRAN) / ( TIMEGRAN / 1_000_000L ); // microseconds
     40        val.it_interval.tv_sec = 0;
     41        val.it_interval.tv_usec = 0;
     42        setitimer( ITIMER_REAL, &val, NULL );
     43}
     44
     45//=============================================================================================
     46// Alarm logic
     47//=============================================================================================
     48
     49void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) {
    2750        this->thrd = thrd;
    2851        this->alarm = alarm;
    2952        this->period = period;
    3053        this->next = 0;
    31 
    32         register_self( this );
     54        this->set = false;
     55        this->kernel_alarm = false;
    3356}
    3457
    35 void ?{}( alarm_node_t * this, processor   * proc, cfa_time_t alarm, cfa_time_t period = 0 ) {
     58void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) {
    3659        this->proc = proc;
    3760        this->alarm = alarm;
    3861        this->period = period;
    3962        this->next = 0;
     63        this->set = false;
     64        this->kernel_alarm = true;
     65}
    4066
    41         register_self( this );
     67void ^?{}( alarm_node_t * this ) {
     68        if( this->set ) {
     69                unregister_self( this );
     70        }
    4271}
    4372
     
    6291}
    6392
    64 void pop( alarm_list_t * this ) {
     93alarm_node_t * pop( alarm_list_t * this ) {
    6594        alarm_node_t * head = this->head;
    6695        if( head ) {
     
    73102        return head;
    74103}
     104
     105static inline void remove_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t it ) {
     106        assert( it );
     107        assert( (*it)->next == n );
     108
     109        (*it)->next = n->next;
     110        if( !n-> next ) {
     111                this->tail = it;
     112        }
     113        n->next = NULL;
     114}
     115
     116static inline void remove( alarm_list_t * this, alarm_node_t * n ) {
     117        alarm_node_t ** it = &this->head;
     118        while( (*it) && (*it)->next != n ) {
     119                it = &(*it)->next;
     120        }
     121
     122        if( *it ) { remove_at( this, n, it ); }
     123}
     124
     125void register_self( alarm_node_t * this ) {
     126        disable_interrupts();
     127        assert( !systemProcessor->pending_alarm );
     128        lock( &systemProcessor->alarm_lock );
     129        {
     130                insert( &systemProcessor->alarms, this );
     131                if( systemProcessor->pending_alarm ) {
     132                        tick_preemption();
     133                }
     134        }
     135        unlock( &systemProcessor->alarm_lock );
     136        this->set = true;
     137        enable_interrupts();
     138}
     139
     140void unregister_self( alarm_node_t * this ) {
     141        disable_interrupts();
     142        lock( &systemProcessor->alarm_lock );
     143        remove( &systemProcessor->alarms, this );
     144        unlock( &systemProcessor->alarm_lock );
     145        disable_interrupts();
     146        this->set = false;
     147}
  • src/libcfa/concurrency/alarm.h

    r7b13aeb rc81ebf9  
    1818#define ALARM_H
    1919
     20#include <stdbool.h>
     21
    2022#include "assert"
    2123
    22 typedef unsigned long int cfa_time_t;
     24typedef unsigned long int __cfa_time_t;
    2325
    2426struct thread_desc;
    2527struct processor;
    2628
     29//=============================================================================================
     30// Clock logic
     31//=============================================================================================
     32
     33#define TIMEGRAN 1_000_000_000L                         // nanosecond granularity, except for timeval
     34
     35__cfa_time_t __kernel_get_time();
     36void __kernel_set_timer( __cfa_time_t alarm );
     37
     38//=============================================================================================
     39// Alarm logic
     40//=============================================================================================
     41
    2742struct alarm_node_t {
    28         cfa_time_t alarm;               // time when alarm goes off
    29         cfa_time_t period;      // if > 0 => period of alarm
    30         alarm_node_t * next;    // intrusive link list field
     43        __cfa_time_t alarm;             // time when alarm goes off
     44        __cfa_time_t period;            // if > 0 => period of alarm
     45        alarm_node_t * next;            // intrusive link list field
    3146
    3247        union {
     
    3449                processor * proc;               // proc who created event
    3550        };
     51
     52        bool set                :1;             // whether or not the alarm has be registered
     53        bool kernel_alarm       :1;             // true if this is not a user defined alarm
    3654};
    3755
    3856typedef alarm_node_t ** __alarm_it_t;
    3957
    40 void ?{}( alarm_node_t * this, thread_desc * thrd, cfa_time_t alarm, cfa_time_t period = 0 );
    41 void ?{}( alarm_node_t * this, processor   * proc, cfa_time_t alarm, cfa_time_t period = 0 );
     58void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = 0, __cfa_time_t period = 0 );
     59void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 );
     60void ^?{}( alarm_node_t * this );
    4261
    4362struct alarm_list_t {
     
    5473alarm_node_t * pop( alarm_list_t * this );
    5574
     75void register_self  ( alarm_node_t * this );
     76void unregister_self( alarm_node_t * this );
     77
    5678#endif
    5779
  • src/libcfa/concurrency/kernel

    r7b13aeb rc81ebf9  
    2828//-----------------------------------------------------------------------------
    2929// Locks
     30bool try_lock( spinlock * );
    3031void lock( spinlock * );
    3132void unlock( spinlock * );
     
    8586
    8687        struct FinishAction finish;
     88
     89        struct alarm_node_t * preemption_alarm;
     90        unsigned int preemption;
     91
     92        unsigned short disable_preempt_count;
     93
     94        bool pending_preemption;
    8795};
    8896
  • src/libcfa/concurrency/kernel.c

    r7b13aeb rc81ebf9  
    3636//CFA Includes
    3737#include "libhdr.h"
     38#include "preemption.h"
    3839
    3940//Private includes
     
    8182
    8283void ?{}( current_stack_info_t * this ) {
    83         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 1\n");
    8484        CtxGet( &this->ctx );
    8585        this->base = this->ctx.FP;
     
    9696
    9797void ?{}( coStack_t * this, current_stack_info_t * info) {
    98         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 2\n");
    9998        this->size = info->size;
    10099        this->storage = info->storage;
     
    107106
    108107void ?{}( coroutine_desc * this, current_stack_info_t * info) {
    109         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 3\n");
    110108        (&this->stack){ info };
    111109        this->name = "Main Thread";
     
    115113
    116114void ?{}( thread_desc * this, current_stack_info_t * info) {
    117         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 4\n");
    118115        (&this->cor){ info };
    119116}
     
    122119// Processor coroutine
    123120void ?{}(processorCtx_t * this, processor * proc) {
    124         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 5\n");
    125121        (&this->__cor){ "Processor" };
    126122        this->proc = proc;
     
    129125
    130126void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) {
    131         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 6\n");
    132127        (&this->__cor){ info };
    133128        this->proc = proc;
     
    136131
    137132void ?{}(processor * this) {
    138         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 7\n");
    139133        this{ systemCluster };
    140134}
    141135
    142136void ?{}(processor * this, cluster * cltr) {
    143         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 8\n");
    144137        this->cltr = cltr;
    145138        this->current_coroutine = NULL;
     
    147140        (&this->terminated){};
    148141        this->is_terminated = false;
     142        this->preemption_alarm = NULL;
     143        this->preemption = default_preemption();
     144        this->disable_preempt_count = 1;                //Start with interrupts disabled
     145        this->pending_preemption = false;
    149146
    150147        start( this );
     
    157154        (&this->terminated){};
    158155        this->is_terminated = false;
     156        this->disable_preempt_count = 0;
     157        this->pending_preemption = false;
    159158
    160159        this->runner = runner;
     
    164163
    165164void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
    166         LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 9\n");
    167165        (&this->alarms){};
    168166        (&this->alarm_lock){};
     167        this->pending_alarm = false;
    169168
    170169        (&this->proc){ cltr, runner };
     
    194193void main(processorCtx_t * runner) {
    195194        processor * this = runner->proc;
     195
    196196        LIB_DEBUG_PRINT_SAFE("Kernel : core %p starting\n", this);
    197197
    198         thread_desc * readyThread = NULL;
    199         for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
    200198        {
    201                 readyThread = nextThread( this->cltr );
    202 
    203                 if(readyThread)
     199                // Setup preemption data
     200                preemption_scope scope = { this };
     201
     202                LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);
     203
     204                thread_desc * readyThread = NULL;
     205                for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
    204206                {
    205                         runThread(this, readyThread);
    206 
    207                         //Some actions need to be taken from the kernel
    208                         finishRunning(this);
    209 
    210                         spin_count = 0;
    211                 }
    212                 else
    213                 {
    214                         spin(this, &spin_count);
    215                 }               
    216         }
    217 
    218         LIB_DEBUG_PRINT_SAFE("Kernel : core %p unlocking thread\n", this);
     207                        readyThread = nextThread( this->cltr );
     208
     209                        if(readyThread)
     210                        {
     211                                runThread(this, readyThread);
     212
     213                                //Some actions need to be taken from the kernel
     214                                finishRunning(this);
     215
     216                                spin_count = 0;
     217                        }
     218                        else
     219                        {
     220                                spin(this, &spin_count);
     221                        }
     222                }
     223
     224                LIB_DEBUG_PRINT_SAFE("Kernel : core %p stopping\n", this);
     225        }
     226
    219227        signal( &this->terminated );
    220228        LIB_DEBUG_PRINT_SAFE("Kernel : core %p terminated\n", this);
     
    315323        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    316324       
    317         // pthread_attr_t attributes;
    318         // pthread_attr_init( &attributes );
    319 
    320325        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    321 
    322         // pthread_attr_destroy( &attributes );
    323326
    324327        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
     
    381384        this_processor->finish.thrd_count = thrd_count;
    382385        suspend();
    383 }
    384 
    385 //=============================================================================================
    386 // Kernel Preemption logic
    387 //=============================================================================================
    388 
    389 #define __CFA_DEFAULT_PREEMPTION__ 10
    390 
    391 unsigned int default_preemption() {
    392         return __CFA_DEFAULT_PREEMPTION__;
    393 }
    394 
    395 void kernel_start_preemption() {
    396 
    397386}
    398387
     
    536525}
    537526
     527bool try_lock( spinlock * this ) {
     528        return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
     529}
     530
    538531void lock( spinlock * this ) {
    539532        for ( unsigned int i = 1;; i += 1 ) {
  • src/libcfa/concurrency/kernel_private.h

    r7b13aeb rc81ebf9  
    5252        alarm_list_t alarms;
    5353        spinlock alarm_lock;
     54
     55        bool pending_alarm;
    5456};
    5557
    5658extern cluster * systemCluster;
    5759extern system_proc_t * systemProcessor;
     60extern thread_local processor * this_processor;
     61
     62static inline void disable_interrupts() {
     63        __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST );
     64        assert( prev != (unsigned short) -1 );
     65}
     66
     67static inline void enable_interrupts_noRF() {
     68        unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     69        assert( prev != (unsigned short) 0 );
     70}
     71
     72static inline void enable_interrupts() {
     73        unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST );
     74        assert( prev != (unsigned short) 0 );
     75        if( prev == 1 && this_processor->pending_preemption ) {
     76                ScheduleInternal( this_processor->current_thread );
     77                this_processor->pending_preemption = false;
     78        }
     79}
    5880
    5981//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/monitor

    r7b13aeb rc81ebf9  
    9292uintptr_t front( condition * this );
    9393
     94struct __acceptable_t {
     95        void (*func)(void);
     96        unsigned short count;
     97        monitor_desc * monitors[1];
     98};
     99
     100void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) );
     101
    94102#endif //MONITOR_H
  • src/libcfa/concurrency/monitor.c

    r7b13aeb rc81ebf9  
    212212        ScheduleInternal( locks, count, threads, thread_count );
    213213
     214
    214215        //WE WOKE UP
    215216
     
    312313        ScheduleInternal( locks, count, &signallee, 1 );
    313314
     315
     316
     317
    314318        LIB_DEBUG_PRINT_SAFE( "Back from signal block\n" );
    315319
     
    330334        );
    331335        return this->blocked.head->user_info;
     336}
     337
     338//-----------------------------------------------------------------------------
     339// Internal scheduling
     340void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ) {
     341        // thread_desc * this = this_thread();
     342
     343        // unsigned short count = this->current_monitor_count;
     344        // unsigned int recursions[ count ];            //Save the current recursion levels to restore them later
     345        // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to ScheduleInternal
     346
     347        // lock_all( this->current_monitors, locks, count );
     348
     349
     350
     351
     352
     353        // // // Everything is ready to go to sleep
     354        // // ScheduleInternal( locks, count, threads, thread_count );
     355
     356
     357        // //WE WOKE UP
     358
     359
     360        // //We are back, restore the owners and recursions
     361        // lock_all( locks, count );
     362        // restore_recursion( this->monitors, recursions, count );
     363        // unlock_all( locks, count );
    332364}
    333365
  • src/libcfa/concurrency/signal.c

    r7b13aeb rc81ebf9  
     1//                              -*- Mode: CFA -*-
     2//
     3// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
     4//
     5// The contents of this file are covered under the licence agreement in the
     6// file "LICENCE" distributed with Cforall.
     7//
     8// signal.c --
     9//
     10// Author           : Thierry Delisle
     11// Created On       : Mon Jun 5 14:20:42 2017
     12// Last Modified By : Thierry Delisle
     13// Last Modified On : --
     14// Update Count     : 0
     15//
     16
     17#include "preemption.h"
     18
     19extern "C" {
     20#include <signal.h>
     21}
     22
     23#define __CFA_DEFAULT_PREEMPTION__ 10
     24
     25__attribute__((weak)) unsigned int default_preemption() {
     26        return __CFA_DEFAULT_PREEMPTION__;
     27}
     28
     29static void preempt( processor   * this );
     30static void timeout( thread_desc * this );
     31
     32//=============================================================================================
     33// Kernel Preemption logic
     34//=============================================================================================
     35
     36void kernel_start_preemption() {
     37
     38}
     39
     40void tick_preemption() {
     41        alarm_list_t * alarms = &systemProcessor->alarms;
     42        __cfa_time_t currtime = __kernel_get_time();
     43        while( alarms->head && alarms->head->alarm < currtime ) {
     44                alarm_node_t * node = pop(alarms);
     45                if( node->kernel_alarm ) {
     46                        preempt( node->proc );
     47                }
     48                else {
     49                        timeout( node->thrd );
     50                }
     51
     52                if( node->period > 0 ) {
     53                        node->alarm += node->period;
     54                        insert( alarms, node );
     55                }
     56                else {
     57                        node->set = false;
     58                }
     59        }
     60
     61        if( alarms->head ) {
     62                __kernel_set_timer( alarms->head->alarm - currtime );
     63        }
     64}
     65
     66void update_preemption( processor * this, __cfa_time_t duration ) {
     67        //     assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 );
     68        alarm_node_t * alarm = this->preemption_alarm;
     69
     70        // Alarms need to be enabled
     71        if ( duration > 0 && !alarm->set ) {
     72                alarm->alarm = __kernel_get_time() + duration;
     73                alarm->period = duration;
     74                register_self( alarm );
     75        }
     76        // Zero duraction but alarm is set
     77        else if ( duration == 0 && alarm->set ) {
     78                unregister_self( alarm );
     79                alarm->alarm = 0;
     80                alarm->period = 0;
     81        }
     82        // If alarm is different from previous, change it
     83        else if ( duration > 0 && alarm->period != duration ) {
     84                unregister_self( alarm );
     85                alarm->alarm = __kernel_get_time() + duration;
     86                alarm->period = duration;
     87                register_self( alarm );
     88        }
     89}
     90
     91void ?{}( preemption_scope * this, processor * proc ) {
     92        (&this->alarm){ proc };
     93        this->proc = proc;
     94        this->proc->preemption_alarm = &this->alarm;
     95        update_preemption( this->proc, this->proc->preemption );
     96}
     97
     98void ^?{}( preemption_scope * this ) {
     99        update_preemption( this->proc, 0 );
     100}
     101
     102//=============================================================================================
     103// Kernel Signal logic
     104//=============================================================================================
     105
     106static inline bool preemption_ready() {
     107        return this_processor->disable_preempt_count == 0;
     108}
     109
     110static inline void defer_ctxSwitch() {
     111        this_processor->pending_preemption = true;
     112}
     113
     114static inline void defer_alarm() {
     115        systemProcessor->pending_alarm = true;
     116}
     117
     118void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) {
     119        if( preemption_ready() ) {
     120                ScheduleInternal( this_processor->current_thread );
     121        }
     122        else {
     123                defer_ctxSwitch();
     124        }
     125}
     126
     127void sigHandler_alarm( __attribute__((unused)) int sig ) {
     128        if( try_lock( &systemProcessor->alarm_lock ) ) {
     129                tick_preemption();
     130                unlock( &systemProcessor->alarm_lock );
     131        }
     132        else {
     133                defer_alarm();
     134        }
     135}
     136
     137static void preempt( processor * this ) {
     138        pthread_kill( this->kernel_thread, SIGUSR1 );
     139}
     140
     141static void timeout( thread_desc * this ) {
     142        //TODO : implement waking threads
     143}
Note: See TracChangeset for help on using the changeset viewer.