Changeset 2b4daf2 for libcfa


Ignore:
Timestamp:
Jan 7, 2021, 5:06:22 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
5ad381b
Parents:
42f6e07 (diff), 58fe85a (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:software/cfa/cfa-cc

Location:
libcfa/src
Files:
5 added
19 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    r42f6e07 r2b4daf2  
    5858        concurrency/iofwd.hfa \
    5959        containers/list.hfa \
    60         containers/stackLockFree.hfa
     60        containers/stackLockFree.hfa \
     61        vec/vec.hfa \
     62        vec/vec2.hfa \
     63        vec/vec3.hfa \
     64        vec/vec4.hfa
    6165
    6266inst_headers_src = \
     
    9498        concurrency/clib/cfathread.h \
    9599        concurrency/invoke.h \
     100        concurrency/future.hfa \
    96101        concurrency/kernel/fwd.hfa
    97102
  • libcfa/src/bits/collection.hfa

    r42f6e07 r2b4daf2  
    11#pragma once
     2#include <stdio.h> // REMOVE THIS AFTER DEBUGGING
     3
    24
    35struct Colable {
    4         Colable * next;                                                                         // next node in the list
     6        struct Colable * next;                                                                          // next node in the list
    57        // invariant: (next != 0) <=> listed()
    68};
    7 
    8 inline {
     9#ifdef __cforall
     10static inline {
    911        // PUBLIC
    1012
     
    2830        }
    2931
    30         // wrappers to make Collection have T
    31         forall( dtype T ) {
    32                 T *& Next( T * n ) {
    33                         return (T *)Next( (Colable *)n );
    34                 }
    35 
    36                 bool listed( T * n ) {
    37                         return Next( (Colable *)n ) != 0p;
    38                 }
    39         } // distribution
     32        // // wrappers to make Collection have T
     33        // forall( dtype T ) {
     34        //      T *& Next( T * n ) {
     35        //              return (T *)Next( (Colable *)n );
     36        //      }
     37        // } // distribution
    4038} // distribution
    4139
     40forall( dtype T | { T *& Next ( T * ); } ) {
     41        bool listed( T * n ) {
     42                return Next( n ) != 0p;
     43        }
     44}
    4245
    4346struct Collection {
     
    4548};
    4649
    47 inline {
     50static inline {
    4851        // class invariant: root == 0 & empty() | *root in *this
    4952        void ?{}( Collection &, const Collection & ) = void; // no copy
     
    6568
    6669struct ColIter {
    67         void * curr;                                                                            // element to be returned by >>
     70        void * curr;                                                                            // element returned by |
    6871};
    6972
    70 inline {
     73static inline {
    7174        void ?{}( ColIter & colIter ) with( colIter ) {
    7275                curr = 0p;
     
    7982        } // distribution
    8083} // distribution
     84#endif
  • libcfa/src/bits/containers.hfa

    r42f6e07 r2b4daf2  
    3636        #define __small_array_t(T) __small_array(T)
    3737#else
    38         #define __small_array_t(T) struct __small_array
     38        #define __small_array_t(T) __small_array
    3939#endif
    4040
  • libcfa/src/bits/defs.hfa

    r42f6e07 r2b4daf2  
    2929#define __cfa_anonymous_object(x) inline struct x
    3030#else
    31 #define __cfa_anonymous_object(x) x __cfa_anonymous_object
     31#define __cfa_anonymous_object(x) struct x __cfa_anonymous_object
    3232#endif
    3333
  • libcfa/src/bits/locks.hfa

    r42f6e07 r2b4daf2  
    283283                void ^?{}(future_t &) {}
    284284
     285                void reset(future_t & this) {
     286                        // needs to be in 0p or 1p
     287                        __atomic_exchange_n( &this.ptr, 0p, __ATOMIC_SEQ_CST);
     288                }
     289
    285290                // check if the future is available
    286291                bool available( future_t & this ) {
     
    340345
    341346                // Mark the future as abandoned, meaning it will be deleted by the server
    342                 void abandon( future_t & this ) {
     347                bool abandon( future_t & this ) {
     348                        /* paranoid */ verify( this.ptr != 3p );
     349
     350                        // Mark the future as abandonned
    343351                        struct oneshot * got = __atomic_exchange_n( &this.ptr, 3p, __ATOMIC_SEQ_CST);
     352
     353                        // If the future isn't already fulfilled, let the server delete it
     354                        if( got == 0p ) return false;
    344355
    345356                        // got == 2p: the future is ready but the context hasn't fully been consumed
     
    347358                        if( got == 2p ) {
    348359                                while( this.ptr != 1p ) Pause();
    349                         }
    350                         return;
     360                                got = 1p;
     361                        }
     362
     363                        // The future is completed delete it now
     364                        /* paranoid */ verify( this.ptr != 1p );
     365                        free( &this );
     366                        return true;
    351367                }
    352368
  • libcfa/src/bits/queue.hfa

    r42f6e07 r2b4daf2  
    33#include "bits/collection.hfa"
    44
    5 forall( dtype T ) {
     5// A Queue(T) is a Collection(T) defining the ordering that nodes are returned by drop() in the same order from those
     6// added by add(). T must be a public descendant of uColable.
     7
     8// The implementation is a typical singly-linked list, except the next field of the last element points to itself
     9// instead of being null.
     10
     11forall( dtype T | { T *& Next ( T * ); } ) {
    612        struct Queue {
    713                inline Collection;                                                              // Plan 9 inheritance
     
    3440                } // post: n == tail() & succ(n) == 0 | n != tail() & *succ(n) in *q
    3541
    36                 void addHead( Queue(T) & q, T & n ) with( q ) {
     42                T & addHead( Queue(T) & q, T & n ) with( q ) {
    3743                        #ifdef __CFA_DEBUG__
    3844                        if ( listed( &n ) ) abort( "(Queue &)%p.addHead( %p ) : Node is already on another list.", &q, &n );
     
    4551                                Next( &n ) = &n;                                                // last node points to itself
    4652                        }
     53                        return n;
    4754                }
    4855
    49                 void addTail( Queue(T) & q, T & n ) with( q ) {
     56                T & addTail( Queue(T) & q, T & n ) with( q ) {
    5057                        #ifdef __CFA_DEBUG__
    5158                        if ( listed( &n ) ) abort( "(Queue &)%p.addTail( %p ) : Node is already on another list.", &q, &n );
     
    5562                        last = &n;
    5663                        Next( &n ) = &n;                                                        // last node points to itself
     64                        return n;
    5765                }
    5866
    59                 void add( Queue(T) & q, T & n ) with( q ) {
    60                         addTail( q, n );
     67                T & add( Queue(T) & q, T & n ) with( q ) {
     68                        return addTail( q, n );
    6169                }
    6270
     
    6472                        T & t = head( q );
    6573                        if ( root ) {
    66                                 root = Next( root );
     74                                root = Next( (T *)root );
    6775                                if ( &head( q ) == &t ) {
    6876                                        root = last = 0p;                                       // only one element
     
    7785                }
    7886
    79                 void remove( Queue(T) & q, T & n ) with( q ) {  // O(n)
     87                T & remove( Queue(T) & q, T & n ) with( q ) {   // O(n)
    8088                        #ifdef __CFA_DEBUG__
    8189                        if ( ! listed( (Colable &)n ) ) abort( "(Queue &)%p.remove( %p ) : Node is not on a list.", &q, &n );
     
    103111                                curr = Next( curr );
    104112                        }
     113                        return n;
    105114                } // post: ! listed( n )
    106115
    107                 T & dropTail( Queue(T) & q ) with( q ) { // O(n)
     116                T & dropTail( Queue(T) & q ) with( q ) {                // O(n)
    108117                        T & n = tail( q );
    109118                        return &n ? remove( q, n ), n : *0p;
     
    142151} // distribution
    143152
    144 forall( dtype T ) {
     153forall( dtype T | { T *& Next ( T * ); } ) {
    145154        struct QueueIter {
    146155                inline ColIter;                                                                 // Plan 9 inheritance
     
    152161                } // post: curr == 0p
    153162
    154                 // create an iterator active in Queue q
     163                // create an iterator active in queue q
    155164                void ?{}( QueueIter(T) & qi, Queue(T) & q ) with( qi ) {
    156165                        curr = &head( q );
     
    161170                } // post: curr = {e in q}
    162171
    163                 // make existing iterator active in Queue q
     172                // make existing iterator active in queue q
    164173                void over( QueueIter(T) & qi, Queue(T) & q ) with( qi ) {
    165174                        curr = &head( q );
    166175                } // post: curr = {e in q}
    167176
    168                 bool ?>>?( QueueIter(T) & qi, T && tp ) with( qi ) {
     177                bool ?|?( QueueIter(T) & qi, T && tp ) with( qi ) {
    169178                        if ( curr ) {
    170179                                &tp = Curr( qi );
     
    174183                        return &tp != 0p;
    175184                }
    176                 // post: elts == null & !operator>>(tp) | elts != null & *tp' in elts & elts' == elts - *tp & operator>>(tp)
     185                // post: elts == null & !operator|(tp) | elts != null & *tp' in elts & elts' == elts - *tp & operator|(tp)
    177186        } // distribution
    178187} // distribution
  • libcfa/src/bits/sequence.hfa

    r42f6e07 r2b4daf2  
    22
    33#include "bits/collection.hfa"
     4#include "bits/defs.hfa"
    45
    56struct Seqable {
    6         inline Colable;
    7         Seqable * back;                                                                         // pointer to previous node in the list
     7        __cfa_anonymous_object(Colable);
     8        struct Seqable * back;                                                                          // pointer to previous node in the list
    89};
    910
    10 inline {
     11#ifdef __cforall
     12static inline {
    1113        // PUBLIC
    1214
     
    2628        }
    2729
    28         // wrappers to make Collection have T
    29         forall( dtype T ) {
    30                 T *& Back( T * n ) {
    31                         return (T *)Back( (Seqable *)n );
    32                 }
    33         } // distribution
     30        // // wrappers to make Collection have T
     31        // forall( dtype T ) {
     32        //      T *& Back( T * n ) {
     33        //              return (T *)Back( (Seqable *)n );
     34        //      }
     35        // } // distribution
    3436} // distribution
    3537
    36 forall( dtype T ) {
     38
     39// A Sequence(T) is a Collection(T) defining the ordering of a uStack and uQueue, and to insert and remove elements
     40// anywhere in the sequence. T must be a public descendant of uSeqable.
     41
     42// The implementation is a typical doubly-linked list, except the next field of the last node points at the first node
     43// and the back field of the last node points at the first node (circular).
     44
     45forall( dtype T | { T *& Back ( T * ); T *& Next ( T * ); } ) {
    3746        struct Sequence {
    3847                inline Collection;                                                              // Plan 9 inheritance
    3948        };
    4049
    41         inline {
     50        static inline {
    4251                // wrappers to make Collection have T
    4352                T & head( Sequence(T) & s ) with( s ) {
     
    5059                void ?{}( Sequence(T) & s ) with( s ) {
    5160                        ((Collection &)s){};
    52                 }       // post: isEmpty().
    53 
    54                 // Return a pointer to the last sequence element, without removing it. 
     61                }       // post: isEmpty()
     62
     63                // Return a pointer to the last sequence element, without removing it.
    5564                T & tail( Sequence(T) & s ) with( s ) {
    5665                        return root ? (T &)*Back( &head( s ) ) : *0p;
     
    6574                } // post: n == tail() & succ(n) == 0 | n != tail() & *succ(n) in *s
    6675
    67                 // Return a pointer to the element before *n, or 0p if there isn't one.
     76                // Return a pointer to the element before *n, or 0p if list empty.
    6877                T * pred( Sequence(T) & s, T * n ) with( s ) {  // pre: *n in *s
    6978                        #ifdef __CFA_DEBUG__
     
    7180                        #endif // __CFA_DEBUG__
    7281                        return n == &head( s ) ? 0p : Back( n );
    73                 }       // post: n == head() & head(n) == 0 | n != head() & *pred(n) in *s
    74 
    75 
    76                 // Insert *n into the sequence before *bef, or at the end if bef == 0.
    77                 void insertBef( Sequence(T) & s, T & n, T & bef ) with( s ) { // pre: !n->listed() & *bef in *s
     82                } // post: n == head() & head(n) == 0 | n != head() & *pred(n) in *s
     83
     84
     85                // Insert *n into the sequence before *bef, or at the end if bef == 0p.
     86                T & insertBef( Sequence(T) & s, T & n, T & bef ) with( s ) { // pre: !n->listed() & *bef in *s
    7887                        #ifdef __CFA_DEBUG__
    7988                        if ( listed( &n ) ) abort( "(Sequence &)%p.insertBef( %p, %p ) : Node is already on another list.", &s, n, &bef );
     
    103112                                Next( Back( &n ) ) = &n;
    104113                        } // if
     114                        return n;
    105115                }       // post: n->listed() & *n in *s & succ(n) == bef
    106116
    107117
    108118                // Insert *n into the sequence after *aft, or at the beginning if aft == 0.
    109                 void insertAft( Sequence(T) & s, T & aft, T & n ) with( s ) {   // pre: !n->listed() & *aft in *s
     119                T & insertAft( Sequence(T) & s, T & aft, T & n ) with( s ) {    // pre: !n->listed() & *aft in *s
    110120                        #ifdef __CFA_DEBUG__
    111121                        if ( listed( &n ) ) abort( "(Sequence &)%p.insertAft( %p, %p ) : Node is already on another list.", &s, &aft, &n );
     
    133143                                Next( &aft ) = &n;
    134144                        } // if
    135                 }         // post: n->listed() & *n in *s & succ(n) == bef
     145                        return n;
     146                } // post: n->listed() & *n in *s & succ(n) == bef
    136147               
    137148                // pre: n->listed() & *n in *s
    138                 void remove( Sequence(T) & s, T & n ) with( s ) { // O(1)
     149                T & remove( Sequence(T) & s, T & n ) with( s ) { // O(1)
    139150                        #ifdef __CFA_DEBUG__
    140151                        if ( ! listed( &n ) ) abort( "(Sequence &)%p.remove( %p ) : Node is not on a list.", &s, &n );
     
    147158                        Next( Back( &n ) ) = Next( &n );
    148159                        Next( &n ) = Back( &n ) = 0p;
    149                 }                                                       // post: !n->listed().
     160                        return n;
     161                } // post: !n->listed()
    150162
    151163                // Add an element to the head of the sequence.
    152                 void addHead( Sequence(T) & s, T & n ) {                // pre: !n->listed(); post: n->listed() & head() == n
    153                         insertAft( s, *0p, n );
    154                 }
     164                T & addHead( Sequence(T) & s, T & n ) {                 // pre: !n->listed(); post: n->listed() & head() == n
     165                        return insertAft( s, *0p, n );
     166                }
     167
    155168                // Add an element to the tail of the sequence.
    156                 void addTail( Sequence(T) & s, T & n ) {                // pre: !n->listed(); post: n->listed() & head() == n
    157                         insertBef( s, n, *0p );
    158                 }
     169                T & addTail( Sequence(T) & s, T & n ) {                 // pre: !n->listed(); post: n->listed() & head() == n
     170                        return insertBef( s, n, *0p );
     171                }
     172
    159173                // Add an element to the tail of the sequence.
    160                 void add( Sequence(T) & s, T & n ) {                    // pre: !n->listed(); post: n->listed() & head() == n
    161                         addTail( s, n );
    162                 }
     174                T & add( Sequence(T) & s, T & n ) {                             // pre: !n->listed(); post: n->listed() & head() == n
     175                        return addTail( s, n );
     176                }
     177
    163178                // Remove and return the head element in the sequence.
    164179                T & dropHead( Sequence(T) & s ) {
     
    166181                        return &n ? remove( s, n ), n : *0p;
    167182                }
     183
    168184                // Remove and return the head element in the sequence.
    169185                T & drop( Sequence(T) & s ) {
    170186                        return dropHead( s );
    171187                }
     188
    172189                // Remove and return the tail element in the sequence.
    173190                T & dropTail( Sequence(T) & s ) {
     
    184201                                T * toEnd = Back( &head( s ) );
    185202                                T * fromEnd = Back( &head( from ) );
    186                                 Back( root ) = fromEnd;
     203                                Back( (T *)root ) = fromEnd;
    187204                                Next( fromEnd ) = &head( s );
    188                                 Back( from.root ) = toEnd;
     205                                Back( (T *)from.root ) = toEnd;
    189206                                Next( toEnd ) = &head( from );
    190207                        } // if
     
    214231} // distribution
    215232
    216 forall( dtype T ) {
     233forall( dtype T | { T *& Back ( T * ); T *& Next ( T * ); } ) {
    217234        // SeqIter(T) is used to iterate over a Sequence(T) in head-to-tail order.
    218235        struct SeqIter {
     
    224241        };
    225242
    226         inline {
     243        static inline {
    227244                void ?{}( SeqIter(T) & si ) with( si ) {
    228245                        ((ColIter &)si){};
    229246                        seq = 0p;
    230                 } // post: elts = null.
    231 
     247                } // post: elts = null
     248
     249                // Create a iterator active in sequence s.
    232250                void ?{}( SeqIter(T) & si, Sequence(T) & s ) with( si ) {
    233251                        ((ColIter &)si){};
    234252                        seq = &s;
    235253                        curr = &head( s );
    236                 } // post: elts = null.
     254                } // post: elts = null
    237255
    238256                void ?{}( SeqIter(T) & si, Sequence(T) & s, T & start ) with( si ) {
     
    240258                        seq = &s;
    241259                        curr = &start;
    242                 } // post: elts = null.
    243 
     260                } // post: elts = null
     261
     262                // Make the iterator active in sequence s.
    244263                void over( SeqIter(T) & si, Sequence(T) & s ) with( si ) {
    245264                        seq = &s;
    246265                        curr = &head( s );
    247                 } // post: elts = {e in s}.
    248 
    249                 bool ?>>?( SeqIter(T) & si, T && tp ) with( si ) {
     266                } // post: elts = {e in s}
     267
     268                bool ?|?( SeqIter(T) & si, T && tp ) with( si ) {
    250269                        if ( curr ) {
    251270                                &tp = Curr( si );
     
    265284        };
    266285
    267         inline {
     286        static inline {
    268287                void ?{}( SeqIterRev(T) & si ) with( si ) {     
    269288                        ((ColIter &)si){};
    270289                        seq = 0p;
    271                 } // post: elts = null.
    272 
     290                } // post: elts = null
     291
     292                // Create a iterator active in sequence s.
    273293                void ?{}( SeqIterRev(T) & si, Sequence(T) & s ) with( si ) {   
    274294                        ((ColIter &)si){};
    275295                        seq = &s;
    276296                        curr = &tail( s );
    277                 } // post: elts = null.
     297                } // post: elts = null
    278298
    279299                void ?{}( SeqIterRev(T) & si, Sequence(T) & s, T & start ) with( si ) {
     
    281301                        seq = &s;
    282302                        curr = &start;
    283                 } // post: elts = null.
    284 
     303                } // post: elts = null
     304
     305                // Make the iterator active in sequence s.
    285306                void over( SeqIterRev(T) & si, Sequence(T) & s ) with( si ) {
    286307                        seq = &s;
    287308                        curr = &tail( s );
    288                 } // post: elts = {e in s}.
    289 
    290                 bool ?>>?( SeqIterRev(T) & si, T && tp ) with( si ) {
     309                } // post: elts = {e in s}
     310
     311                bool ?|?( SeqIterRev(T) & si, T && tp ) with( si ) {
    291312                        if ( curr ) {
    292313                                &tp = Curr( si );
     
    298319        } // distribution
    299320} // distribution
     321
     322#endif
  • libcfa/src/bits/stack.hfa

    r42f6e07 r2b4daf2  
    33#include "bits/collection.hfa"
    44
    5 forall( dtype T ) {
     5// A Stack(T) is a Collection(T) defining the ordering that nodes are returned by drop() in the reverse order from those
     6// added by add(). T must be a public descendant of uColable.
     7
     8// The implementation is a typical singly-linked list, except the next field of the last element points to itself
     9// instead of being null.
     10
     11forall( dtype T | { T *& Next ( T * ); } ) {
    612        struct Stack {
    713                inline Collection;                                                              // Plan 9 inheritance
     
    2531                }
    2632
    27                 void addHead( Stack(T) & s, T & n ) with( s ) {
     33                T & addHead( Stack(T) & s, T & n ) with( s ) {
    2834                        #ifdef __CFA_DEBUG__
    2935                        if ( listed( (Colable &)(n) ) ) abort( "(Stack &)%p.addHead( %p ) : Node is already on another list.", &s, n );
     
    3137                        Next( &n ) = &head( s ) ? &head( s ) : &n;
    3238                        root = &n;
     39                        return n;
    3340                }
    3441
    35                 void add( Stack(T) & s, T & n ) with( s ) {
    36                         addHead( s, n );
     42                T & add( Stack(T) & s, T & n ) with( s ) {
     43                        return addHead( s, n );
    3744                }
    3845
    39                 void push( Stack(T) & s, T & n ) with( s ) {
    40                         addHead( s, n );
     46                T & push( Stack(T) & s, T & n ) with( s ) {
     47                        return addHead( s, n );
    4148                }
    4249
     
    4451                        T & t = head( s );
    4552                        if ( root ) {
    46                                 root = ( T *)Next( root );
     53                                root = ( T *)Next( (T *)root );
    4754                                if ( &head( s ) == &t ) root = 0p;              // only one element ?
    4855                                Next( &t ) = 0p;
     
    5764} // distribution
    5865
     66// A StackIter(T) is a subclass of ColIter(T) that generates the elements of a Stack(T).  It returns the elements in the
     67// order returned by drop().
    5968
    60 forall( dtype T ) {
     69forall( dtype T | { T *& Next ( T * ); } ) {
    6170        struct StackIter {
    6271                inline ColIter;                                                                 // Plan 9 inheritance
     
    6877                } // post: curr == 0p
    6978
    70                 // create an iterator active in Stack s
     79                // create an iterator active in stack s
    7180                void ?{}( StackIter(T) & si, Stack(T) & s ) with( si ) {
    7281                        curr = &head( s );
     
    7786                } // post: curr = {e in s}
    7887
    79                 // make existing iterator active in Stack q
     88                // make existing iterator active in stack s
    8089                void over( StackIter(T) & si, Stack(T) & s ) with( si ) {
    8190                        curr = &head( s );
    8291                } // post: curr = {e in s}
    8392
    84                 bool ?>>?( StackIter(T) & si, T && tp ) with( si ) {
     93                bool ?|?( StackIter(T) & si, T && tp ) with( si ) {
    8594                        if ( curr ) {
    8695                                &tp = Curr( si );
  • libcfa/src/concurrency/invoke.h

    r42f6e07 r2b4daf2  
    189189                struct __monitor_group_t monitors;
    190190
     191                // used to put threads on user data structures
     192                struct {
     193                        struct $thread * next;
     194                        struct $thread * back;
     195                } seqable;
     196
    191197                struct {
    192198                        struct $thread * next;
     
    218224                }
    219225
     226                static inline $thread *& Back( $thread * this ) __attribute__((const)) {
     227                        return this->seqable.back;
     228                }
     229
     230                static inline $thread *& Next( $thread * this ) __attribute__((const)) {
     231                        return this->seqable.next;
     232                }
     233
     234                static inline bool listed( $thread * this ) {
     235                        return this->seqable.next != 0p;
     236                }
     237
    220238                static inline void ?{}(__monitor_group_t & this) {
    221239                        (this.data){0p};
  • libcfa/src/concurrency/kernel/startup.cfa

    r42f6e07 r2b4daf2  
    118118
    119119extern size_t __page_size;
     120extern int __map_prot;
    120121
    121122//-----------------------------------------------------------------------------
     
    725726                }
    726727        #else
     728                __cfaabi_dbg_debug_do(
     729                        // pthread has no mechanism to create the guard page in user supplied stack.
     730                        if ( mprotect( stack, __page_size, __map_prot ) == -1 ) {
     731                                abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
     732                        } // if
     733                );
    727734                free( stack );
    728735        #endif
  • libcfa/src/concurrency/locks.cfa

    r42f6e07 r2b4daf2  
    11#include "locks.hfa"
    22#include "kernel_private.hfa"
    3 #include <stdlib.h>
    4 #include <stdio.h>
    53
    64#include <kernel.hfa>
    75#include <stdlib.hfa>
    8 #include <thread.hfa>
    9 
    10 ///////////////////////////////////////////////////////////////////
    11 //// info_thread
    12 ///////////////////////////////////////////////////////////////////
    13 
     6
     7//-----------------------------------------------------------------------------
     8// info_thread
    149forall(dtype L | is_blocking_lock(L)) {
    15         void ?{}( info_thread(L) & this, $thread * t ) {
    16                 ((Seqable &) this){};
    17                 this.t = t;
    18                 this.lock = 0p;
    19                 this.listed = false;
    20         }
    21 
    22         void ?{}( info_thread(L) & this, $thread * t, uintptr_t info ) {
     10        struct info_thread {
     11                // used to put info_thread on a dl queue (aka sequence)
     12                inline Seqable;
     13
     14                // waiting thread
     15                struct $thread * t;
     16
     17                // shadow field
     18                uintptr_t info;
     19
     20                // lock that is passed to wait() (if one is passed)
     21                L * lock;
     22
     23                // true when signalled and false when timeout wakes thread
     24                bool signalled;
     25        };
     26
     27        void ?{}( info_thread(L) & this, $thread * t, uintptr_t info, L * l ) {
    2328                ((Seqable &) this){};
    2429                this.t = t;
    2530                this.info = info;
    26                 this.lock = 0p;
    27                 this.listed = false;
    28         }
    29 
    30         void ^?{}( info_thread(L) & this ){ }
    31 }
    32 
    33 ///////////////////////////////////////////////////////////////////
    34 //// Blocking Locks
    35 ///////////////////////////////////////////////////////////////////
    36 
     31                this.lock = l;
     32        }
     33
     34        void ^?{}( info_thread(L) & this ) {}
     35
     36        info_thread(L) *& Back( info_thread(L) * this ) {
     37                return (info_thread(L) *)Back( (Seqable *)this );
     38        }
     39
     40        info_thread(L) *& Next( info_thread(L) * this ) {
     41                return (info_thread(L) *)Next( (Colable *)this );
     42        }
     43}
     44
     45//-----------------------------------------------------------------------------
     46// Blocking Locks
    3747void ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner ) {
    3848        this.lock{};
     
    4656
    4757void ^?{}( blocking_lock & this ) {}
    48 void ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };}
     58void  ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };}
    4959void ^?{}( single_acquisition_lock & this ) {}
    50 void ?{}( owner_lock & this ) {((blocking_lock &)this){ true, true };}
     60void  ?{}( owner_lock & this ) {((blocking_lock &)this){ true, true };}
    5161void ^?{}( owner_lock & this ) {}
    52 void ?{}( multiple_acquisition_lock & this ) {((blocking_lock &)this){ true, false };}
     62void  ?{}( multiple_acquisition_lock & this ) {((blocking_lock &)this){ true, false };}
    5363void ^?{}( multiple_acquisition_lock & this ) {}
    5464
    5565void lock( blocking_lock & this ) with( this ) {
    5666        lock( lock __cfaabi_dbg_ctx2 );
    57         if ( owner == active_thread() && !multi_acquisition) {
    58                 abort("A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock.");
    59         } else if ( owner != 0p && owner != active_thread() ) {
    60                 append( blocked_threads, active_thread() );
     67        $thread * thrd = active_thread();
     68
     69        // single acquisition lock is held by current thread
     70        /* paranoid */ verifyf( owner != thrd || multi_acquisition, "Single acquisition lock holder (%p) attempted to reacquire the lock %p resulting in a deadlock.", owner, &this );
     71
     72        // lock is held by some other thread
     73        if ( owner != 0p && owner != thrd ) {
     74                addTail( blocked_threads, *thrd );
    6175                wait_count++;
    6276                unlock( lock );
    6377                park( );
    64         } else if ( owner == active_thread() && multi_acquisition ) {
     78        }
     79        // multi acquisition lock is held by current thread
     80        else if ( owner == thrd && multi_acquisition ) {
    6581                recursion_count++;
    6682                unlock( lock );
    67         } else {
    68                 owner = active_thread();
     83        }
     84        // lock isn't held
     85        else {
     86                owner = thrd;
    6987                recursion_count = 1;
    7088                unlock( lock );
     
    7593        bool ret = false;
    7694        lock( lock __cfaabi_dbg_ctx2 );
     95
     96        // lock isn't held
    7797        if ( owner == 0p ) {
    7898                owner = active_thread();
    7999                recursion_count = 1;
    80100                ret = true;
    81         } else if ( owner == active_thread() && multi_acquisition ) {
     101        }
     102        // multi acquisition lock is held by current thread
     103        else if ( owner == active_thread() && multi_acquisition ) {
    82104                recursion_count++;
    83105                ret = true;
    84106        }
     107
    85108        unlock( lock );
    86109        return ret;
    87110}
    88111
    89 void unlock_error_check( blocking_lock & this ) with( this ) {
    90         if ( owner == 0p ){ // no owner implies lock isn't held
    91                 abort( "There was an attempt to release a lock that isn't held" );
    92         } else if ( strict_owner && owner != active_thread() ) {
    93                 abort( "A thread other than the owner attempted to release an owner lock" );
    94         }
    95 }
    96 
    97112void pop_and_set_new_owner( blocking_lock & this ) with( this ) {
    98         $thread * t = pop_head( blocked_threads );
     113        $thread * t = &dropHead( blocked_threads );
    99114        owner = t;
    100115        recursion_count = ( t ? 1 : 0 );
     
    105120void unlock( blocking_lock & this ) with( this ) {
    106121        lock( lock __cfaabi_dbg_ctx2 );
    107         unlock_error_check( this );
     122        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
     123        /* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
     124
     125        // if recursion count is zero release lock and set new owner if one is waiting
    108126        recursion_count--;
    109127        if ( recursion_count == 0 ) {
     
    125143}
    126144
    127 void add_( blocking_lock & this, $thread * t ) with( this ) {
    128     lock( lock __cfaabi_dbg_ctx2 );
     145void on_notify( blocking_lock & this, $thread * t ) with( this ) {
     146        lock( lock __cfaabi_dbg_ctx2 );
     147        // lock held
    129148        if ( owner != 0p ) {
    130                 append( blocked_threads, t );
     149                addTail( blocked_threads, *t );
    131150                wait_count++;
    132151                unlock( lock );
    133         } else {
     152        }
     153        // lock not held
     154        else {
    134155                owner = t;
    135156                recursion_count = 1;
     
    139160}
    140161
    141 void remove_( blocking_lock & this ) with( this ) {
    142     lock( lock __cfaabi_dbg_ctx2 );
    143         unlock_error_check( this );
     162void on_wait( blocking_lock & this ) with( this ) {
     163        lock( lock __cfaabi_dbg_ctx2 );
     164        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
     165        /* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
     166
    144167        pop_and_set_new_owner( this );
    145168        unlock( lock );
    146169}
    147170
    148 ///////////////////////////////////////////////////////////////////
    149 //// Overloaded routines for traits
    150 ///////////////////////////////////////////////////////////////////
    151 
    152 // This is temporary until an inheritance bug is fixed
    153 
    154 void lock( single_acquisition_lock & this ){ lock( (blocking_lock &)this ); }
    155 void unlock( single_acquisition_lock & this ){ unlock( (blocking_lock &)this ); }
    156 void add_( single_acquisition_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); }
    157 void remove_( single_acquisition_lock & this ){ remove_( (blocking_lock &)this ); }
    158 void set_recursion_count( single_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
    159 size_t get_recursion_count( single_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
    160 
    161 void lock( owner_lock & this ){ lock( (blocking_lock &)this ); }
    162 void unlock( owner_lock & this ){ unlock( (blocking_lock &)this ); }
    163 void add_( owner_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); }
    164 void remove_( owner_lock & this ){ remove_( (blocking_lock &)this ); }
    165 void set_recursion_count( owner_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
    166 size_t get_recursion_count( owner_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
    167 
    168 void lock( multiple_acquisition_lock & this ){ lock( (blocking_lock &)this ); }
    169 void unlock( multiple_acquisition_lock & this ){ unlock( (blocking_lock &)this ); }
    170 void add_( multiple_acquisition_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); }
    171 void remove_( multiple_acquisition_lock & this ){ remove_( (blocking_lock &)this ); }
    172 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
     171//-----------------------------------------------------------------------------
     172// Overloaded routines for traits
     173// These routines are temporary until an inheritance bug is fixed
     174void   lock      ( single_acquisition_lock & this ) { lock   ( (blocking_lock &)this ); }
     175void   unlock    ( single_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); }
     176void   on_wait   ( single_acquisition_lock & this ) { on_wait( (blocking_lock &)this ); }
     177void   on_notify ( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
     178void   set_recursion_count( single_acquisition_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
     179size_t get_recursion_count( single_acquisition_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
     180
     181void   lock     ( owner_lock & this ) { lock   ( (blocking_lock &)this ); }
     182void   unlock   ( owner_lock & this ) { unlock ( (blocking_lock &)this ); }
     183void   on_wait  ( owner_lock & this ) { on_wait( (blocking_lock &)this ); }
     184void   on_notify( owner_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
     185void   set_recursion_count( owner_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
     186size_t get_recursion_count( owner_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
     187
     188void   lock     ( multiple_acquisition_lock & this ) { lock   ( (blocking_lock &)this ); }
     189void   unlock   ( multiple_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); }
     190void   on_wait  ( multiple_acquisition_lock & this ) { on_wait( (blocking_lock &)this ); }
     191void   on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); }
     192void   set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
    173193size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
    174194
    175 ///////////////////////////////////////////////////////////////////
    176 //// condition variable
    177 ///////////////////////////////////////////////////////////////////
    178 
     195//-----------------------------------------------------------------------------
     196// alarm node wrapper
    179197forall(dtype L | is_blocking_lock(L)) {
     198        struct alarm_node_wrap {
     199                alarm_node_t alarm_node;
     200                condition_variable(L) * cond;
     201                info_thread(L) * i;
     202        };
     203
     204        void ?{}( alarm_node_wrap(L) & this, Time alarm, Duration period, Alarm_Callback callback, condition_variable(L) * c, info_thread(L) * i ) {
     205                this.alarm_node{ callback, alarm, period };
     206                this.cond = c;
     207                this.i = i;
     208        }
     209
     210        void ^?{}( alarm_node_wrap(L) & this ) { }
    180211
    181212        void timeout_handler ( alarm_node_wrap(L) & this ) with( this ) {
    182         // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
    183             lock( cond->lock __cfaabi_dbg_ctx2 );
    184            
    185             if ( i->listed ) {                  // is thread on queue
    186                 cond->last_thread = i;          // REMOVE THIS AFTER DEBUG
    187                         remove( cond->blocked_threads, *i );             //remove this thread O(1)
     213                // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
     214                lock( cond->lock __cfaabi_dbg_ctx2 );
     215
     216                // this check is necessary to avoid a race condition since this timeout handler
     217                //      may still be called after a thread has been removed from the queue but
     218                //      before the alarm is unregistered
     219                if ( listed(i) ) {      // is thread on queue
     220                        i->signalled = false;
     221                        // remove this thread O(1)
     222                        remove( cond->blocked_threads, *i );
    188223                        cond->count--;
    189                         if( !i->lock ) {
     224                        if( i->lock ) {
     225                                // call lock's on_notify if a lock was passed
     226                                on_notify(*i->lock, i->t);
     227                        } else {
     228                                // otherwise wake thread
    190229                                unpark( i->t );
    191                 } else {
    192                         add_(*i->lock, i->t);                   // call lock's add_
    193                 }
    194             }
    195             unlock( cond->lock );
    196         }
    197 
     230                        }
     231                }
     232                unlock( cond->lock );
     233        }
     234
     235        // this casts the alarm node to our wrapped type since we used type erasure
    198236        void alarm_node_wrap_cast( alarm_node_t & a ) { timeout_handler( (alarm_node_wrap(L) &)a ); }
     237}
     238
     239//-----------------------------------------------------------------------------
     240// condition variable
     241forall(dtype L | is_blocking_lock(L)) {
    199242
    200243        void ?{}( condition_variable(L) & this ){
     
    202245                this.blocked_threads{};
    203246                this.count = 0;
    204                 this.last_thread = 0p; // REMOVE AFTER DEBUG
    205247        }
    206248
    207249        void ^?{}( condition_variable(L) & this ){ }
    208 
    209         void ?{}( alarm_node_wrap(L) & this, Time alarm, Duration period, Alarm_Callback callback ) {
    210                 this.alarm_node{ callback, alarm, period };
    211         }
    212 
    213         void ^?{}( alarm_node_wrap(L) & this ) { }
    214250
    215251        void process_popped( condition_variable(L) & this, info_thread(L) & popped ) with( this ) {
    216252                if(&popped != 0p) {
    217                         popped.listed = false;
     253                        popped.signalled = true;
    218254                        count--;
    219255                        if (popped.lock) {
    220                                 add_(*popped.lock, popped.t);
     256                                // if lock passed call on_notify
     257                                on_notify(*popped.lock, popped.t);
    221258                        } else {
     259                                // otherwise wake thread
    222260                                unpark(popped.t);
    223261                        }
     
    252290
    253291        size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) {
     292                // add info_thread to waiting queue
    254293                addTail( blocked_threads, *i );
    255294                count++;
    256                 i->listed = true;
    257295                size_t recursion_count = 0;
    258296                if (i->lock) {
    259                         i->t->link.next = 1p;
     297                        // if lock was passed get recursion count to reset to after waking thread
    260298                        recursion_count = get_recursion_count(*i->lock);
    261                         remove_( *i->lock );
     299                        on_wait( *i->lock );
    262300                }
    263301                return recursion_count;
     
    269307                size_t recursion_count = queue_and_get_recursion(this, &i);
    270308                unlock( lock );
    271                 park( ); // blocks here
    272                 if (i.lock) set_recursion_count(*i.lock, recursion_count); // resets recursion count here after waking
    273         }
     309
     310                // blocks here
     311                park( );
     312
     313                // resets recursion count here after waking
     314                if (i.lock) set_recursion_count(*i.lock, recursion_count);
     315        }
     316
     317        #define WAIT( u, l ) \
     318                info_thread( L ) i = { active_thread(), u, l }; \
     319                queue_info_thread( this, i );
    274320
    275321        // helper for wait()'s' with a timeout
     
    277323                lock( lock __cfaabi_dbg_ctx2 );
    278324                size_t recursion_count = queue_and_get_recursion(this, &info);
    279                 alarm_node_wrap(L) node_wrap = { t, 0`s, alarm_node_wrap_cast };
    280                 node_wrap.cond = &this;
    281                 node_wrap.i = &info;
     325                alarm_node_wrap(L) node_wrap = { t, 0`s, alarm_node_wrap_cast, &this, &info };
    282326                register_self( &node_wrap.alarm_node );
    283327                unlock( lock );
     328
     329                // blocks here
    284330                park();
     331
     332                // unregisters alarm so it doesn't go off if this happens first
    285333                unregister_self( &node_wrap.alarm_node );
     334
     335                // resets recursion count here after waking
    286336                if (info.lock) set_recursion_count(*info.lock, recursion_count);
    287337        }
    288338
    289         void wait( condition_variable(L) & this ) with(this) {
    290                 info_thread( L ) i = { active_thread() };
    291                 queue_info_thread( this, i );
    292         }
    293 
    294         void wait( condition_variable(L) & this, uintptr_t info ) with(this) {
    295                 info_thread( L ) i = { active_thread(), info };
    296                 queue_info_thread( this, i );
    297         }
    298        
    299         void wait( condition_variable(L) & this, Duration duration ) with(this) {
    300                 info_thread( L ) i = { active_thread() };
    301                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    302         }
    303 
    304         void wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) {
    305                 info_thread( L ) i = { active_thread(), info };
    306                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    307         }
    308 
    309         void wait( condition_variable(L) & this, Time time ) with(this) {
    310                 info_thread( L ) i = { active_thread() };
    311                 queue_info_thread_timeout(this, i, time);
    312         }
    313 
    314         void wait( condition_variable(L) & this, uintptr_t info, Time time ) with(this) {
    315                 info_thread( L ) i = { active_thread(), info };
    316                 queue_info_thread_timeout(this, i, time);
    317         }
    318 
    319         void wait( condition_variable(L) & this, L & l ) with(this) {
    320                 info_thread(L) i = { active_thread() };
    321                 i.lock = &l;
    322                 queue_info_thread( this, i );
    323         }
    324 
    325         void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) {
    326                 info_thread(L) i = { active_thread(), info };
    327                 i.lock = &l;
    328                 queue_info_thread( this, i );
    329         }
    330        
    331         void wait( condition_variable(L) & this, L & l, Duration duration ) with(this) {
    332                 info_thread(L) i = { active_thread() };
    333                 i.lock = &l;
    334                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    335         }
    336        
    337         void wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) {
    338                 info_thread(L) i = { active_thread(), info };
    339                 i.lock = &l;
    340                 queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
    341         }
    342        
    343         void wait( condition_variable(L) & this, L & l, Time time ) with(this) {
    344                 info_thread(L) i = { active_thread() };
    345                 i.lock = &l;
    346                 queue_info_thread_timeout(this, i, time );
    347         }
    348        
    349         void wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ) with(this) {
    350                 info_thread(L) i = { active_thread(), info };
    351                 i.lock = &l;
    352                 queue_info_thread_timeout(this, i, time );
    353         }
    354 }
     339        #define WAIT_TIME( u, l, t ) \
     340                info_thread( L ) i = { active_thread(), u, l }; \
     341                queue_info_thread_timeout(this, i, t ); \
     342                return i.signalled;
     343
     344        void wait( condition_variable(L) & this                        ) with(this) { WAIT( 0, 0p    ) }
     345        void wait( condition_variable(L) & this, uintptr_t info        ) with(this) { WAIT( info, 0p ) }
     346        void wait( condition_variable(L) & this, L & l                 ) with(this) { WAIT( 0, &l    ) }
     347        void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) { WAIT( info, &l ) }
     348
     349        bool wait( condition_variable(L) & this, Duration duration                        ) with(this) { WAIT_TIME( 0   , 0p , __kernel_get_time() + duration ) }
     350        bool wait( condition_variable(L) & this, uintptr_t info, Duration duration        ) with(this) { WAIT_TIME( info, 0p , __kernel_get_time() + duration ) }
     351        bool wait( condition_variable(L) & this, Time time                                ) with(this) { WAIT_TIME( 0   , 0p , time ) }
     352        bool wait( condition_variable(L) & this, uintptr_t info, Time time                ) with(this) { WAIT_TIME( info, 0p , time ) }
     353        bool wait( condition_variable(L) & this, L & l, Duration duration                 ) with(this) { WAIT_TIME( 0   , &l , __kernel_get_time() + duration ) }
     354        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, &l , __kernel_get_time() + duration ) }
     355        bool wait( condition_variable(L) & this, L & l, Time time                         ) with(this) { WAIT_TIME( 0   , &l , time ) }
     356        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Time time         ) with(this) { WAIT_TIME( info, &l , time ) }
     357}
  • libcfa/src/concurrency/locks.hfa

    r42f6e07 r2b4daf2  
    33#include <stdbool.h>
    44
    5 #include "bits/algorithm.hfa"
    65#include "bits/locks.hfa"
    76#include "bits/sequence.hfa"
    8 #include "bits/containers.hfa"
    97
    108#include "invoke.h"
     
    1210#include "time_t.hfa"
    1311#include "time.hfa"
    14 #include <sys/time.h>
    15 #include "alarm.hfa"
    1612
    17 ///////////////////////////////////////////////////////////////////
    18 //// is_blocking_lock
    19 ///////////////////////////////////////////////////////////////////
     13//-----------------------------------------------------------------------------
     14// is_blocking_lock
     15trait is_blocking_lock(dtype L | sized(L)) {
     16        // For synchronization locks to use when acquiring
     17        void on_notify( L &, struct $thread * );
    2018
    21 trait is_blocking_lock(dtype L | sized(L)) {
    22         void add_( L &, struct $thread * );             // For synchronization locks to use when acquiring
    23         void remove_( L & );    // For synchronization locks to use when releasing
    24         size_t get_recursion_count( L & ); // to get recursion count for cond lock to reset after waking
    25         void set_recursion_count( L &, size_t recursion ); // to set recursion count after getting signalled;
     19        // For synchronization locks to use when releasing
     20        void on_wait( L & );
     21
     22        // to get recursion count for cond lock to reset after waking
     23        size_t get_recursion_count( L & );
     24
     25        // to set recursion count after getting signalled;
     26        void set_recursion_count( L &, size_t recursion );
    2627};
    2728
    28 ///////////////////////////////////////////////////////////////////
    29 //// info_thread
    30 ///////////////////////////////////////////////////////////////////
     29//-----------------------------------------------------------------------------
     30// info_thread
     31// the info thread is a wrapper around a thread used
     32// to store extra data for use in the condition variable
     33forall(dtype L | is_blocking_lock(L)) {
     34        struct info_thread;
    3135
    32 forall(dtype L | is_blocking_lock(L)) {
    33         struct info_thread {
    34                 inline Seqable;
    35                 struct $thread * t;
    36                 uintptr_t info;
    37                 L * lock;
    38                 bool listed;                                    // true if info_thread is on queue, false otherwise;
    39         };
    40 
    41 
    42         void ?{}( info_thread(L) & this, $thread * t );
    43         void ?{}( info_thread(L) & this, $thread * t, uintptr_t info );
    44         void ^?{}( info_thread(L) & this );
     36        // for use by sequence
     37        info_thread(L) *& Back( info_thread(L) * this );
     38        info_thread(L) *& Next( info_thread(L) * this );
    4539}
    4640
    47 ///////////////////////////////////////////////////////////////////
    48 //// Blocking Locks
    49 ///////////////////////////////////////////////////////////////////
    50 
    51 // struct lock_thread {
    52 //      struct $thread * t;
    53 //      lock_thread * next;
    54 // };
    55 
    56 // void ?{}( lock_thread & this, struct $thread * thd );
    57 // void ^?{}( lock_thread & this );
    58 
    59 // lock_thread *& get_next( lock_thread & );
    60 
     41//-----------------------------------------------------------------------------
     42// Blocking Locks
    6143struct blocking_lock {
    6244        // Spin lock used for mutual exclusion
     
    6446
    6547        // List of blocked threads
    66         __queue_t( $thread ) blocked_threads;
     48        Sequence( $thread ) blocked_threads;
    6749
    6850        // Count of current blocked threads
     
    9476};
    9577
    96 void ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner );
     78void  ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner );
    9779void ^?{}( blocking_lock & this );
    9880
    99 void ?{}( single_acquisition_lock & this );
     81void  ?{}( single_acquisition_lock & this );
    10082void ^?{}( single_acquisition_lock & this );
    10183
    102 void ?{}( owner_lock & this );
     84void  ?{}( owner_lock & this );
    10385void ^?{}( owner_lock & this );
    10486
    105 void ?{}( multiple_acquisition_lock & this );
     87void  ?{}( multiple_acquisition_lock & this );
    10688void ^?{}( multiple_acquisition_lock & this );
    10789
     
    10991bool try_lock( blocking_lock & this );
    11092void unlock( blocking_lock & this );
    111 void add_( blocking_lock & this, struct $thread * t );
    112 void remove_( blocking_lock & this );
     93void on_notify( blocking_lock & this, struct $thread * t );
     94void on_wait( blocking_lock & this );
    11395size_t wait_count( blocking_lock & this );
    11496void set_recursion_count( blocking_lock & this, size_t recursion );
     
    11799void lock( single_acquisition_lock & this );
    118100void unlock( single_acquisition_lock & this );
    119 void add_( single_acquisition_lock & this, struct $thread * t );
    120 void remove_( single_acquisition_lock & this );
     101void on_notify( single_acquisition_lock & this, struct $thread * t );
     102void on_wait( single_acquisition_lock & this );
    121103void set_recursion_count( single_acquisition_lock & this, size_t recursion );
    122104size_t get_recursion_count( single_acquisition_lock & this );
     
    124106void lock( owner_lock & this );
    125107void unlock( owner_lock & this );
    126 void add_( owner_lock & this, struct $thread * t );
    127 void remove_( owner_lock & this );
     108void on_notify( owner_lock & this, struct $thread * t );
     109void on_wait( owner_lock & this );
    128110void set_recursion_count( owner_lock & this, size_t recursion );
    129111size_t get_recursion_count( owner_lock & this );
     
    131113void lock( multiple_acquisition_lock & this );
    132114void unlock( multiple_acquisition_lock & this );
    133 void add_( multiple_acquisition_lock & this, struct $thread * t );
    134 void remove_( multiple_acquisition_lock & this );
     115void on_notify( multiple_acquisition_lock & this, struct $thread * t );
     116void on_wait( multiple_acquisition_lock & this );
    135117void set_recursion_count( multiple_acquisition_lock & this, size_t recursion );
    136118size_t get_recursion_count( multiple_acquisition_lock & this );
    137119
    138 ///////////////////////////////////////////////////////////////////
    139 //// Synchronization Locks
    140 ///////////////////////////////////////////////////////////////////
     120//-----------------------------------------------------------------------------
     121// Synchronization Locks
    141122forall(dtype L | is_blocking_lock(L)) {
    142123        struct condition_variable {
    143124                // Spin lock used for mutual exclusion
    144125                __spinlock_t lock;
    145 
    146                 info_thread(L) * last_thread;
    147126
    148127                // List of blocked threads
     
    153132        };
    154133
    155         void ?{}( condition_variable(L) & this );
     134        void  ?{}( condition_variable(L) & this );
    156135        void ^?{}( condition_variable(L) & this );
    157 
    158         struct alarm_node_wrap {
    159                 alarm_node_t alarm_node;
    160 
    161                 condition_variable(L) * cond;
    162 
    163                 info_thread(L) * i;
    164         };
    165 
    166         void ?{}( alarm_node_wrap(L) & this, Time alarm, Duration period, Alarm_Callback callback );
    167         void ^?{}( alarm_node_wrap(L) & this );
    168 
    169         void alarm_node_callback( alarm_node_wrap(L) & this );
    170 
    171         void alarm_node_wrap_cast( alarm_node_t & a );
    172136
    173137        bool notify_one( condition_variable(L) & this );
     
    176140        uintptr_t front( condition_variable(L) & this );
    177141
    178         bool empty( condition_variable(L) & this );
    179         int counter( condition_variable(L) & this );
     142        bool empty  ( condition_variable(L) & this );
     143        int  counter( condition_variable(L) & this );
    180144
    181         // TODO: look into changing timout routines to return bool showing if signalled or woken by kernel
    182145        void wait( condition_variable(L) & this );
    183146        void wait( condition_variable(L) & this, uintptr_t info );
    184         void wait( condition_variable(L) & this, Duration duration );
    185         void wait( condition_variable(L) & this, uintptr_t info, Duration duration );
    186         void wait( condition_variable(L) & this, Time time );
    187         void wait( condition_variable(L) & this, uintptr_t info, Time time );
     147        bool wait( condition_variable(L) & this, Duration duration );
     148        bool wait( condition_variable(L) & this, uintptr_t info, Duration duration );
     149        bool wait( condition_variable(L) & this, Time time );
     150        bool wait( condition_variable(L) & this, uintptr_t info, Time time );
    188151
    189152        void wait( condition_variable(L) & this, L & l );
    190153        void wait( condition_variable(L) & this, L & l, uintptr_t info );
    191         void wait( condition_variable(L) & this, L & l, Duration duration );
    192         void wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration );
    193         void wait( condition_variable(L) & this, L & l, Time time );
    194         void wait( condition_variable(L) & this, L & l, uintptr_t info, Time time );
     154        bool wait( condition_variable(L) & this, L & l, Duration duration );
     155        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration );
     156        bool wait( condition_variable(L) & this, L & l, Time time );
     157        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Time time );
    195158}
  • libcfa/src/concurrency/monitor.hfa

    r42f6e07 r2b4daf2  
    132132
    133133              void wait        ( condition & this, uintptr_t user_info = 0 );
     134static inline bool is_empty    ( condition & this ) { return this.blocked.head == 1p; }
    134135              bool signal      ( condition & this );
    135136              bool signal_block( condition & this );
    136 static inline bool is_empty    ( condition & this ) { return this.blocked.head == 1p; }
     137static inline bool signal_all  ( condition & this ) { bool ret = false; while(!is_empty(this)) { ret = signal(this) || ret; } return ret; }
    137138         uintptr_t front       ( condition & this );
    138139
  • libcfa/src/concurrency/thread.cfa

    r42f6e07 r2b4daf2  
    4343                canary = 0x0D15EA5E0D15EA5Ep;
    4444        #endif
     45
     46        seqable.next = 0p;
     47        seqable.back = 0p;
    4548
    4649        node.next = 0p;
     
    130133
    131134        this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
    132         verify( this_thrd->context.SP );
     135        /* paranoid */ verify( this_thrd->context.SP );
    133136
    134137        __schedule_thread( this_thrd );
  • libcfa/src/heap.cfa

    r42f6e07 r2b4daf2  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Dec 15 21:37:54 2020
    13 // Update Count     : 1013
     12// Last Modified On : Wed Dec 16 12:28:25 2020
     13// Update Count     : 1023
    1414//
    1515
     
    438438        header = headerAddr( addr );
    439439
    440   if ( unlikely( heapEnd < addr ) ) {                                   // mmapped ?
     440  if ( unlikely( addr < heapBegin || heapEnd < addr ) ) { // mmapped ?
    441441                fakeHeader( header, alignment );
    442442                size = header->kind.real.blockSize & -3;                // mmap size
     
    445445
    446446        #ifdef __CFA_DEBUG__
    447         checkHeader( addr < heapBegin, name, addr );            // bad low address ?
     447        checkHeader( header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
    448448        #endif // __CFA_DEBUG__
    449449
     
    484484#endif // __CFA_DEBUG__
    485485
     486
    486487#define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes."
    487488
    488 #include <unistd.h>
    489489static inline void * extend( size_t size ) with( heapManager ) {
    490490        lock( extlock __cfaabi_dbg_ctx2 );
     
    511511                #ifdef __CFA_DEBUG__
    512512                // Set new memory to garbage so subsequent uninitialized usages might fail.
    513                 memset( (char *)heapEnd + heapRemaining, '\hde', increase );
     513                memset( (char *)heapEnd + heapRemaining, '\xde', increase );
    514514                //Memset( (char *)heapEnd + heapRemaining, increase );
    515515                #endif // __CFA_DEBUG__
     
    586586                #ifdef __CFA_DEBUG__
    587587                // Set new memory to garbage so subsequent uninitialized usages might fail.
    588                 memset( block, '\hde', tsize );
     588                memset( block, '\xde', tsize );
    589589                //Memset( block, tsize );
    590590                #endif // __CFA_DEBUG__
     
    634634                #ifdef __CFA_DEBUG__
    635635                // Set free memory to garbage so subsequent usages might fail.
    636                 memset( ((HeapManager.Storage *)header)->data, '\hde', freeElem->blockSize - sizeof( HeapManager.Storage ) );
     636                memset( ((HeapManager.Storage *)header)->data, '\xde', freeElem->blockSize - sizeof( HeapManager.Storage ) );
    637637                //Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) );
    638638                #endif // __CFA_DEBUG__
     
    10291029        } // cmemalign
    10301030
     1031
    10311032        // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple
    10321033    // of alignment. This requirement is universally ignored.
     
    10451046                return 0;
    10461047        } // posix_memalign
     1048
    10471049
    10481050        // Allocates size bytes and returns a pointer to the allocated memory. The memory address shall be a multiple of the
  • libcfa/src/memory.cfa

    r42f6e07 r2b4daf2  
    6666forall(dtype T | sized(T), ttype Args | { void ?{}(T&, Args); })
    6767void ?{}(counter_ptr(T) & this, Args args) {
    68         this.data = new(args);
     68        this.data = (counter_data(T)*)new(args);
    6969}
    7070
     
    126126forall(dtype T | sized(T), ttype Args | { void ?{}(T &, Args); })
    127127void ?{}(unique_ptr(T) & this, Args args) {
    128         this.data = new(args);
     128        this.data = (T *)new(args);
    129129}
    130130
  • libcfa/src/parseargs.cfa

    r42f6e07 r2b4daf2  
    105105                                        if(opt == options[i].short_name) {
    106106                                                const char * arg = optarg ? optarg : "";
     107                                                if( arg[0] == '=' ) { arg++; }
    107108                                                bool success = options[i].parse( arg, options[i].variable );
    108109                                                if(success) continue NEXT_ARG;
     
    185186}
    186187
     188bool parse_truefalse(const char * arg, bool & value) {
     189        if(strcmp(arg, "true") == 0) {
     190                value = true;
     191                return true;
     192        }
     193
     194        if(strcmp(arg, "false") == 0) {
     195                value = false;
     196                return true;
     197        }
     198
     199        return false;
     200}
     201
    187202bool parse_settrue (const char *, bool & value ) {
    188203        value = true;
  • libcfa/src/parseargs.hfa

    r42f6e07 r2b4daf2  
    3737void print_args_usage(int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn));
    3838
    39 bool parse_yesno   (const char *, bool & );
    40 bool parse_settrue (const char *, bool & );
    41 bool parse_setfalse(const char *, bool & );
     39bool parse_yesno    (const char *, bool & );
     40bool parse_truefalse(const char *, bool & );
     41bool parse_settrue  (const char *, bool & );
     42bool parse_setfalse (const char *, bool & );
    4243
    4344bool parse(const char *, const char * & );
  • libcfa/src/stdlib.hfa

    r42f6e07 r2b4daf2  
    267267static inline forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } )
    268268T * new( TT p ) {
    269         return &(*malloc()){ p };                                                       // run constructor
     269        return &(*(T *)malloc()){ p };                                                  // run constructor
    270270} // new
    271271
Note: See TracChangeset for help on using the changeset viewer.