Changeset e3987770


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

Files:
7 added
10 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    r5f642e38 re3987770  
    1 
    21%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%%
    32%%
     
    1211%% Created On       : Sat Apr  9 10:06:17 2016
    1312%% Last Modified By : Peter A. Buhr
    14 %% Last Modified On : Wed Apr 12 11:32:26 2017
    15 %% Update Count     : 257
     13%% Last Modified On : Tue Apr 18 17:16:13 2017
     14%% Update Count     : 270
    1615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1716
     
    3736% Names used in the document.
    3837
    39 \newcommand{\CFA}{C$\mathbf\forall$\xspace} % set language symbolic name
    40 \newcommand{\CFL}{Cforall\xspace}               % set language text name
    41 \newcommand{\CC}{\rm C\kern-.1em\hbox{+\kern-.25em+}\xspace} % CC symbolic name
     38\newcommand{\CFA}{C$\mathbf\forall$\xspace} % Cforall symbolic name
     39\newcommand{\CFL}{Cforall\xspace} % Cforall symbolic name
     40\newcommand{\CC}{\rm C\kern-.1em\hbox{+\kern-.25em+}\xspace} % C++ symbolic name
    4241\newcommand{\CCeleven}{\rm C\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name
    4342\newcommand{\CCfourteen}{\rm C\kern-.1em\hbox{+\kern-.25em+}14\xspace} % C++14 symbolic name
    4443\newcommand{\CCseventeen}{\rm C\kern-.1em\hbox{+\kern-.25em+}17\xspace} % C++17 symbolic name
    45 \newcommand{\CCtwenty}{\rm C\kern-.1em\hbox{+\kern-.25em+}20} % C++20 symbolic name
    46 \newcommand{\Celeven}{C11\xspace}               % C11 symbolic name
    47 \newcommand{\Csharp}{C\raisebox{-0.65ex}{\large$^\sharp$}\xspace}       % C# symbolic name
     44\newcommand{\CCtwenty}{\rm C\kern-.1em\hbox{+\kern-.25em+}20\xspace} % C++20 symbolic name
     45\newcommand{\Celeven}{C11\xspace} % C11 symbolic name
     46\newcommand{\Csharp}{C\raisebox{-0.7ex}{\Large$^\sharp$}\xspace} % C# symbolic name
    4847
    4948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    5554\setlength{\parindentlnth}{\parindent}
    5655
    57 \newlength{\gcolumnposn}                                % temporary hack because lstlisting does handle tabs correctly
     56\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    5857\newlength{\columnposn}
    5958\setlength{\gcolumnposn}{2.5in}
     
    274273belowskip=3pt,
    275274% replace/adjust listing characters that look bad in sanserif
    276 literate={-}{\raisebox{-0.15ex}{\texttt{-}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    277         {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {_}{\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    278         {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2,
     275literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     276        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
     277        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
    279278moredelim=**[is][\color{red}]{®}{®},                                    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    280279moredelim=**[is][\color{blue}]{ß}{ß},                                   % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
  • doc/generic_types/generic_types.tex

    r5f642e38 re3987770  
    8383belowskip=3pt,
    8484% replace/adjust listing characters that look bad in sanserif
    85 literate={-}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     85literate={-}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.06ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    8686        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    87         {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.1ex}}}\kern-0.3ex\textgreater}2,
     87        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.06ex}}}\kern-0.3ex\textgreater}2,
    8888moredelim=**[is][\color{red}]{`}{`},
    8989}% lstset
     
    285285if (x) x++                                                                      $\C{// if (x != 0) x += 1;}$
    286286\end{lstlisting}
    287 Every if and iteration statement in C compares the condition with @0@, and every increment and decrement operator is semantically equivalent to adding or subtracting the value @1@ and storing the result.
     287Every @if@ and iteration statement in C compares the condition with @0@, and every increment and decrement operator is semantically equivalent to adding or subtracting the value @1@ and storing the result.
    288288Due to these rewrite rules, the values @0@ and @1@ have the types @zero_t@ and @one_t@ in \CFA, which allows overloading various operations for new types that seamlessly connect to all special @0@ and @1@ contexts.
    289289The types @zero_t@ and @one_t@ have special built in implicit conversions to the various integral types, and a conversion to pointer types for @0@, which allows standard C code involving @0@ and @1@ to work as normal.
     
    398398The \CFA translator template-expands concrete generic-types into new structure types, affording maximal inlining.
    399399To enable inter-operation among equivalent instantiations of a generic type, the translator saves the set of instantiations currently in scope and reuses the generated structure declarations where appropriate.
    400 For example, a function declaration that accepts or returns a concrete generic-type produces a declaration for the instantiated struct in the same scope, which all callers may reuse.
     400A function declaration that accepts or returns a concrete generic-type produces a declaration for the instantiated structure in the same scope, which all callers may reuse.
    401401For example, the concrete instantiation for @pair( const char *, int )@ is:
    402402\begin{lstlisting}
     
    523523However, the \CFA type-system must support significantly more complex composition:
    524524\begin{lstlisting}
    525 [ int, int ] foo$\(_1\)$( int );
     525[ int, int ] foo$\(_1\)$( int );                        $\C{// overloaded foo functions}$
    526526[ double ] foo$\(_2\)$( int );
    527527void bar( int, double, double );
     
    772772Since @sum@\(_0\) does not accept any arguments, it is not a valid candidate function for the call @sum(10, 20, 30)@.
    773773In order to call @sum@\(_1\), @10@ is matched with @x@, and the argument resolution moves on to the argument pack @rest@, which consumes the remainder of the argument list and @Params@ is bound to @[20, 30]@.
    774 The process continues, @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.
     774The process continues unitl @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.
    775775Effectively, this algorithm traces as @sum(10, 20, 30)@ $\rightarrow$ @10 + sum(20, 30)@ $\rightarrow$ @10 + (20 + sum(30))@ $\rightarrow$ @10 + (20 + (30 + sum()))@ $\rightarrow$ @10 + (20 + (30 + 0))@.
    776776
     
    795795\end{lstlisting}
    796796Unlike C variadic functions, it is unnecessary to hard code the number and expected types.
    797 Furthermore, this code is extendable so any user-defined type with a @?+?@ operator.
     797Furthermore, this code is extendable for any user-defined type with a @?+?@ operator.
    798798Summing arbitrary heterogeneous lists is possible with similar code by adding the appropriate type variables and addition operators.
    799799
     
    998998On the other hand, C does not have a generic collections-library in its standard distribution, resulting in frequent reimplementation of such collection types by C programmers.
    999999\CCV does not use the \CC standard template library by construction, and in fact includes the definition of @object@ and wrapper classes for @bool@, @char@, @int@, and @const char *@ in its line count, which inflates this count somewhat, as an actual object-oriented language would include these in the standard library;
    1000 with their omission the \CCV line count is similar to C.
     1000with their omission, the \CCV line count is similar to C.
    10011001We justify the given line count by noting that many object-oriented languages do not allow implementing new interfaces on library types without subclassing or wrapper types, which may be similarly verbose.
    10021002
  • doc/proposals/concurrency/thePlan.md

    r5f642e38 re3987770  
    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
  • doc/user/user.tex

    r5f642e38 re3987770  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Wed Apr 12 12:18:58 2017
    14 %% Update Count     : 1415
     13%% Last Modified On : Tue Apr 18 17:17:24 2017
     14%% Update Count     : 1430
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    2525\usepackage{textcomp}
    2626\usepackage[latin1]{inputenc}
     27% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     28% removes it as a variable-name character so keyworks in variables are highlighted
     29\DeclareTextCommandDefault{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}
     30
    2731
    2832\usepackage{fullpage,times,comment}
  • 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.