Ignore:
File:
1 edited

Legend:

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

    rc81ebf9 r759908f  
    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 
    17 extern "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 
    36 void __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 
    49 void ?{}( 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 
    58 void ?{}( 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 
    67 void ^?{}( alarm_node_t * this ) {
    68         if( this->set ) {
    69                 unregister_self( this );
    70         }
    71 }
    72 
    73 static 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 
    84 void 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 
    93 alarm_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 
    105 static 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 
    116 static 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 
    125 void 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 
    140 void 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 }
Note: See TracChangeset for help on using the changeset viewer.