Changeset e3987770 for src


Ignore:
Timestamp:
Apr 19, 2017, 3:09:24 PM (7 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:
b3d70eba
Parents:
5f642e38 (diff), 8731d8c (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
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/invoke.h

    r5f642e38 re3987770  
    3333      };
    3434
    35       struct simple_thread_list {
     35      struct __thread_queue_t {
    3636            struct thread_desc * head;
    3737            struct thread_desc ** tail;
    3838      };
    3939
     40      struct __thread_stack_t {
     41            struct thread_desc * top;
     42      };
     43
    4044      #ifdef __CFORALL__
    4145      extern "Cforall" {
    42             void ?{}( struct simple_thread_list * );
    43             void append( struct simple_thread_list *, struct thread_desc * );
    44             struct thread_desc * pop_head( struct simple_thread_list * );
     46            void ?{}( struct __thread_queue_t * );
     47            void append( struct __thread_queue_t *, struct thread_desc * );
     48            struct thread_desc * pop_head( struct __thread_queue_t * );
     49
     50            void ?{}( struct __thread_stack_t * );
     51            void push( struct __thread_stack_t *, struct thread_desc * );           
     52            struct thread_desc * pop( struct __thread_stack_t * );
    4553
    4654            void ?{}(spinlock * this);
     
    5058
    5159      struct coStack_t {
    52             unsigned int size;                  // size of stack
    53             void *storage;                      // pointer to stack
    54             void *limit;                        // stack grows towards stack limit
    55             void *base;                         // base of stack
    56             void *context;                      // address of cfa_context_t
    57             void *top;                          // address of top of storage
    58             bool userStack;                     // whether or not the user allocated the stack
     60            unsigned int size;                        // size of stack
     61            void *storage;                            // pointer to stack
     62            void *limit;                              // stack grows towards stack limit
     63            void *base;                               // base of stack
     64            void *context;                            // address of cfa_context_t
     65            void *top;                                // address of top of storage
     66            bool userStack;                           // whether or not the user allocated the stack
    5967      };
    6068
     
    6270
    6371      struct coroutine_desc {
    64             struct coStack_t stack;             // stack information of the coroutine
    65             const char *name;                   // textual name for coroutine/task, initialized by uC++ generated code
    66             int errno_;                         // copy of global UNIX variable errno
    67             enum coroutine_state state;         // current execution status for coroutine
    68             struct coroutine_desc *starter;     // first coroutine to resume this one
    69             struct coroutine_desc *last;              // last coroutine to resume this one
     72            struct coStack_t stack;                   // stack information of the coroutine
     73            const char *name;                         // textual name for coroutine/task, initialized by uC++ generated code
     74            int errno_;                               // copy of global UNIX variable errno
     75            enum coroutine_state state;               // current execution status for coroutine
     76            struct coroutine_desc *starter;           // first coroutine to resume this one
     77            struct coroutine_desc *last;                    // last coroutine to resume this one
    7078      };
    7179
    7280      struct monitor_desc {
    73             struct spinlock lock;
    74             struct thread_desc * owner;
    75             struct simple_thread_list entry_queue;
    76             unsigned int recursion;
     81            struct spinlock lock;                     // spinlock to protect internal data
     82            struct thread_desc * owner;               // current owner of the monitor
     83            struct __thread_queue_t entry_queue;      // queue of threads that are blocked waiting for the monitor
     84            struct __thread_stack_t signal_stack;     // stack of threads to run next once we exit the monitor
     85            struct monitor_desc * stack_owner;        // if bulk acquiring was used we need to synchronize signals with an other monitor
     86            unsigned int recursion;                   // monitor routines can be called recursively, we need to keep track of that
    7787      };
    7888
    7989      struct thread_desc {
    80             struct coroutine_desc cor;          // coroutine body used to store context
    81             struct monitor_desc mon;            // monitor body used for mutual exclusion
    82             struct thread_desc * next;          // instrusive link field for threads
     90            struct coroutine_desc cor;                // coroutine body used to store context
     91            struct monitor_desc mon;                  // monitor body used for mutual exclusion
     92            struct thread_desc * next;                // instrusive link field for threads
     93            struct monitor_desc ** current_monitors;  // currently held monitors
     94            unsigned short current_monitor_count;     // number of currently held monitors
    8395      };
    8496
  • src/libcfa/concurrency/kernel

    r5f642e38 re3987770  
    3232
    3333struct signal_once {
    34         volatile bool condition;
     34        volatile bool cond;
    3535        struct spinlock lock;
    36         struct simple_thread_list blocked;
     36        struct __thread_queue_t blocked;
    3737};
    3838
     
    4646// Cluster
    4747struct cluster {
    48         simple_thread_list ready_queue;
     48        __thread_queue_t ready_queue;
    4949        spinlock lock;
    5050};
  • src/libcfa/concurrency/kernel.c

    r5f642e38 re3987770  
    299299// Scheduler routines
    300300void ScheduleThread( thread_desc * thrd ) {
     301        if( !thrd ) return;
     302
    301303        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
    302304       
     
    473475
    474476void ?{}( signal_once * this ) {
    475         this->condition = false;
     477        this->cond = false;
    476478}
    477479void ^?{}( signal_once * this ) {
     
    481483void wait( signal_once * this ) {
    482484        lock( &this->lock );
    483         if( !this->condition ) {
     485        if( !this->cond ) {
    484486                append( &this->blocked, this_thread() );
    485487                ScheduleInternal( &this->lock );
     
    492494        lock( &this->lock );
    493495        {
    494                 this->condition = true;
     496                this->cond = true;
    495497
    496498                thread_desc * it;
     
    504506//-----------------------------------------------------------------------------
    505507// Queues
    506 void ?{}( simple_thread_list * this ) {
     508void ?{}( __thread_queue_t * this ) {
    507509        this->head = NULL;
    508510        this->tail = &this->head;
    509511}
    510512
    511 void append( simple_thread_list * this, thread_desc * t ) {
     513void append( __thread_queue_t * this, thread_desc * t ) {
    512514        assert(this->tail != NULL);
    513515        *this->tail = t;
     
    515517}
    516518
    517 thread_desc * pop_head( simple_thread_list * this ) {
     519thread_desc * pop_head( __thread_queue_t * this ) {
    518520        thread_desc * head = this->head;
    519521        if( head ) {
     
    526528        return head;
    527529}
     530
     531void ?{}( __thread_stack_t * this ) {
     532        this->top = NULL;
     533}
     534
     535void push( __thread_stack_t * this, thread_desc * t ) {
     536        assert(t->next != NULL);
     537        t->next = this->top;
     538        this->top = t;
     539}
     540
     541thread_desc * pop( __thread_stack_t * this ) {
     542        thread_desc * top = this->top;
     543        if( top ) {
     544                this->top = top->next;
     545                top->next = NULL;
     546        }       
     547        return top;
     548}
    528549// Local Variables: //
    529550// mode: c //
  • src/libcfa/concurrency/monitor

    r5f642e38 re3987770  
    1818#define MONITOR_H
    1919
     20#include <stddef.h>
     21
    2022#include "assert"
    2123#include "invoke.h"
     
    2325
    2426static inline void ?{}(monitor_desc * this) {
    25         this->owner = 0;
     27        this->owner = NULL;
     28      this->stack_owner = NULL;
    2629        this->recursion = 0;
    2730}
    28 
    29 //Array entering routine
    30 void enter(monitor_desc **, int count);
    31 void leave(monitor_desc **, int count);
    3231
    3332struct monitor_guard_t {
    3433        monitor_desc ** m;
    3534        int count;
     35      monitor_desc ** prev_mntrs;
     36      unsigned short  prev_count;
    3637};
    3738
     
    4041}
    4142
    42 static inline void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) {
    43         this->m = m;
    44         this->count = count;
    45         qsort(this->m, count);
    46         enter( this->m, this->count );
     43void ?{}( monitor_guard_t * this, monitor_desc ** m, int count );
     44void ^?{}( monitor_guard_t * this );
     45
     46//-----------------------------------------------------------------------------
     47// Internal scheduling
     48struct condition {
     49        __thread_queue_t blocked;
     50        monitor_desc ** monitors;
     51        unsigned short monitor_count;
     52};
     53
     54static inline void ?{}( condition * this ) {
     55        this->monitors = NULL;
     56        this->monitor_count = 0;
    4757}
    4858
    49 static inline void ^?{}( monitor_guard_t * this ) {
    50         leave( this->m, this->count );
    51 }
    52 
    53 
     59void wait( condition * this );
     60void signal( condition * this );
    5461#endif //MONITOR_H
  • src/libcfa/concurrency/monitor.c

    r5f642e38 re3987770  
    1818
    1919#include "kernel_private.h"
     20#include "libhdr.h"
     21
     22void set_owner( monitor_desc * this, thread_desc * owner ) {
     23        //Pass the monitor appropriately
     24        this->owner = owner;
     25
     26        //We are passing the monitor to someone else, which means recursion level is not 0
     27        this->recursion = owner ? 1 : 0;
     28}
    2029
    2130extern "C" {
    22         void __enter_monitor_desc(monitor_desc * this) {
     31        void __enter_monitor_desc(monitor_desc * this, monitor_desc * leader) {
    2332                lock( &this->lock );
    2433                thread_desc * thrd = this_thread();
    2534
     35                // //Update the stack owner
     36                // this->stack_owner = leader;
     37
     38                LIB_DEBUG_PRINT_SAFE("Entering %p (o: %p, r: %i)\n", this, this->owner, this->recursion);
     39
    2640                if( !this->owner ) {
    2741                        //No one has the monitor, just take it
    28                         this->owner = thrd;
    29                         this->recursion = 1;
     42                        set_owner( this, thrd );
    3043                }
    3144                else if( this->owner == thrd) {
     
    4457
    4558                unlock( &this->lock );
    46         }
    47 
    48         void __leave_monitor_desc(monitor_desc * this) {
     59                return;
     60        }
     61
     62        // leave pseudo code :
     63        //      decrement level
     64        //      leve == 0 ?
     65        //              no : done
     66        //              yes :
     67        //                      signal stack empty ?
     68        //                              has leader :
     69        //                                      bulk acquiring means we don't own the signal stack
     70        //                                      ignore it but don't release the monitor
     71        //                              yes :
     72        //                                      next in entry queue is new owner
     73        //                              no :
     74        //                                      top of the signal stack is the owner
     75        //                                      context switch to him right away
     76        //
     77        void __leave_monitor_desc(monitor_desc * this, monitor_desc * leader) {
    4978                lock( &this->lock );
    5079
     80                LIB_DEBUG_PRINT_SAFE("Leaving %p (o: %p, r: %i)\n", this, this->owner, this->recursion);
     81
    5182                thread_desc * thrd = this_thread();
    52                 assert( thrd == this->owner );
     83                assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", this->owner, thrd, this->recursion );
    5384
    5485                //Leaving a recursion level, decrement the counter
    5586                this->recursion -= 1;
    5687
    57                 //If we left the last level of recursion it means we are changing who owns the monitor
     88                //If we haven't left the last level of recursion
     89                //it means we don't need to do anything
     90                if( this->recursion != 0) {
     91                        // this->stack_owner = leader;
     92                        unlock( &this->lock );
     93                        return;
     94                }
     95                       
     96                // //If we don't own the signal stack then just leave it to the owner
     97                // if( this->stack_owner ) {
     98                //      this->stack_owner = leader;
     99                //      unlock( &this->lock );
     100                //      return;
     101                // }
     102
     103                //We are the stack owner and have left the last recursion level.
     104                //We are in charge of passing the monitor
    58105                thread_desc * new_owner = 0;
    59                 if( this->recursion == 0) {
    60                         //Get the next thread in the list
    61                         new_owner = this->owner = pop_head( &this->entry_queue );
    62 
    63                         //We are passing the monitor to someone else, which means recursion level is not 0
    64                         this->recursion = new_owner ? 1 : 0;
    65                 }       
    66 
     106
     107                //Check the signaller stack
     108                new_owner = pop( &this->signal_stack );
     109                if( new_owner ) {
     110                        //The signaller stack is not empty,
     111                        //transfer control immediately
     112                        set_owner( this, new_owner );
     113                        // this->stack_owner = leader;
     114                        ScheduleInternal( &this->lock, new_owner );
     115                        return;
     116                }
     117               
     118                // No signaller thread
     119                // Get the next thread in the entry_queue
     120                new_owner = pop_head( &this->entry_queue );
     121                set_owner( this, new_owner );
     122
     123                // //Update the stack owner
     124                // this->stack_owner = leader;
     125
     126                //We can now let other threads in safely
    67127                unlock( &this->lock );
    68128
    69                 //If we have a new owner, we need to wake-up the thread
    70                 if( new_owner ) {
    71                         ScheduleThread( new_owner );
    72                 }
    73         }
    74 }
    75 
    76 void enter(monitor_desc ** monitors, int count) {
    77         for(int i = 0; i < count; i++) {
    78                 __enter_monitor_desc( monitors[i] );
    79         }
    80 }
    81 
    82 void leave(monitor_desc ** monitors, int count) {
    83         for(int i = count - 1; i >= 0; i--) {
    84                 __leave_monitor_desc( monitors[i] );
    85         }
    86 }
     129                //We need to wake-up the thread
     130                ScheduleThread( new_owner );
     131        }
     132}
     133
     134static inline void enter(monitor_desc ** monitors, int count) {
     135        __enter_monitor_desc( monitors[0], NULL );
     136        for(int i = 1; i < count; i++) {
     137                __enter_monitor_desc( monitors[i], monitors[0] );
     138        }
     139}
     140
     141static inline void leave(monitor_desc ** monitors, int count) {
     142        __leave_monitor_desc( monitors[0], NULL );
     143        for(int i = count - 1; i >= 1; i--) {
     144                __leave_monitor_desc( monitors[i], monitors[0] );
     145        }
     146}
     147
     148void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) {
     149        this->m = m;
     150        this->count = count;
     151        qsort(this->m, count);
     152        enter( this->m, this->count );
     153
     154        this->prev_mntrs = this_thread()->current_monitors;
     155        this->prev_count = this_thread()->current_monitor_count;
     156
     157        this_thread()->current_monitors      = m;
     158        this_thread()->current_monitor_count = count;
     159}
     160
     161void ^?{}( monitor_guard_t * this ) {
     162        leave( this->m, this->count );
     163
     164        this_thread()->current_monitors      = this->prev_mntrs;
     165        this_thread()->current_monitor_count = this->prev_count;
     166}
     167
     168//-----------------------------------------------------------------------------
     169// Internal scheduling
     170void wait( condition * this ) {
     171        assertf(false, "NO SUPPORTED");
     172        // LIB_DEBUG_FPRINTF("Waiting\n");
     173        thread_desc * this_thrd = this_thread();
     174
     175        if( !this->monitors ) {
     176                this->monitors = this_thrd->current_monitors;
     177                this->monitor_count = this_thrd->current_monitor_count;
     178        }
     179
     180        unsigned short count = this->monitor_count;
     181
     182        //Check that everything is as expected
     183        assert( this->monitors != NULL );
     184        assert( this->monitor_count != 0 );
     185
     186        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
     187        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
     188
     189        // LIB_DEBUG_FPRINTF("Getting ready to wait\n");
     190
     191        //Loop on all the monitors and release the owner
     192        for( unsigned int i = 0; i < count; i++ ) {
     193                monitor_desc * cur = this->monitors[i];
     194
     195                assert( cur );
     196
     197                // LIB_DEBUG_FPRINTF("cur %p lock %p\n", cur, &cur->lock);
     198
     199                //Store the locks for later
     200                locks[i] = &cur->lock;
     201
     202                //Protect the monitors
     203                lock( locks[i] );
     204                {               
     205                        //Save the recursion levels
     206                        recursions[i] = cur->recursion;
     207
     208                        //Release the owner
     209                        cur->recursion = 0;
     210                        cur->owner = NULL;
     211                }
     212                //Release the monitor
     213                unlock( locks[i] );
     214        }
     215
     216        // LIB_DEBUG_FPRINTF("Waiting now\n");
     217
     218        //Everything is ready to go to sleep
     219        ScheduleInternal( locks, count );
     220
     221
     222        //WE WOKE UP
     223
     224
     225        //We are back, restore the owners and recursions
     226        for( unsigned int i = 0; i < count; i++ ) {
     227                monitor_desc * cur = this->monitors[i];
     228
     229                //Protect the monitors
     230                lock( locks[i] );
     231                {
     232                        //Release the owner
     233                        cur->owner = this_thrd;
     234                        cur->recursion = recursions[i];
     235                }
     236                //Release the monitor
     237                unlock( locks[i] );
     238        }
     239}
     240
     241static void __signal_internal( condition * this ) {
     242        assertf(false, "NO SUPPORTED");
     243        if( !this->blocked.head ) return;
     244
     245        //Check that everything is as expected
     246        assert( this->monitors );
     247        assert( this->monitor_count != 0 );
     248       
     249        LIB_DEBUG_DO(
     250                if ( this->monitors != this_thread()->current_monitors ) {
     251                        abortf( "Signal on condition %p made outside of the correct monitor(s)", this );
     252                } // if
     253        );
     254
     255        monitor_desc * owner = this->monitors[0];
     256        lock( &owner->lock );
     257        {
     258                thread_desc * unblock = pop_head( &this->blocked );
     259                push( &owner->signal_stack, unblock );
     260        }
     261        unlock( &owner->lock );
     262}
     263
     264void signal( condition * this ) {
     265        __signal_internal( this );
     266}
  • src/libcfa/concurrency/thread.c

    r5f642e38 re3987770  
    3939        this->mon.recursion = 1;
    4040        this->next = NULL;
     41
     42        this->current_monitors      = NULL;
     43        this->current_monitor_count = 0;
    4144}
    4245
Note: See TracChangeset for help on using the changeset viewer.