Changes in / [936a287:72dc82a]


Ignore:
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • doc/proposals/concurrency/thePlan.md

    r936a287 r72dc82a  
    1010done - Multi monitors calls,
    1111done - Monitors as a language feature (not calling enter/leave by hand)
     12
     13_Phase 3_ : Monitor features
    1214Internal scheduling
     15External scheduling
    1316
    14 _Phase 3_ : Kernel features
     17_Phase 4_ : Kernel features
    1518Preemption
    1619Detach thread
    1720Cluster migration
    18 
    19 _Phase 4_ : Monitor features
    20 External scheduling
    2121
    2222_Phase 5_ : Performance
  • src/libcfa/concurrency/invoke.h

    r936a287 r72dc82a  
    3838      };
    3939
     40      struct simple_thread_stack {
     41            struct thread_desc * top;
     42      };
     43
    4044      #ifdef __CFORALL__
    4145      extern "Cforall" {
     
    4347            void append( struct simple_thread_list *, struct thread_desc * );
    4448            struct thread_desc * pop_head( struct simple_thread_list * );
     49
     50            void ?{}( struct simple_thread_stack * );
     51            void push( struct simple_thread_stack *, struct thread_desc * );           
     52            struct thread_desc * pop( struct simple_thread_stack * );
    4553
    4654            void ?{}(spinlock * this);
     
    7482            struct thread_desc * owner;
    7583            struct simple_thread_list entry_queue;
     84            struct simple_thread_stack signal_stack;
     85            struct monitor_desc * stack_owner;
    7686            unsigned int recursion;
    7787      };
  • src/libcfa/concurrency/kernel.c

    r936a287 r72dc82a  
    294294// Scheduler routines
    295295void ScheduleThread( thread_desc * thrd ) {
     296        if( !thrd ) return;
     297
    296298        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
    297299       
     
    468470        return head;
    469471}
     472
     473void ?{}( simple_thread_stack * this ) {
     474        this->top = NULL;
     475}
     476
     477void push( simple_thread_stack * this, thread_desc * t ) {
     478        assert(t->next != NULL);
     479        t->next = this->top;
     480        this->top = t;
     481}
     482
     483thread_desc * pop( simple_thread_stack * this ) {
     484        thread_desc * top = this->top;
     485        if( top ) {
     486                this->top = top->next;
     487                top->next = NULL;
     488        }       
     489        return top;
     490}
    470491// Local Variables: //
    471492// mode: c //
  • src/libcfa/concurrency/monitor

    r936a287 r72dc82a  
    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}
  • src/libcfa/concurrency/monitor.c

    r936a287 r72dc82a  
    1818
    1919#include "kernel_private.h"
     20
     21void set_owner( monitor_desc * this, thread_desc * owner ) {
     22        //Pass the monitor appropriately
     23        this->owner = owner;
     24
     25        //We are passing the monitor to someone else, which means recursion level is not 0
     26        this->recursion = owner ? 1 : 0;
     27}
    2028
    2129extern "C" {
     
    4654        }
    4755
     56        // leave pseudo code :
     57        //      decrement level
     58        //      leve == 0 ?
     59        //              no : done
     60        //              yes :
     61        //                      signal stack empty ?
     62        //                              has leader :
     63        //                                      bulk acquiring means we don't own the signal stack
     64        //                                      ignore it but don't release the monitor
     65        //                              yes :
     66        //                                      next in entry queue is new owner
     67        //                              no :
     68        //                                      top of the signal stack is the owner
     69        //                                      context switch to him right away
     70        //
    4871        void __leave_monitor_desc(monitor_desc * this) {
    4972                lock( &this->lock );
     
    5578                this->recursion -= 1;
    5679
    57                 //If we left the last level of recursion it means we are changing who owns the monitor
     80                //If we haven't left the last level of recursion
     81                //it means we don't need to do anything
     82                if( this->recursion != 0) {
     83                        unlock( &this->lock );
     84                        return;
     85                }
     86                       
     87                //If we don't own the signal stack then just leave it to the owner
     88                if( this->stack_owner ) {
     89                        assert( this->owner == this->stack_owner );
     90                        unlock( &this->lock );
     91                        return;
     92                }
     93
     94                //We are the stack owner and have left the last recursion level.
     95                //We are in charge of passing the monitor
    5896                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 );
    6297
    63                         //We are passing the monitor to someone else, which means recursion level is not 0
    64                         this->recursion = new_owner ? 1 : 0;
    65                 }       
     98                //Check the signaller stack
     99                new_owner = pop( &this->signal_stack );
     100                if( new_owner ) {
     101                        //The signaller stack is not empty,
     102                        //transfer control immediately
     103                        set_owner( this, new_owner );
     104                        ScheduleInternal( &this->lock, new_owner );
     105                        return;
     106                }
     107               
     108                // No signaller thread
     109                // Get the next thread in the entry_queue
     110                new_owner = pop_head( &this->entry_queue );
     111                set_owner( this, new_owner );
    66112
     113                //We can now let other threads in safely
    67114                unlock( &this->lock );
    68115
    69                 //If we have a new owner, we need to wake-up the thread
    70                 if( new_owner ) {
    71                         ScheduleThread( new_owner );
    72                 }
     116                //We need to wake-up the thread
     117                ScheduleThread( new_owner );
    73118        }
    74119}
Note: See TracChangeset for help on using the changeset viewer.