- Timestamp:
- Jan 7, 2021, 5:06:22 PM (5 years ago)
- 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. - Location:
- libcfa/src
- Files:
-
- 5 added
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/Makefile.am
r42f6e07 r2b4daf2 58 58 concurrency/iofwd.hfa \ 59 59 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 61 65 62 66 inst_headers_src = \ … … 94 98 concurrency/clib/cfathread.h \ 95 99 concurrency/invoke.h \ 100 concurrency/future.hfa \ 96 101 concurrency/kernel/fwd.hfa 97 102 -
libcfa/src/bits/collection.hfa
r42f6e07 r2b4daf2 1 1 #pragma once 2 #include <stdio.h> // REMOVE THIS AFTER DEBUGGING 3 2 4 3 5 struct Colable { 4 Colable * next; // next node in the list6 struct Colable * next; // next node in the list 5 7 // invariant: (next != 0) <=> listed() 6 8 }; 7 8 inline {9 #ifdef __cforall 10 static inline { 9 11 // PUBLIC 10 12 … … 28 30 } 29 31 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 40 38 } // distribution 41 39 40 forall( dtype T | { T *& Next ( T * ); } ) { 41 bool listed( T * n ) { 42 return Next( n ) != 0p; 43 } 44 } 42 45 43 46 struct Collection { … … 45 48 }; 46 49 47 inline {50 static inline { 48 51 // class invariant: root == 0 & empty() | *root in *this 49 52 void ?{}( Collection &, const Collection & ) = void; // no copy … … 65 68 66 69 struct ColIter { 67 void * curr; // element to be returned by >>70 void * curr; // element returned by | 68 71 }; 69 72 70 inline {73 static inline { 71 74 void ?{}( ColIter & colIter ) with( colIter ) { 72 75 curr = 0p; … … 79 82 } // distribution 80 83 } // distribution 84 #endif -
libcfa/src/bits/containers.hfa
r42f6e07 r2b4daf2 36 36 #define __small_array_t(T) __small_array(T) 37 37 #else 38 #define __small_array_t(T) struct__small_array38 #define __small_array_t(T) __small_array 39 39 #endif 40 40 -
libcfa/src/bits/defs.hfa
r42f6e07 r2b4daf2 29 29 #define __cfa_anonymous_object(x) inline struct x 30 30 #else 31 #define __cfa_anonymous_object(x) x __cfa_anonymous_object31 #define __cfa_anonymous_object(x) struct x __cfa_anonymous_object 32 32 #endif 33 33 -
libcfa/src/bits/locks.hfa
r42f6e07 r2b4daf2 283 283 void ^?{}(future_t &) {} 284 284 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 285 290 // check if the future is available 286 291 bool available( future_t & this ) { … … 340 345 341 346 // 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 343 351 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; 344 355 345 356 // got == 2p: the future is ready but the context hasn't fully been consumed … … 347 358 if( got == 2p ) { 348 359 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; 351 367 } 352 368 -
libcfa/src/bits/queue.hfa
r42f6e07 r2b4daf2 3 3 #include "bits/collection.hfa" 4 4 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 11 forall( dtype T | { T *& Next ( T * ); } ) { 6 12 struct Queue { 7 13 inline Collection; // Plan 9 inheritance … … 34 40 } // post: n == tail() & succ(n) == 0 | n != tail() & *succ(n) in *q 35 41 36 voidaddHead( Queue(T) & q, T & n ) with( q ) {42 T & addHead( Queue(T) & q, T & n ) with( q ) { 37 43 #ifdef __CFA_DEBUG__ 38 44 if ( listed( &n ) ) abort( "(Queue &)%p.addHead( %p ) : Node is already on another list.", &q, &n ); … … 45 51 Next( &n ) = &n; // last node points to itself 46 52 } 53 return n; 47 54 } 48 55 49 voidaddTail( Queue(T) & q, T & n ) with( q ) {56 T & addTail( Queue(T) & q, T & n ) with( q ) { 50 57 #ifdef __CFA_DEBUG__ 51 58 if ( listed( &n ) ) abort( "(Queue &)%p.addTail( %p ) : Node is already on another list.", &q, &n ); … … 55 62 last = &n; 56 63 Next( &n ) = &n; // last node points to itself 64 return n; 57 65 } 58 66 59 voidadd( 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 ); 61 69 } 62 70 … … 64 72 T & t = head( q ); 65 73 if ( root ) { 66 root = Next( root );74 root = Next( (T *)root ); 67 75 if ( &head( q ) == &t ) { 68 76 root = last = 0p; // only one element … … 77 85 } 78 86 79 voidremove( Queue(T) & q, T & n ) with( q ) { // O(n)87 T & remove( Queue(T) & q, T & n ) with( q ) { // O(n) 80 88 #ifdef __CFA_DEBUG__ 81 89 if ( ! listed( (Colable &)n ) ) abort( "(Queue &)%p.remove( %p ) : Node is not on a list.", &q, &n ); … … 103 111 curr = Next( curr ); 104 112 } 113 return n; 105 114 } // post: ! listed( n ) 106 115 107 T & dropTail( Queue(T) & q ) with( q ) { 116 T & dropTail( Queue(T) & q ) with( q ) { // O(n) 108 117 T & n = tail( q ); 109 118 return &n ? remove( q, n ), n : *0p; … … 142 151 } // distribution 143 152 144 forall( dtype T ) {153 forall( dtype T | { T *& Next ( T * ); } ) { 145 154 struct QueueIter { 146 155 inline ColIter; // Plan 9 inheritance … … 152 161 } // post: curr == 0p 153 162 154 // create an iterator active in Queue q163 // create an iterator active in queue q 155 164 void ?{}( QueueIter(T) & qi, Queue(T) & q ) with( qi ) { 156 165 curr = &head( q ); … … 161 170 } // post: curr = {e in q} 162 171 163 // make existing iterator active in Queue q172 // make existing iterator active in queue q 164 173 void over( QueueIter(T) & qi, Queue(T) & q ) with( qi ) { 165 174 curr = &head( q ); 166 175 } // post: curr = {e in q} 167 176 168 bool ? >>?( QueueIter(T) & qi, T && tp ) with( qi ) {177 bool ?|?( QueueIter(T) & qi, T && tp ) with( qi ) { 169 178 if ( curr ) { 170 179 &tp = Curr( qi ); … … 174 183 return &tp != 0p; 175 184 } 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) 177 186 } // distribution 178 187 } // distribution -
libcfa/src/bits/sequence.hfa
r42f6e07 r2b4daf2 2 2 3 3 #include "bits/collection.hfa" 4 #include "bits/defs.hfa" 4 5 5 6 struct Seqable { 6 inline Colable;7 Seqable * back; // pointer to previous node in the list7 __cfa_anonymous_object(Colable); 8 struct Seqable * back; // pointer to previous node in the list 8 9 }; 9 10 10 inline { 11 #ifdef __cforall 12 static inline { 11 13 // PUBLIC 12 14 … … 26 28 } 27 29 28 // wrappers to make Collection have T29 forall( dtype T ) {30 T *& Back( T * n ) {31 return (T *)Back( (Seqable *)n );32 }33 } // distribution30 // // wrappers to make Collection have T 31 // forall( dtype T ) { 32 // T *& Back( T * n ) { 33 // return (T *)Back( (Seqable *)n ); 34 // } 35 // } // distribution 34 36 } // distribution 35 37 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 45 forall( dtype T | { T *& Back ( T * ); T *& Next ( T * ); } ) { 37 46 struct Sequence { 38 47 inline Collection; // Plan 9 inheritance 39 48 }; 40 49 41 inline {50 static inline { 42 51 // wrappers to make Collection have T 43 52 T & head( Sequence(T) & s ) with( s ) { … … 50 59 void ?{}( Sequence(T) & s ) with( s ) { 51 60 ((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. 55 64 T & tail( Sequence(T) & s ) with( s ) { 56 65 return root ? (T &)*Back( &head( s ) ) : *0p; … … 65 74 } // post: n == tail() & succ(n) == 0 | n != tail() & *succ(n) in *s 66 75 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. 68 77 T * pred( Sequence(T) & s, T * n ) with( s ) { // pre: *n in *s 69 78 #ifdef __CFA_DEBUG__ … … 71 80 #endif // __CFA_DEBUG__ 72 81 return n == &head( s ) ? 0p : Back( n ); 73 } 74 75 76 // Insert *n into the sequence before *bef, or at the end if bef == 0 .77 voidinsertBef( Sequence(T) & s, T & n, T & bef ) with( s ) { // pre: !n->listed() & *bef in *s82 } // 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 78 87 #ifdef __CFA_DEBUG__ 79 88 if ( listed( &n ) ) abort( "(Sequence &)%p.insertBef( %p, %p ) : Node is already on another list.", &s, n, &bef ); … … 103 112 Next( Back( &n ) ) = &n; 104 113 } // if 114 return n; 105 115 } // post: n->listed() & *n in *s & succ(n) == bef 106 116 107 117 108 118 // Insert *n into the sequence after *aft, or at the beginning if aft == 0. 109 voidinsertAft( Sequence(T) & s, T & aft, T & n ) with( s ) { // pre: !n->listed() & *aft in *s119 T & insertAft( Sequence(T) & s, T & aft, T & n ) with( s ) { // pre: !n->listed() & *aft in *s 110 120 #ifdef __CFA_DEBUG__ 111 121 if ( listed( &n ) ) abort( "(Sequence &)%p.insertAft( %p, %p ) : Node is already on another list.", &s, &aft, &n ); … … 133 143 Next( &aft ) = &n; 134 144 } // if 135 } // post: n->listed() & *n in *s & succ(n) == bef 145 return n; 146 } // post: n->listed() & *n in *s & succ(n) == bef 136 147 137 148 // pre: n->listed() & *n in *s 138 voidremove( Sequence(T) & s, T & n ) with( s ) { // O(1)149 T & remove( Sequence(T) & s, T & n ) with( s ) { // O(1) 139 150 #ifdef __CFA_DEBUG__ 140 151 if ( ! listed( &n ) ) abort( "(Sequence &)%p.remove( %p ) : Node is not on a list.", &s, &n ); … … 147 158 Next( Back( &n ) ) = Next( &n ); 148 159 Next( &n ) = Back( &n ) = 0p; 149 } // post: !n->listed(). 160 return n; 161 } // post: !n->listed() 150 162 151 163 // 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 155 168 // 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 159 173 // 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 163 178 // Remove and return the head element in the sequence. 164 179 T & dropHead( Sequence(T) & s ) { … … 166 181 return &n ? remove( s, n ), n : *0p; 167 182 } 183 168 184 // Remove and return the head element in the sequence. 169 185 T & drop( Sequence(T) & s ) { 170 186 return dropHead( s ); 171 187 } 188 172 189 // Remove and return the tail element in the sequence. 173 190 T & dropTail( Sequence(T) & s ) { … … 184 201 T * toEnd = Back( &head( s ) ); 185 202 T * fromEnd = Back( &head( from ) ); 186 Back( root ) = fromEnd;203 Back( (T *)root ) = fromEnd; 187 204 Next( fromEnd ) = &head( s ); 188 Back( from.root ) = toEnd;205 Back( (T *)from.root ) = toEnd; 189 206 Next( toEnd ) = &head( from ); 190 207 } // if … … 214 231 } // distribution 215 232 216 forall( dtype T ) {233 forall( dtype T | { T *& Back ( T * ); T *& Next ( T * ); } ) { 217 234 // SeqIter(T) is used to iterate over a Sequence(T) in head-to-tail order. 218 235 struct SeqIter { … … 224 241 }; 225 242 226 inline {243 static inline { 227 244 void ?{}( SeqIter(T) & si ) with( si ) { 228 245 ((ColIter &)si){}; 229 246 seq = 0p; 230 } // post: elts = null. 231 247 } // post: elts = null 248 249 // Create a iterator active in sequence s. 232 250 void ?{}( SeqIter(T) & si, Sequence(T) & s ) with( si ) { 233 251 ((ColIter &)si){}; 234 252 seq = &s; 235 253 curr = &head( s ); 236 } // post: elts = null .254 } // post: elts = null 237 255 238 256 void ?{}( SeqIter(T) & si, Sequence(T) & s, T & start ) with( si ) { … … 240 258 seq = &s; 241 259 curr = &start; 242 } // post: elts = null. 243 260 } // post: elts = null 261 262 // Make the iterator active in sequence s. 244 263 void over( SeqIter(T) & si, Sequence(T) & s ) with( si ) { 245 264 seq = &s; 246 265 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 ) { 250 269 if ( curr ) { 251 270 &tp = Curr( si ); … … 265 284 }; 266 285 267 inline {286 static inline { 268 287 void ?{}( SeqIterRev(T) & si ) with( si ) { 269 288 ((ColIter &)si){}; 270 289 seq = 0p; 271 } // post: elts = null. 272 290 } // post: elts = null 291 292 // Create a iterator active in sequence s. 273 293 void ?{}( SeqIterRev(T) & si, Sequence(T) & s ) with( si ) { 274 294 ((ColIter &)si){}; 275 295 seq = &s; 276 296 curr = &tail( s ); 277 } // post: elts = null .297 } // post: elts = null 278 298 279 299 void ?{}( SeqIterRev(T) & si, Sequence(T) & s, T & start ) with( si ) { … … 281 301 seq = &s; 282 302 curr = &start; 283 } // post: elts = null. 284 303 } // post: elts = null 304 305 // Make the iterator active in sequence s. 285 306 void over( SeqIterRev(T) & si, Sequence(T) & s ) with( si ) { 286 307 seq = &s; 287 308 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 ) { 291 312 if ( curr ) { 292 313 &tp = Curr( si ); … … 298 319 } // distribution 299 320 } // distribution 321 322 #endif -
libcfa/src/bits/stack.hfa
r42f6e07 r2b4daf2 3 3 #include "bits/collection.hfa" 4 4 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 11 forall( dtype T | { T *& Next ( T * ); } ) { 6 12 struct Stack { 7 13 inline Collection; // Plan 9 inheritance … … 25 31 } 26 32 27 voidaddHead( Stack(T) & s, T & n ) with( s ) {33 T & addHead( Stack(T) & s, T & n ) with( s ) { 28 34 #ifdef __CFA_DEBUG__ 29 35 if ( listed( (Colable &)(n) ) ) abort( "(Stack &)%p.addHead( %p ) : Node is already on another list.", &s, n ); … … 31 37 Next( &n ) = &head( s ) ? &head( s ) : &n; 32 38 root = &n; 39 return n; 33 40 } 34 41 35 voidadd( 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 ); 37 44 } 38 45 39 voidpush( 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 ); 41 48 } 42 49 … … 44 51 T & t = head( s ); 45 52 if ( root ) { 46 root = ( T *)Next( root );53 root = ( T *)Next( (T *)root ); 47 54 if ( &head( s ) == &t ) root = 0p; // only one element ? 48 55 Next( &t ) = 0p; … … 57 64 } // distribution 58 65 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(). 59 68 60 forall( dtype T ) {69 forall( dtype T | { T *& Next ( T * ); } ) { 61 70 struct StackIter { 62 71 inline ColIter; // Plan 9 inheritance … … 68 77 } // post: curr == 0p 69 78 70 // create an iterator active in Stack s79 // create an iterator active in stack s 71 80 void ?{}( StackIter(T) & si, Stack(T) & s ) with( si ) { 72 81 curr = &head( s ); … … 77 86 } // post: curr = {e in s} 78 87 79 // make existing iterator active in Stack q88 // make existing iterator active in stack s 80 89 void over( StackIter(T) & si, Stack(T) & s ) with( si ) { 81 90 curr = &head( s ); 82 91 } // post: curr = {e in s} 83 92 84 bool ? >>?( StackIter(T) & si, T && tp ) with( si ) {93 bool ?|?( StackIter(T) & si, T && tp ) with( si ) { 85 94 if ( curr ) { 86 95 &tp = Curr( si ); -
libcfa/src/concurrency/invoke.h
r42f6e07 r2b4daf2 189 189 struct __monitor_group_t monitors; 190 190 191 // used to put threads on user data structures 192 struct { 193 struct $thread * next; 194 struct $thread * back; 195 } seqable; 196 191 197 struct { 192 198 struct $thread * next; … … 218 224 } 219 225 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 220 238 static inline void ?{}(__monitor_group_t & this) { 221 239 (this.data){0p}; -
libcfa/src/concurrency/kernel/startup.cfa
r42f6e07 r2b4daf2 118 118 119 119 extern size_t __page_size; 120 extern int __map_prot; 120 121 121 122 //----------------------------------------------------------------------------- … … 725 726 } 726 727 #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 ); 727 734 free( stack ); 728 735 #endif -
libcfa/src/concurrency/locks.cfa
r42f6e07 r2b4daf2 1 1 #include "locks.hfa" 2 2 #include "kernel_private.hfa" 3 #include <stdlib.h>4 #include <stdio.h>5 3 6 4 #include <kernel.hfa> 7 5 #include <stdlib.hfa> 8 #include <thread.hfa> 9 10 /////////////////////////////////////////////////////////////////// 11 //// info_thread 12 /////////////////////////////////////////////////////////////////// 13 6 7 //----------------------------------------------------------------------------- 8 // info_thread 14 9 forall(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 ) { 23 28 ((Seqable &) this){}; 24 29 this.t = t; 25 30 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 37 47 void ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner ) { 38 48 this.lock{}; … … 46 56 47 57 void ^?{}( blocking_lock & this ) {} 48 void ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };}58 void ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };} 49 59 void ^?{}( single_acquisition_lock & this ) {} 50 void ?{}( owner_lock & this ) {((blocking_lock &)this){ true, true };}60 void ?{}( owner_lock & this ) {((blocking_lock &)this){ true, true };} 51 61 void ^?{}( owner_lock & this ) {} 52 void ?{}( multiple_acquisition_lock & this ) {((blocking_lock &)this){ true, false };}62 void ?{}( multiple_acquisition_lock & this ) {((blocking_lock &)this){ true, false };} 53 63 void ^?{}( multiple_acquisition_lock & this ) {} 54 64 55 65 void lock( blocking_lock & this ) with( this ) { 56 66 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 ); 61 75 wait_count++; 62 76 unlock( lock ); 63 77 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 ) { 65 81 recursion_count++; 66 82 unlock( lock ); 67 } else { 68 owner = active_thread(); 83 } 84 // lock isn't held 85 else { 86 owner = thrd; 69 87 recursion_count = 1; 70 88 unlock( lock ); … … 75 93 bool ret = false; 76 94 lock( lock __cfaabi_dbg_ctx2 ); 95 96 // lock isn't held 77 97 if ( owner == 0p ) { 78 98 owner = active_thread(); 79 99 recursion_count = 1; 80 100 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 ) { 82 104 recursion_count++; 83 105 ret = true; 84 106 } 107 85 108 unlock( lock ); 86 109 return ret; 87 110 } 88 111 89 void unlock_error_check( blocking_lock & this ) with( this ) {90 if ( owner == 0p ){ // no owner implies lock isn't held91 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 97 112 void pop_and_set_new_owner( blocking_lock & this ) with( this ) { 98 $thread * t = pop_head( blocked_threads );113 $thread * t = &dropHead( blocked_threads ); 99 114 owner = t; 100 115 recursion_count = ( t ? 1 : 0 ); … … 105 120 void unlock( blocking_lock & this ) with( this ) { 106 121 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 108 126 recursion_count--; 109 127 if ( recursion_count == 0 ) { … … 125 143 } 126 144 127 void add_( blocking_lock & this, $thread * t ) with( this ) { 128 lock( lock __cfaabi_dbg_ctx2 ); 145 void on_notify( blocking_lock & this, $thread * t ) with( this ) { 146 lock( lock __cfaabi_dbg_ctx2 ); 147 // lock held 129 148 if ( owner != 0p ) { 130 a ppend( blocked_threads,t );149 addTail( blocked_threads, *t ); 131 150 wait_count++; 132 151 unlock( lock ); 133 } else { 152 } 153 // lock not held 154 else { 134 155 owner = t; 135 156 recursion_count = 1; … … 139 160 } 140 161 141 void remove_( blocking_lock & this ) with( this ) { 142 lock( lock __cfaabi_dbg_ctx2 ); 143 unlock_error_check( this ); 162 void 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 144 167 pop_and_set_new_owner( this ); 145 168 unlock( lock ); 146 169 } 147 170 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 174 void lock ( single_acquisition_lock & this ) { lock ( (blocking_lock &)this ); } 175 void unlock ( single_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); } 176 void on_wait ( single_acquisition_lock & this ) { on_wait( (blocking_lock &)this ); } 177 void on_notify ( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); } 178 void set_recursion_count( single_acquisition_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); } 179 size_t get_recursion_count( single_acquisition_lock & this ) { return get_recursion_count( (blocking_lock &)this ); } 180 181 void lock ( owner_lock & this ) { lock ( (blocking_lock &)this ); } 182 void unlock ( owner_lock & this ) { unlock ( (blocking_lock &)this ); } 183 void on_wait ( owner_lock & this ) { on_wait( (blocking_lock &)this ); } 184 void on_notify( owner_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); } 185 void set_recursion_count( owner_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); } 186 size_t get_recursion_count( owner_lock & this ) { return get_recursion_count( (blocking_lock &)this ); } 187 188 void lock ( multiple_acquisition_lock & this ) { lock ( (blocking_lock &)this ); } 189 void unlock ( multiple_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); } 190 void on_wait ( multiple_acquisition_lock & this ) { on_wait( (blocking_lock &)this ); } 191 void on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); } 192 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); } 173 193 size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } 174 194 175 /////////////////////////////////////////////////////////////////// 176 //// condition variable 177 /////////////////////////////////////////////////////////////////// 178 195 //----------------------------------------------------------------------------- 196 // alarm node wrapper 179 197 forall(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 ) { } 180 211 181 212 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 ); 188 223 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 190 229 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 198 236 void alarm_node_wrap_cast( alarm_node_t & a ) { timeout_handler( (alarm_node_wrap(L) &)a ); } 237 } 238 239 //----------------------------------------------------------------------------- 240 // condition variable 241 forall(dtype L | is_blocking_lock(L)) { 199 242 200 243 void ?{}( condition_variable(L) & this ){ … … 202 245 this.blocked_threads{}; 203 246 this.count = 0; 204 this.last_thread = 0p; // REMOVE AFTER DEBUG205 247 } 206 248 207 249 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 ) { }214 250 215 251 void process_popped( condition_variable(L) & this, info_thread(L) & popped ) with( this ) { 216 252 if(&popped != 0p) { 217 popped. listed = false;253 popped.signalled = true; 218 254 count--; 219 255 if (popped.lock) { 220 add_(*popped.lock, popped.t); 256 // if lock passed call on_notify 257 on_notify(*popped.lock, popped.t); 221 258 } else { 259 // otherwise wake thread 222 260 unpark(popped.t); 223 261 } … … 252 290 253 291 size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) { 292 // add info_thread to waiting queue 254 293 addTail( blocked_threads, *i ); 255 294 count++; 256 i->listed = true;257 295 size_t recursion_count = 0; 258 296 if (i->lock) { 259 i->t->link.next = 1p;297 // if lock was passed get recursion count to reset to after waking thread 260 298 recursion_count = get_recursion_count(*i->lock); 261 remove_( *i->lock );299 on_wait( *i->lock ); 262 300 } 263 301 return recursion_count; … … 269 307 size_t recursion_count = queue_and_get_recursion(this, &i); 270 308 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 ); 274 320 275 321 // helper for wait()'s' with a timeout … … 277 323 lock( lock __cfaabi_dbg_ctx2 ); 278 324 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 }; 282 326 register_self( &node_wrap.alarm_node ); 283 327 unlock( lock ); 328 329 // blocks here 284 330 park(); 331 332 // unregisters alarm so it doesn't go off if this happens first 285 333 unregister_self( &node_wrap.alarm_node ); 334 335 // resets recursion count here after waking 286 336 if (info.lock) set_recursion_count(*info.lock, recursion_count); 287 337 } 288 338 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 3 3 #include <stdbool.h> 4 4 5 #include "bits/algorithm.hfa"6 5 #include "bits/locks.hfa" 7 6 #include "bits/sequence.hfa" 8 #include "bits/containers.hfa"9 7 10 8 #include "invoke.h" … … 12 10 #include "time_t.hfa" 13 11 #include "time.hfa" 14 #include <sys/time.h>15 #include "alarm.hfa"16 12 17 /////////////////////////////////////////////////////////////////// 18 //// is_blocking_lock 19 /////////////////////////////////////////////////////////////////// 13 //----------------------------------------------------------------------------- 14 // is_blocking_lock 15 trait is_blocking_lock(dtype L | sized(L)) { 16 // For synchronization locks to use when acquiring 17 void on_notify( L &, struct $thread * ); 20 18 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 ); 26 27 }; 27 28 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 33 forall(dtype L | is_blocking_lock(L)) { 34 struct info_thread; 31 35 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 ); 45 39 } 46 40 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 61 43 struct blocking_lock { 62 44 // Spin lock used for mutual exclusion … … 64 46 65 47 // List of blocked threads 66 __queue_t( $thread ) blocked_threads;48 Sequence( $thread ) blocked_threads; 67 49 68 50 // Count of current blocked threads … … 94 76 }; 95 77 96 void ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner );78 void ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner ); 97 79 void ^?{}( blocking_lock & this ); 98 80 99 void ?{}( single_acquisition_lock & this );81 void ?{}( single_acquisition_lock & this ); 100 82 void ^?{}( single_acquisition_lock & this ); 101 83 102 void ?{}( owner_lock & this );84 void ?{}( owner_lock & this ); 103 85 void ^?{}( owner_lock & this ); 104 86 105 void ?{}( multiple_acquisition_lock & this );87 void ?{}( multiple_acquisition_lock & this ); 106 88 void ^?{}( multiple_acquisition_lock & this ); 107 89 … … 109 91 bool try_lock( blocking_lock & this ); 110 92 void unlock( blocking_lock & this ); 111 void add_( blocking_lock & this, struct $thread * t );112 void remove_( blocking_lock & this );93 void on_notify( blocking_lock & this, struct $thread * t ); 94 void on_wait( blocking_lock & this ); 113 95 size_t wait_count( blocking_lock & this ); 114 96 void set_recursion_count( blocking_lock & this, size_t recursion ); … … 117 99 void lock( single_acquisition_lock & this ); 118 100 void unlock( single_acquisition_lock & this ); 119 void add_( single_acquisition_lock & this, struct $thread * t );120 void remove_( single_acquisition_lock & this );101 void on_notify( single_acquisition_lock & this, struct $thread * t ); 102 void on_wait( single_acquisition_lock & this ); 121 103 void set_recursion_count( single_acquisition_lock & this, size_t recursion ); 122 104 size_t get_recursion_count( single_acquisition_lock & this ); … … 124 106 void lock( owner_lock & this ); 125 107 void unlock( owner_lock & this ); 126 void add_( owner_lock & this, struct $thread * t );127 void remove_( owner_lock & this );108 void on_notify( owner_lock & this, struct $thread * t ); 109 void on_wait( owner_lock & this ); 128 110 void set_recursion_count( owner_lock & this, size_t recursion ); 129 111 size_t get_recursion_count( owner_lock & this ); … … 131 113 void lock( multiple_acquisition_lock & this ); 132 114 void unlock( multiple_acquisition_lock & this ); 133 void add_( multiple_acquisition_lock & this, struct $thread * t );134 void remove_( multiple_acquisition_lock & this );115 void on_notify( multiple_acquisition_lock & this, struct $thread * t ); 116 void on_wait( multiple_acquisition_lock & this ); 135 117 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ); 136 118 size_t get_recursion_count( multiple_acquisition_lock & this ); 137 119 138 /////////////////////////////////////////////////////////////////// 139 //// Synchronization Locks 140 /////////////////////////////////////////////////////////////////// 120 //----------------------------------------------------------------------------- 121 // Synchronization Locks 141 122 forall(dtype L | is_blocking_lock(L)) { 142 123 struct condition_variable { 143 124 // Spin lock used for mutual exclusion 144 125 __spinlock_t lock; 145 146 info_thread(L) * last_thread;147 126 148 127 // List of blocked threads … … 153 132 }; 154 133 155 void ?{}( condition_variable(L) & this );134 void ?{}( condition_variable(L) & this ); 156 135 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 );172 136 173 137 bool notify_one( condition_variable(L) & this ); … … 176 140 uintptr_t front( condition_variable(L) & this ); 177 141 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 ); 180 144 181 // TODO: look into changing timout routines to return bool showing if signalled or woken by kernel182 145 void wait( condition_variable(L) & this ); 183 146 void wait( condition_variable(L) & this, uintptr_t info ); 184 voidwait( condition_variable(L) & this, Duration duration );185 voidwait( condition_variable(L) & this, uintptr_t info, Duration duration );186 voidwait( condition_variable(L) & this, Time time );187 voidwait( 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 ); 188 151 189 152 void wait( condition_variable(L) & this, L & l ); 190 153 void wait( condition_variable(L) & this, L & l, uintptr_t info ); 191 voidwait( condition_variable(L) & this, L & l, Duration duration );192 voidwait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration );193 voidwait( condition_variable(L) & this, L & l, Time time );194 voidwait( 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 ); 195 158 } -
libcfa/src/concurrency/monitor.hfa
r42f6e07 r2b4daf2 132 132 133 133 void wait ( condition & this, uintptr_t user_info = 0 ); 134 static inline bool is_empty ( condition & this ) { return this.blocked.head == 1p; } 134 135 bool signal ( condition & this ); 135 136 bool signal_block( condition & this ); 136 static inline bool is_empty ( condition & this ) { return this.blocked.head == 1p; }137 static inline bool signal_all ( condition & this ) { bool ret = false; while(!is_empty(this)) { ret = signal(this) || ret; } return ret; } 137 138 uintptr_t front ( condition & this ); 138 139 -
libcfa/src/concurrency/thread.cfa
r42f6e07 r2b4daf2 43 43 canary = 0x0D15EA5E0D15EA5Ep; 44 44 #endif 45 46 seqable.next = 0p; 47 seqable.back = 0p; 45 48 46 49 node.next = 0p; … … 130 133 131 134 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 ); 133 136 134 137 __schedule_thread( this_thrd ); -
libcfa/src/heap.cfa
r42f6e07 r2b4daf2 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 15 21:37:54202013 // Update Count : 10 1312 // Last Modified On : Wed Dec 16 12:28:25 2020 13 // Update Count : 1023 14 14 // 15 15 … … 438 438 header = headerAddr( addr ); 439 439 440 if ( unlikely( heapEnd < addr ) ) {// mmapped ?440 if ( unlikely( addr < heapBegin || heapEnd < addr ) ) { // mmapped ? 441 441 fakeHeader( header, alignment ); 442 442 size = header->kind.real.blockSize & -3; // mmap size … … 445 445 446 446 #ifdef __CFA_DEBUG__ 447 checkHeader( addr < heapBegin, name, addr );// bad low address ?447 checkHeader( header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ? 448 448 #endif // __CFA_DEBUG__ 449 449 … … 484 484 #endif // __CFA_DEBUG__ 485 485 486 486 487 #define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes." 487 488 488 #include <unistd.h>489 489 static inline void * extend( size_t size ) with( heapManager ) { 490 490 lock( extlock __cfaabi_dbg_ctx2 ); … … 511 511 #ifdef __CFA_DEBUG__ 512 512 // 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 ); 514 514 //Memset( (char *)heapEnd + heapRemaining, increase ); 515 515 #endif // __CFA_DEBUG__ … … 586 586 #ifdef __CFA_DEBUG__ 587 587 // Set new memory to garbage so subsequent uninitialized usages might fail. 588 memset( block, '\ hde', tsize );588 memset( block, '\xde', tsize ); 589 589 //Memset( block, tsize ); 590 590 #endif // __CFA_DEBUG__ … … 634 634 #ifdef __CFA_DEBUG__ 635 635 // 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 ) ); 637 637 //Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) ); 638 638 #endif // __CFA_DEBUG__ … … 1029 1029 } // cmemalign 1030 1030 1031 1031 1032 // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple 1032 1033 // of alignment. This requirement is universally ignored. … … 1045 1046 return 0; 1046 1047 } // posix_memalign 1048 1047 1049 1048 1050 // 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 66 66 forall(dtype T | sized(T), ttype Args | { void ?{}(T&, Args); }) 67 67 void ?{}(counter_ptr(T) & this, Args args) { 68 this.data = new(args);68 this.data = (counter_data(T)*)new(args); 69 69 } 70 70 … … 126 126 forall(dtype T | sized(T), ttype Args | { void ?{}(T &, Args); }) 127 127 void ?{}(unique_ptr(T) & this, Args args) { 128 this.data = new(args);128 this.data = (T *)new(args); 129 129 } 130 130 -
libcfa/src/parseargs.cfa
r42f6e07 r2b4daf2 105 105 if(opt == options[i].short_name) { 106 106 const char * arg = optarg ? optarg : ""; 107 if( arg[0] == '=' ) { arg++; } 107 108 bool success = options[i].parse( arg, options[i].variable ); 108 109 if(success) continue NEXT_ARG; … … 185 186 } 186 187 188 bool 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 187 202 bool parse_settrue (const char *, bool & value ) { 188 203 value = true; -
libcfa/src/parseargs.hfa
r42f6e07 r2b4daf2 37 37 void print_args_usage(int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn)); 38 38 39 bool parse_yesno (const char *, bool & ); 40 bool parse_settrue (const char *, bool & ); 41 bool parse_setfalse(const char *, bool & ); 39 bool parse_yesno (const char *, bool & ); 40 bool parse_truefalse(const char *, bool & ); 41 bool parse_settrue (const char *, bool & ); 42 bool parse_setfalse (const char *, bool & ); 42 43 43 44 bool parse(const char *, const char * & ); -
libcfa/src/stdlib.hfa
r42f6e07 r2b4daf2 267 267 static inline forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } ) 268 268 T * new( TT p ) { 269 return &(* malloc()){ p }; // run constructor269 return &(*(T *)malloc()){ p }; // run constructor 270 270 } // new 271 271
Note:
See TracChangeset
for help on using the changeset viewer.