Changes in / [e3987770:5f642e38]


Ignore:
Files:
7 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    re3987770 r5f642e38  
     1
    12%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%%
    23%%
     
    1112%% Created On       : Sat Apr  9 10:06:17 2016
    1213%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Apr 18 17:16:13 2017
    14 %% Update Count     : 270
     14%% Last Modified On : Wed Apr 12 11:32:26 2017
     15%% Update Count     : 257
    1516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1617
     
    3637% Names used in the document.
    3738
    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
     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
    4142\newcommand{\CCeleven}{\rm C\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name
    4243\newcommand{\CCfourteen}{\rm C\kern-.1em\hbox{+\kern-.25em+}14\xspace} % C++14 symbolic name
    4344\newcommand{\CCseventeen}{\rm C\kern-.1em\hbox{+\kern-.25em+}17\xspace} % C++17 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
     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
    4748
    4849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    5455\setlength{\parindentlnth}{\parindent}
    5556
    56 \newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
     57\newlength{\gcolumnposn}                                % temporary hack because lstlisting does handle tabs correctly
    5758\newlength{\columnposn}
    5859\setlength{\gcolumnposn}{2.5in}
     
    273274belowskip=3pt,
    274275% replace/adjust listing characters that look bad in sanserif
    275 literate={-}{\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,
     276literate={-}{\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,
    278279moredelim=**[is][\color{red}]{®}{®},                                    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    279280moredelim=**[is][\color{blue}]{ß}{ß},                                   % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
  • doc/generic_types/generic_types.tex

    re3987770 r5f642e38  
    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.06ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     85literate={-}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.1ex}}}}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.06ex}}}\kern-0.3ex\textgreater}2,
     87        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.1ex}}}\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 A 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.
     400For 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.
    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 );                        $\C{// overloaded foo functions}$
     525[ int, int ] foo$\(_1\)$( int );
    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 unitl @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.
     774The process continues, @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 for any user-defined type with a @?+?@ operator.
     797Furthermore, this code is extendable so 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

    re3987770 r5f642e38  
    1010done - Multi monitors calls,
    1111done - Monitors as a language feature (not calling enter/leave by hand)
     12Internal scheduling
    1213
    13 _Phase 3_ : Monitor features
    14 Internal scheduling
    15 External scheduling
    16 
    17 _Phase 4_ : Kernel features
     14_Phase 3_ : Kernel features
    1815Preemption
    1916Detach thread
    2017Cluster migration
     18
     19_Phase 4_ : Monitor features
     20External scheduling
    2121
    2222_Phase 5_ : Performance
  • doc/user/user.tex

    re3987770 r5f642e38  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Apr 18 17:17:24 2017
    14 %% Update Count     : 1430
     13%% Last Modified On : Wed Apr 12 12:18:58 2017
     14%% Update Count     : 1415
    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 
    3127
    3228\usepackage{fullpage,times,comment}
  • src/libcfa/concurrency/invoke.h

    re3987770 r5f642e38  
    3333      };
    3434
    35       struct __thread_queue_t {
     35      struct simple_thread_list {
    3636            struct thread_desc * head;
    3737            struct thread_desc ** tail;
    3838      };
    3939
    40       struct __thread_stack_t {
    41             struct thread_desc * top;
    42       };
    43 
    4440      #ifdef __CFORALL__
    4541      extern "Cforall" {
    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 * );
     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 * );
    5345
    5446            void ?{}(spinlock * this);
     
    5850
    5951      struct coStack_t {
    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
     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
    6759      };
    6860
     
    7062
    7163      struct coroutine_desc {
    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
     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
    7870      };
    7971
    8072      struct monitor_desc {
    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
     73            struct spinlock lock;
     74            struct thread_desc * owner;
     75            struct simple_thread_list entry_queue;
     76            unsigned int recursion;
    8777      };
    8878
    8979      struct thread_desc {
    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
     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
    9583      };
    9684
  • src/libcfa/concurrency/kernel

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

    re3987770 r5f642e38  
    299299// Scheduler routines
    300300void ScheduleThread( thread_desc * thrd ) {
    301         if( !thrd ) return;
    302 
    303301        assertf( thrd->next == NULL, "Expected null got %p", thrd->next );
    304302       
     
    475473
    476474void ?{}( signal_once * this ) {
    477         this->cond = false;
     475        this->condition = false;
    478476}
    479477void ^?{}( signal_once * this ) {
     
    483481void wait( signal_once * this ) {
    484482        lock( &this->lock );
    485         if( !this->cond ) {
     483        if( !this->condition ) {
    486484                append( &this->blocked, this_thread() );
    487485                ScheduleInternal( &this->lock );
     
    494492        lock( &this->lock );
    495493        {
    496                 this->cond = true;
     494                this->condition = true;
    497495
    498496                thread_desc * it;
     
    506504//-----------------------------------------------------------------------------
    507505// Queues
    508 void ?{}( __thread_queue_t * this ) {
     506void ?{}( simple_thread_list * this ) {
    509507        this->head = NULL;
    510508        this->tail = &this->head;
    511509}
    512510
    513 void append( __thread_queue_t * this, thread_desc * t ) {
     511void append( simple_thread_list * this, thread_desc * t ) {
    514512        assert(this->tail != NULL);
    515513        *this->tail = t;
     
    517515}
    518516
    519 thread_desc * pop_head( __thread_queue_t * this ) {
     517thread_desc * pop_head( simple_thread_list * this ) {
    520518        thread_desc * head = this->head;
    521519        if( head ) {
     
    528526        return head;
    529527}
    530 
    531 void ?{}( __thread_stack_t * this ) {
    532         this->top = NULL;
    533 }
    534 
    535 void push( __thread_stack_t * this, thread_desc * t ) {
    536         assert(t->next != NULL);
    537         t->next = this->top;
    538         this->top = t;
    539 }
    540 
    541 thread_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 }
    549528// Local Variables: //
    550529// mode: c //
  • src/libcfa/concurrency/monitor

    re3987770 r5f642e38  
    1818#define MONITOR_H
    1919
    20 #include <stddef.h>
    21 
    2220#include "assert"
    2321#include "invoke.h"
     
    2523
    2624static inline void ?{}(monitor_desc * this) {
    27         this->owner = NULL;
    28       this->stack_owner = NULL;
     25        this->owner = 0;
    2926        this->recursion = 0;
    3027}
     28
     29//Array entering routine
     30void enter(monitor_desc **, int count);
     31void leave(monitor_desc **, int count);
    3132
    3233struct monitor_guard_t {
    3334        monitor_desc ** m;
    3435        int count;
    35       monitor_desc ** prev_mntrs;
    36       unsigned short  prev_count;
    3736};
    3837
     
    4140}
    4241
    43 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count );
    44 void ^?{}( monitor_guard_t * this );
    45 
    46 //-----------------------------------------------------------------------------
    47 // Internal scheduling
    48 struct condition {
    49         __thread_queue_t blocked;
    50         monitor_desc ** monitors;
    51         unsigned short monitor_count;
    52 };
    53 
    54 static inline void ?{}( condition * this ) {
    55         this->monitors = NULL;
    56         this->monitor_count = 0;
     42static 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 );
    5747}
    5848
    59 void wait( condition * this );
    60 void signal( condition * this );
     49static inline void ^?{}( monitor_guard_t * this ) {
     50        leave( this->m, this->count );
     51}
     52
     53
    6154#endif //MONITOR_H
  • src/libcfa/concurrency/monitor.c

    re3987770 r5f642e38  
    1818
    1919#include "kernel_private.h"
    20 #include "libhdr.h"
    21 
    22 void 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 }
    2920
    3021extern "C" {
    31         void __enter_monitor_desc(monitor_desc * this, monitor_desc * leader) {
     22        void __enter_monitor_desc(monitor_desc * this) {
    3223                lock( &this->lock );
    3324                thread_desc * thrd = this_thread();
    3425
    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 
    4026                if( !this->owner ) {
    4127                        //No one has the monitor, just take it
    42                         set_owner( this, thrd );
     28                        this->owner = thrd;
     29                        this->recursion = 1;
    4330                }
    4431                else if( this->owner == thrd) {
     
    5744
    5845                unlock( &this->lock );
    59                 return;
    6046        }
    6147
    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) {
     48        void __leave_monitor_desc(monitor_desc * this) {
    7849                lock( &this->lock );
    7950
    80                 LIB_DEBUG_PRINT_SAFE("Leaving %p (o: %p, r: %i)\n", this, this->owner, this->recursion);
    81 
    8251                thread_desc * thrd = this_thread();
    83                 assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", this->owner, thrd, this->recursion );
     52                assert( thrd == this->owner );
    8453
    8554                //Leaving a recursion level, decrement the counter
    8655                this->recursion -= 1;
    8756
    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                 // }
     57                //If we left the last level of recursion it means we are changing who owns the monitor
     58                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 );
    10262
    103                 //We are the stack owner and have left the last recursion level.
    104                 //We are in charge of passing the monitor
    105                 thread_desc * new_owner = 0;
     63                        //We are passing the monitor to someone else, which means recursion level is not 0
     64                        this->recursion = new_owner ? 1 : 0;
     65                }       
    10666
    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
    12767                unlock( &this->lock );
    12868
    129                 //We need to wake-up the thread
    130                 ScheduleThread( new_owner );
     69                //If we have a new owner, we need to wake-up the thread
     70                if( new_owner ) {
     71                        ScheduleThread( new_owner );
     72                }
    13173        }
    13274}
    13375
    134 static 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] );
     76void enter(monitor_desc ** monitors, int count) {
     77        for(int i = 0; i < count; i++) {
     78                __enter_monitor_desc( monitors[i] );
    13879        }
    13980}
    14081
    141 static 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] );
     82void leave(monitor_desc ** monitors, int count) {
     83        for(int i = count - 1; i >= 0; i--) {
     84                __leave_monitor_desc( monitors[i] );
    14585        }
    14686}
    147 
    148 void ?{}( 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 
    161 void ^?{}( 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
    170 void 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 
    241 static 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 
    264 void signal( condition * this ) {
    265         __signal_internal( this );
    266 }
  • src/libcfa/concurrency/thread.c

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