Ignore:
Timestamp:
Jun 6, 2017, 2:50:57 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
c6d2e93
Parents:
8ca3a72 (diff), c5ac6d5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:/u/cforall/software/cfa/cfa-cc

Location:
src/libcfa/concurrency
Files:
3 added
1 deleted
6 edited

Legend:

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

    r8ca3a72 r10e90cb  
     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// alarm.c --
     9//
     10// Author           : Thierry Delisle
     11// Created On       : Fri Jun 2 11:31:25 2017
     12// Last Modified By : Thierry Delisle
     13// Last Modified On : --
     14// Update Count     : 0
     15//
     16
     17extern "C" {
     18#include <time.h>
     19#include <sys/time.h>
     20}
     21
     22#include "alarm.h"
     23#include "kernel_private.h"
     24#include "preemption.h"
     25
     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;
     34}
     35
     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 ) {
     50        this->thrd = thrd;
     51        this->alarm = alarm;
     52        this->period = period;
     53        this->next = 0;
     54        this->set = false;
     55        this->kernel_alarm = false;
     56}
     57
     58void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) {
     59        this->proc = proc;
     60        this->alarm = alarm;
     61        this->period = period;
     62        this->next = 0;
     63        this->set = false;
     64        this->kernel_alarm = true;
     65}
     66
     67void ^?{}( alarm_node_t * this ) {
     68        if( this->set ) {
     69                unregister_self( this );
     70        }
     71}
     72
     73static inline void insert_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t p ) {
     74        assert( !n->next );
     75        if( p == this->tail ) {
     76                this->tail = &n->next;
     77        }
     78        else {
     79                n->next = *p;
     80        }
     81        *p = n;
     82}
     83
     84void insert( alarm_list_t * this, alarm_node_t * n ) {
     85        alarm_node_t ** it = &this->head;
     86        while( (*it) && (n->alarm > (*it)->alarm) ) {
     87                it = &(*it)->next;
     88        }
     89
     90        insert_at( this, n, it );
     91}
     92
     93alarm_node_t * pop( alarm_list_t * this ) {
     94        alarm_node_t * head = this->head;
     95        if( head ) {
     96                this->head = head->next;
     97                if( !head->next ) {
     98                        this->tail = &this->head;
     99                }
     100                head->next = NULL;
     101        }
     102        return head;
     103}
     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/kernel

    r8ca3a72 r10e90cb  
    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
     
    94102
    95103// Local Variables: //
    96 // mode: c //
    97 // tab-width: 4 //
     104// mode: CFA //
     105// tab-width: 6 //
    98106// End: //
  • src/libcfa/concurrency/kernel.c

    r8ca3a72 r10e90cb  
    3636//CFA Includes
    3737#include "libhdr.h"
     38#include "preemption.h"
    3839
    3940//Private includes
     
    4748KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
    4849KERNEL_STORAGE(cluster, systemCluster);
    49 KERNEL_STORAGE(processor, systemProcessor);
     50KERNEL_STORAGE(system_proc_t, systemProcessor);
    5051KERNEL_STORAGE(thread_desc, mainThread);
    5152KERNEL_STORAGE(machine_context_t, mainThread_context);
    5253
    5354cluster * systemCluster;
    54 processor * systemProcessor;
     55system_proc_t * systemProcessor;
    5556thread_desc * mainThread;
    5657
     
    118119// Processor coroutine
    119120void ?{}(processorCtx_t * this, processor * proc) {
    120         (&this->__cor){};
     121        (&this->__cor){ "Processor" };
    121122        this->proc = proc;
    122123        proc->runner = this;
     
    139140        (&this->terminated){};
    140141        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;
    141146
    142147        start( this );
     
    149154        (&this->terminated){};
    150155        this->is_terminated = false;
     156        this->disable_preempt_count = 0;
     157        this->pending_preemption = false;
    151158
    152159        this->runner = runner;
    153160        LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
    154161        runner{ this };
     162}
     163
     164void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
     165        (&this->alarms){};
     166        (&this->alarm_lock){};
     167        this->pending_alarm = false;
     168
     169        (&this->proc){ cltr, runner };
    155170}
    156171
     
    178193void main(processorCtx_t * runner) {
    179194        processor * this = runner->proc;
     195
    180196        LIB_DEBUG_PRINT_SAFE("Kernel : core %p starting\n", this);
    181197
    182         thread_desc * readyThread = NULL;
    183         for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
    184198        {
    185                 readyThread = nextThread( this->cltr );
    186 
    187                 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++ )
    188206                {
    189                         runThread(this, readyThread);
    190 
    191                         //Some actions need to be taken from the kernel
    192                         finishRunning(this);
    193 
    194                         spin_count = 0;
    195                 }
    196                 else
    197                 {
    198                         spin(this, &spin_count);
    199                 }               
    200         }
    201 
    202         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
    203227        signal( &this->terminated );
    204228        LIB_DEBUG_PRINT_SAFE("Kernel : core %p terminated\n", this);
     
    299323        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    300324       
    301         // pthread_attr_t attributes;
    302         // pthread_attr_init( &attributes );
    303 
    304325        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    305 
    306         // pthread_attr_destroy( &attributes );
    307326
    308327        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
     
    316335        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
    317336       
    318         lock( &systemProcessor->cltr->lock );
    319         append( &systemProcessor->cltr->ready_queue, thrd );
    320         unlock( &systemProcessor->cltr->lock );
     337        lock( &systemProcessor->proc.cltr->lock );
     338        append( &systemProcessor->proc.cltr->ready_queue, thrd );
     339        unlock( &systemProcessor->proc.cltr->lock );
    321340}
    322341
     
    367386}
    368387
     388//=============================================================================================
     389// Kernel Setup logic
     390//=============================================================================================
    369391//-----------------------------------------------------------------------------
    370392// Kernel boot procedures
     
    379401        mainThread{ &info };
    380402
     403        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
     404
     405        // Enable preemption
     406        kernel_start_preemption();
     407
    381408        // Initialize the system cluster
    382409        systemCluster = (cluster *)&systemCluster_storage;
    383410        systemCluster{};
    384411
     412        LIB_DEBUG_PRINT_SAFE("Kernel : System cluster ready\n");
     413
    385414        // Initialize the system processor and the system processor ctx
    386415        // (the coroutine that contains the processing control flow)
    387         systemProcessor = (processor *)&systemProcessor_storage;
     416        systemProcessor = (system_proc_t *)&systemProcessor_storage;
    388417        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
    389418
    390419        // Add the main thread to the ready queue
    391         // once resume is called on systemProcessor->ctx the mainThread needs to be scheduled like any normal thread
     420        // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    392421        ScheduleThread(mainThread);
    393422
    394423        //initialize the global state variables
    395         this_processor = systemProcessor;
     424        this_processor = &systemProcessor->proc;
    396425        this_processor->current_thread = mainThread;
    397426        this_processor->current_coroutine = &mainThread->cor;
     
    400429        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    401430        // mainThread is on the ready queue when this call is made.
    402         resume(systemProcessor->runner);
     431        resume( systemProcessor->proc.runner );
    403432
    404433
     
    414443        // When its coroutine terminates, it return control to the mainThread
    415444        // which is currently here
    416         systemProcessor->is_terminated = true;
     445        systemProcessor->proc.is_terminated = true;
    417446        suspend();
    418447
     
    421450        // Destroy the system processor and its context in reverse order of construction
    422451        // These were manually constructed so we need manually destroy them
    423         ^(systemProcessor->runner){};
     452        ^(systemProcessor->proc.runner){};
    424453        ^(systemProcessor){};
    425454
     
    484513}
    485514
     515//=============================================================================================
     516// Kernel Utilities
     517//=============================================================================================
    486518//-----------------------------------------------------------------------------
    487519// Locks
     
    491523void ^?{}( spinlock * this ) {
    492524
     525}
     526
     527bool try_lock( spinlock * this ) {
     528        return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
    493529}
    494530
  • src/libcfa/concurrency/kernel_private.h

    r8ca3a72 r10e90cb  
    2121#include "thread"
    2222
     23#include "alarm.h"
     24
    2325//-----------------------------------------------------------------------------
    2426// Scheduler
     
    3537//-----------------------------------------------------------------------------
    3638// Processor
    37 struct processorCtx_t {
     39coroutine processorCtx_t {
    3840        processor * proc;
    39         coroutine_desc __cor;
    4041};
    41 
    42 DECL_COROUTINE(processorCtx_t);
    4342
    4443void main(processorCtx_t *);
     
    4746void finishRunning(processor * this);
    4847void spin(processor * this, unsigned int * spin_count);
     48
     49struct system_proc_t {
     50        processor proc;
     51
     52        alarm_list_t alarms;
     53        spinlock alarm_lock;
     54
     55        bool pending_alarm;
     56};
     57
     58extern cluster * systemCluster;
     59extern 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}
    4980
    5081//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/monitor

    r8ca3a72 r10e90cb  
    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

    r8ca3a72 r10e90cb  
    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
Note: See TracChangeset for help on using the changeset viewer.