Changeset 8bd886e for libcfa/src
- Timestamp:
- Oct 20, 2022, 4:09:13 PM (2 years ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- a5e2682
- Parents:
- 1a45263
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/pthread.cfa
r1a45263 r8bd886e 33 33 enum { PTHREAD_KEYS_MAX = 1024 }; 34 34 35 struct Pthread_values{35 struct pthread_values{ 36 36 inline Seqable; 37 37 void* value; … … 39 39 }; 40 40 41 42 static Pthread_values *& Back( Pthread_values * n ) { 43 return (Pthread_values *)Back( (Seqable *)n ); 44 } 45 static Pthread_values *& Next( Pthread_values * n ) { 46 return (Pthread_values *)Next( (Colable *)n ); 47 } 48 49 struct Pthread_keys{ 41 static inline { 42 pthread_values *& Back( pthread_values * n ) { 43 return (pthread_values *)Back( (Seqable *)n ); 44 } 45 46 pthread_values *& Next( pthread_values * n ) { 47 return (pthread_values *)Next( (Colable *)n ); 48 } 49 } 50 51 struct pthread_keys { 50 52 bool in_use; 51 53 void (*destructor)( void * ); 52 Sequence( Pthread_values) threads;53 }; // Pthread keys54 55 static void ?{}( Pthread_keys& k){54 Sequence(pthread_values) threads; 55 }; 56 57 static void ?{}(pthread_keys& k){ 56 58 k.threads{}; 57 59 } 58 60 59 61 // Create storage separately to ensure no constructors are called. 60 static Pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));62 static pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16))); 61 63 62 64 static void init_pthread_storage(){ … … 66 68 } 67 69 68 #define cfa_pthread_keys (( Pthread_keys *)cfa_pthread_keys_storage)70 #define cfa_pthread_keys ((pthread_keys *)cfa_pthread_keys_storage) 69 71 70 72 /* Controlling the iterations of destructors for thread-specific data. */ … … 115 117 /* mutex helper routines */ 116 118 static void mutex_check(pthread_mutex_t* t){ 117 // Use double check to improve performance. Check is safe on x86; volatile prevents compiler reordering 119 // Use double check to improve performance. 120 // Check is safe on x86; volatile prevents compiler reordering 118 121 volatile pthread_mutex_t *const mutex_ = t; 122 119 123 // SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h 120 124 int _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock; 125 121 126 // if pthread_mutex_t is initialized by PTHREAD_MUTEX_INITIALIZER, _lock_val should be 0 122 if ( _lock_val == 0 ) { // static initialized ?123 lock(magic_mutex_check); // race127 if ( _lock_val == 0 ) { 128 lock(magic_mutex_check); 124 129 _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock; 125 if ( _lock_val == 0 ) { // static initialized ?126 pthread_mutex_init( t, NULL );127 } // if128 unlock(magic_mutex_check); // race129 } // if130 if ( _lock_val == 0 ) { 131 pthread_mutex_init( t, NULL ); 132 } 133 unlock(magic_mutex_check); 134 } 130 135 } // mutex_check 131 136 … … 168 173 }; 169 174 170 171 /*172 static const cfaPthread_attr_t default_attrs = {173 PTHREAD_SCOPE_SYSTEM,174 PTHREAD_CREATE_JOINABLE,175 (size_t)DEFAULT_STACK_SIZE,176 (void *)NULL,177 0,178 PTHREAD_EXPLICIT_SCHED,179 {0}180 };181 */182 183 184 185 175 static cfaPthread_attr_t* get(const pthread_attr_t* attr){ 186 176 static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t),"sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)"); … … 198 188 cfaPthread_attr_t attr; 199 189 pthread_t pthreadId; 200 void *joinval; // pthreads return value 201 pthread_attr_t pthread_attr; // pthread attributes 202 void *(*start_routine)(void *); // routine start 203 void *arg; // thread parameter 204 Pthread_values* pthreadData; 205 bool isTerminated; // flag used for tryjoin 190 191 // pthreads return value 192 void *joinval; 193 194 // pthread attributes 195 pthread_attr_t pthread_attr; 196 197 void *(*start_routine)(void *); 198 void *start_arg; 199 200 // thread local data 201 pthread_values* pthreadData; 202 203 // flag used for tryjoin 204 bool isTerminated; 206 205 }; 207 206 … … 209 208 // cfaPthread entry point 210 209 void main(cfaPthread& _thread) with(_thread){ 211 joinval = start_routine( arg);210 joinval = start_routine(start_arg); 212 211 isTerminated = true; 213 }214 215 // generate pthread_t by cfaPthread ptr216 static pthread_t create( cfaPthread *p ) {217 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");218 return (pthread_t)p;219 212 } 220 213 … … 224 217 } 225 218 226 static void pthread_deletespecific_( Pthread_values* values ) { // see uMachContext::invokeTask227 Pthread_values* value;228 Pthread_keys* key;219 static void pthread_deletespecific_( pthread_values* values ) { // see uMachContext::invokeTask 220 pthread_values* value; 221 pthread_keys* key; 229 222 bool destcalled = true; 230 223 if (values != NULL){ … … 258 251 static void ^?{}(cfaPthread & mutex t){ 259 252 // delete pthread local storage 260 Pthread_values* values = t.pthreadData;253 pthread_values * values = t.pthreadData; 261 254 pthread_deletespecific_(values); 262 255 } 263 256 264 257 static void ?{}(cfaPthread &t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) { 258 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread*)"); 265 259 266 260 // set up user thread stackSize … … 269 263 270 264 // initialize _thread & cfaPthread id 271 t.pthreadId = create(&t); 272 *_thread = t.pthreadId; 265 *_thread = t.pthreadId = (pthread_t)(&t); 273 266 274 267 // if attr null, self attr will be set as default_attrs; else set to attr … … 277 270 // init start routine and arguments 278 271 t.start_routine = start_routine; 279 t. arg = arg;272 t.start_arg = arg; 280 273 t.pthreadData = NULL; 281 } // not used274 } 282 275 283 276 … … 287 280 int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW { 288 281 cfaPthread_attr_t* _attr = get(attr); 289 ?{}(*_attr); 290 *_attr = default_attrs; 282 ?{}(*_attr, default_attrs); 291 283 return 0; 292 284 } … … 360 352 // and destroyed with pthread_attr_destroy when no longer needed. 361 353 int pthread_getattr_np( pthread_t threadID, pthread_attr_t *attr ) libcfa_public __THROW { // GNU extension 362 // race condition during copy 363 cfaPthread_attr_t* _attr = get(attr); 364 ?{}(*_attr); 365 if (_attr == NULL){ 366 return ENOMEM; 367 } // if 368 *_attr = lookup( threadID )->attr; // copy all fields 354 check_nonnull(attr); 355 356 // copy all fields 357 *get(attr) = lookup( threadID )->attr; 358 369 359 return 0; 370 360 } // pthread_getattr_np … … 376 366 cfaPthread *t = alloc(); 377 367 (*t){_thread, attr, start_routine, arg}; 378 //init_user_pthread(*t, _thread, attr, start_routine, arg); 379 if (t == NULL) return EAGAIN; //no resource 380 return 0; 381 } //pthread_create_ 368 return 0; 369 } 382 370 383 371 384 372 int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 385 if (_thread == NULL) return EINVAL; // if thread is invalid 373 // if thread is invalid 374 if (_thread == NULL) return EINVAL; 386 375 if (_thread == pthread_self()) return EDEADLK; 387 cfaPthread* p = lookup(_thread); // get user thr pointer 376 377 // get user thr pointer 378 cfaPthread* p = lookup(_thread); 388 379 try { 389 380 join(*p); 390 } catchResume (ThreadCancelled(cfaPthread) * cancel) {} // if thread called pthread_exit 391 if (value_ptr != NULL ) *value_ptr = p->joinval; // fetch result 392 delete(p); 393 return 0; 394 } //pthread_join_ 395 396 int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 397 if (_thread == NULL) return EINVAL; // if thread is invalid 398 if (_thread == pthread_self()) return EDEADLK; 399 cfaPthread* p = lookup(_thread); 400 if (!p->isTerminated) return EBUSY; // thread not finished ? 401 join( *p ); 381 } 382 // if thread called pthread_exit 383 catchResume (ThreadCancelled(cfaPthread) * cancel) {} 384 385 // fetch result 402 386 if (value_ptr != NULL ) *value_ptr = p->joinval; 403 387 delete(p); 404 388 return 0; 405 } //pthread_join_ 389 } 390 391 int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 392 // if thread is invalid 393 if (_thread == NULL) return EINVAL; 394 if (_thread == pthread_self()) return EDEADLK; 395 396 cfaPthread* p = lookup(_thread); 397 398 // thread not finished ? 399 if (!p->isTerminated) return EBUSY; 400 401 join( *p ); 402 403 if (value_ptr != NULL ) *value_ptr = p->joinval; 404 delete(p); 405 return 0; 406 } 406 407 407 408 pthread_t pthread_self(void) libcfa_public __THROW { 408 return (pthread_t)(( char*)active_thread()-(sizeof(cfaPthread)-sizeof(thread$)));409 } //pthread_self_409 return (pthread_t)((uintptr_t)active_thread() - (sizeof(cfaPthread) - sizeof(thread$))); 410 } 410 411 411 412 void pthread_exit(void * status) libcfa_public __THROW { … … 551 552 552 553 // Remove key from all threads with a value. 553 Pthread_values& p;554 Sequence( Pthread_values)& head = cfa_pthread_keys[key].threads;555 for ( SeqIter( Pthread_values) iter = { head }; iter | p; ) {554 pthread_values& p; 555 Sequence(pthread_values)& head = cfa_pthread_keys[key].threads; 556 for ( SeqIter(pthread_values) iter = { head }; iter | p; ) { 556 557 remove(head, p); 557 558 p.in_use = false; … … 565 566 cfaPthread* t = lookup(pthread_self()); 566 567 // if current thread's pthreadData is NULL; initialize it 567 Pthread_values* values;568 pthread_values* values; 568 569 if (t->pthreadData == NULL){ 569 570 values = anew( PTHREAD_KEYS_MAX); … … 582 583 return EINVAL; 583 584 } // if 584 Pthread_values &entry = values[key];585 pthread_values &entry = values[key]; 585 586 if ( ! entry.in_use ) { 586 587 entry.in_use = true; … … 599 600 if (t->pthreadData == NULL) return NULL; 600 601 lock(key_lock); 601 Pthread_values &entry = ((Pthread_values *)t->pthreadData)[key];602 pthread_values &entry = ((pthread_values *)t->pthreadData)[key]; 602 603 if ( ! entry.in_use ) { 603 604 unlock( key_lock ); … … 611 612 612 613 //######################### Parallelism ######################### 613 void pthread_delete_kernel_threads_() libcfa_public__THROW { // see uMain::~uMain614 void pthread_delete_kernel_threads_() __THROW { // see uMain::~uMain 614 615 Pthread_kernel_threads& p; 615 616 for ( StackIter(Pthread_kernel_threads) iter = {cfa_pthreads_kernel_threads}; iter | p; ) { … … 618 619 } // pthread_delete_kernel_threads_ 619 620 620 int pthread_getconcurrency( void ) libcfa_public__THROW { // XOPEN extension621 int pthread_getconcurrency( void ) __THROW { // XOPEN extension 621 622 return cfa_pthreads_kernel_threads_zero ? 0 : cfa_pthreads_no_kernel_threads; 622 623 } // pthread_getconcurrency 623 624 624 625 int pthread_setconcurrency( int new_level ) libcfa_public __THROW { // XOPEN extension 625 626 627 cfa_pthreads_kernel_threads_zero = true; // remember set to zero, but ignore628 return 0; // do not do kernel thread management629 630 631 632 633 push(cfa_pthreads_kernel_threads, *new() );634 635 636 delete(&pop(cfa_pthreads_kernel_threads));637 638 639 626 if ( new_level < 0 ) return EINVAL; 627 if ( new_level == 0 ) { 628 cfa_pthreads_kernel_threads_zero = true; // remember set to zero, but ignore 629 return 0; // do not do kernel thread management 630 } // exit 631 cfa_pthreads_kernel_threads_zero = false; 632 lock( concurrency_lock ); 633 for ( ; new_level > cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads += 1 ) { // add processors ? 634 push(cfa_pthreads_kernel_threads, *new() ); 635 } // for 636 for ( ; new_level < cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads -= 1 ) { // remove processors ? 637 delete(&pop(cfa_pthreads_kernel_threads)); 638 } // for 639 unlock( concurrency_lock ); 640 return 0; 640 641 } // pthread_setconcurrency 641 642 … … 644 645 645 646 int pthread_sigmask( int /* how */, const sigset_t * /* set */, sigset_t * /* oset */ ) libcfa_public __THROW { 646 return 0; 647 abort( "pthread_sigmask : not implemented" ); 648 return 0; 647 649 } // pthread_sigmask 648 650 … … 657 659 658 660 int pthread_sigqueue(pthread_t , int sig, const union sigval) libcfa_public __THROW { 661 abort( "pthread_sigqueue : not implemented" ); 659 662 return 0; 660 663 } // pthread_sigqueue … … 662 665 //######################### Scheduling ######################### 663 666 int pthread_detach( pthread_t threadID ) __THROW { 664 abort( "pthread_detach " );667 abort( "pthread_detach : not implemented" ); 665 668 return 0; 666 669 } // pthread_detach … … 683 686 684 687 int pthread_mutexattr_destroy( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW { 685 return 0;688 return 0; 686 689 } // pthread_mutexattr_destroy 687 690 688 691 int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW { 689 return 0;692 return 0; 690 693 } // pthread_mutexattr_setpshared 691 694 692 695 int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW { 693 return 0;696 return 0; 694 697 } // pthread_mutexattr_getpshared 695 698 696 699 int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW { 697 return 0;700 return 0; 698 701 } // pthread_mutexattr_setprotocol 699 702 700 703 int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW { 701 return 0;704 return 0; 702 705 } // pthread_mutexattr_getprotocol 703 706 704 707 int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW { 705 return 0;708 return 0; 706 709 } // pthread_mutexattr_setprioceiling 707 710 708 711 int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW { 709 return 0;712 return 0; 710 713 } // pthread_mutexattr_getprioceiling 711 714 712 715 int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW { 713 return 0;716 return 0; 714 717 } // pthread_mutex_setprioceiling 715 718 716 719 int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW { 717 return 0;720 return 0; 718 721 } // pthread_mutex_getprioceiling 719 722 720 723 int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW { 721 return 0;724 return 0; 722 725 } // pthread_mutexattr_gettype 723 726 724 727 int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW { 725 return 0;728 return 0; 726 729 } // pthread_mutexattr_settype 727 730
Note: See TracChangeset
for help on using the changeset viewer.