- Timestamp:
- Sep 22, 2022, 3:10:12 PM (3 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation
- Children:
- df6cc9d
- Parents:
- 95dab9e
- Location:
- libcfa/src
- Files:
-
- 5 edited
-
bits/defs.hfa (modified) (2 diffs)
-
concurrency/kernel/private.hfa (modified) (1 diff)
-
concurrency/pthread.cfa (modified) (12 diffs)
-
interpose.cfa (modified) (1 diff)
-
interpose_thread.cfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/bits/defs.hfa
r95dab9e r9cd5bd2 21 21 #include <stdint.h> 22 22 #include <assert.h> 23 #include <signal.h>24 23 25 24 #define likely(x) __builtin_expect(!!(x), 1) … … 59 58 void abort( bool signalAbort, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )); 60 59 extern "C" { 60 #endif 61 61 void __cabi_abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )); 62 #ifdef __cforall 62 63 } 63 64 #endif -
libcfa/src/concurrency/kernel/private.hfa
r95dab9e r9cd5bd2 20 20 #endif 21 21 22 #include <signal.h> 23 22 24 #include "kernel.hfa" 23 25 #include "thread.hfa" -
libcfa/src/concurrency/pthread.cfa
r95dab9e r9cd5bd2 17 17 #define _GNU_SOURCE 18 18 19 #include <signal.h> 19 20 #include <pthread.h> 20 21 #include <errno.h> … … 23 24 24 25 25 #pragma GCC diagnostic push 26 #pragma GCC diagnostic ignored "-Wnonnull-compare" 26 #define check_nonnull(x) asm("": "+rm"(x)); if( x == 0p ) return EINVAL; 27 27 28 28 /* pthread key, pthread once inner routine mutual exclusion */ … … 31 31 //######################### Local Storage Helpers ######################### 32 32 33 #define PTHREADS_THR_MAX 256 34 #define PTHREAD_KEYS_MAX 1024 33 enum { PTHREAD_KEYS_MAX = 1024 }; 34 35 35 struct Pthread_values{ 36 inline Seqable;37 void* value;38 bool in_use;36 inline Seqable; 37 void* value; 38 bool in_use; 39 39 }; 40 40 41 41 42 42 static Pthread_values *& Back( Pthread_values * n ) { 43 return (Pthread_values *)Back( (Seqable *)n );43 return (Pthread_values *)Back( (Seqable *)n ); 44 44 } 45 45 static Pthread_values *& Next( Pthread_values * n ) { 46 return (Pthread_values *)Next( (Colable *)n );46 return (Pthread_values *)Next( (Colable *)n ); 47 47 } 48 48 49 49 struct Pthread_keys{ 50 bool in_use;51 void (*destructor)( void * );52 Sequence(Pthread_values) threads;50 bool in_use; 51 void (*destructor)( void * ); 52 Sequence(Pthread_values) threads; 53 53 }; // Pthread keys 54 54 55 55 static void ?{}(Pthread_keys& k){ 56 //sout | "inited"; 57 k.threads{}; 56 k.threads{}; 58 57 } 59 58 60 59 // Create storage separately to ensure no constructors are called. 61 //static char cfa_pthread_keys_storage[sizeof(Pthread_keys) * PTHREAD_KEYS_MAX] __attribute__((aligned (16))) = {0};62 60 static Pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16))); 63 61 64 62 static void init_pthread_storage(){ 65 for (int i = 0; i < PTHREAD_KEYS_MAX; i++){66 cfa_pthread_keys_storage[i]{};67 }63 for (int i = 0; i < PTHREAD_KEYS_MAX; i++){ 64 cfa_pthread_keys_storage[i]{}; 65 } 68 66 } 69 67 … … 78 76 79 77 struct Pthread_kernel_threads{ 80 inline Colable;81 processor p;78 inline Colable; 79 processor p; 82 80 }; 83 81 84 82 Pthread_kernel_threads *& Next( Pthread_kernel_threads * n ) { 85 return (Pthread_kernel_threads *)Next( (Colable *)n );83 return (Pthread_kernel_threads *)Next( (Colable *)n ); 86 84 } 87 85 … … 97 95 /* condvar helper routines */ 98 96 static void init(pthread_cond_t* pcond){ 99 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");100 cfa2pthr_cond_var_t* _cond = (cfa2pthr_cond_var_t*)pcond;101 ?{}(*_cond);97 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 98 cfa2pthr_cond_var_t* _cond = (cfa2pthr_cond_var_t*)pcond; 99 ?{}(*_cond); 102 100 } 103 101 104 102 static cfa2pthr_cond_var_t* get(pthread_cond_t* pcond){ 105 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");106 return (cfa2pthr_cond_var_t*)pcond;103 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 104 return (cfa2pthr_cond_var_t*)pcond; 107 105 } 108 106 109 107 static void destroy(pthread_cond_t* cond){ 110 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");111 ^?{}(*get(cond));108 static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)"); 109 ^?{}(*get(cond)); 112 110 } 113 111 … … 123 121 // if pthread_mutex_t is initialized by PTHREAD_MUTEX_INITIALIZER, _lock_val should be 0 124 122 if ( _lock_val == 0 ) { // static initialized ? 125 lock(magic_mutex_check); // race126 _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;127 if ( _lock_val == 0 ) { // static initialized ?123 lock(magic_mutex_check); // race 124 _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock; 125 if ( _lock_val == 0 ) { // static initialized ? 128 126 pthread_mutex_init( t, NULL ); 129 } // if130 unlock(magic_mutex_check); // race127 } // if 128 unlock(magic_mutex_check); // race 131 129 } // if 132 130 } // mutex_check … … 134 132 135 133 static void init(pthread_mutex_t* plock){ 136 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");137 simple_owner_lock* _lock = (simple_owner_lock*)plock;138 ?{}(*_lock);134 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 135 simple_owner_lock* _lock = (simple_owner_lock*)plock; 136 ?{}(*_lock); 139 137 } 140 138 141 139 static simple_owner_lock* get(pthread_mutex_t* plock){ 142 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");143 return (simple_owner_lock*)plock;140 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 141 return (simple_owner_lock*)plock; 144 142 } 145 143 146 144 static void destroy(pthread_mutex_t* plock){ 147 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");148 ^?{}(*get(plock));145 static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)"); 146 ^?{}(*get(plock)); 149 147 } 150 148 … … 161 159 162 160 static const cfaPthread_attr_t default_attrs{ 163 0,164 0,165 (size_t)65000,166 (void *)NULL,167 0,168 0,169 {0}161 0, 162 0, 163 (size_t)65000, 164 (void *)NULL, 165 0, 166 0, 167 {0} 170 168 }; 171 169 … … 173 171 /* 174 172 static const cfaPthread_attr_t default_attrs = { 175 PTHREAD_SCOPE_SYSTEM,176 PTHREAD_CREATE_JOINABLE,177 (size_t)DEFAULT_STACK_SIZE,178 (void *)NULL,179 0,180 PTHREAD_EXPLICIT_SCHED,181 {0}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} 182 180 }; 183 181 */ … … 186 184 187 185 static cfaPthread_attr_t* get(const pthread_attr_t* attr){ 188 static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t),"sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)");189 return (cfaPthread_attr_t*)attr;186 static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t),"sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)"); 187 return (cfaPthread_attr_t*)attr; 190 188 } 191 189 … … 195 193 // exception for cancel_stack in pthread_exit 196 194 exception pthread_exit_exp {}; 197 static vtable(pthread_exit_exp) exp ;195 static vtable(pthread_exit_exp) exp_vt; 198 196 199 197 thread cfaPthread{ 200 cfaPthread_attr_t attr;201 pthread_t pthreadId;202 void *joinval; // pthreads return value198 cfaPthread_attr_t attr; 199 pthread_t pthreadId; 200 void *joinval; // pthreads return value 203 201 pthread_attr_t pthread_attr; // pthread attributes 204 void *(*start_routine)(void *); // routine start205 void *arg; // thread parameter 206 Pthread_values* pthreadData;207 bool isTerminated; // flag used for tryjoin202 void *(*start_routine)(void *); // routine start 203 void *arg; // thread parameter 204 Pthread_values* pthreadData; 205 bool isTerminated; // flag used for tryjoin 208 206 }; 209 207 … … 211 209 // cfaPthread entry point 212 210 void main(cfaPthread& _thread) with(_thread){ 213 joinval = start_routine(arg);214 isTerminated = true;211 joinval = start_routine(arg); 212 isTerminated = true; 215 213 } 216 214 217 215 // generate pthread_t by cfaPthread ptr 218 216 static pthread_t create( cfaPthread *p ) { 219 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");217 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)"); 220 218 return (pthread_t)p; 221 219 } 222 220 223 221 static cfaPthread *lookup( pthread_t p ){ 224 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");225 return (cfaPthread*)p;222 static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)"); 223 return (cfaPthread*)p; 226 224 } 227 225 228 226 static void pthread_deletespecific_( Pthread_values* values ) { // see uMachContext::invokeTask 229 Pthread_values* value;230 Pthread_keys* key;231 bool destcalled = true;232 if (values != NULL){233 for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) {234 destcalled = false;235 lock(key_lock);236 for (int i = 0; i < PTHREAD_KEYS_MAX; i++){237 // for each valid key238 if ( values[i].in_use){239 value = &values[i];240 key = &cfa_pthread_keys[i];241 value->in_use = false;242 remove(key->threads, *value);243 // if a key value has a non-NULL destructor pointer, and the thread has a non-NULL value associated with that key, 244 // the value of the key is set to NULL, and then the function pointed to is called with the previously associated value as its sole argument.245 if (value->value != NULL && key->destructor != NULL){246 unlock(key_lock);247 key->destructor(value->value); // run destructor248 lock(key_lock);249 destcalled = true;250 } // if251 value->value = NULL;252 } // if253 } // for254 unlock(key_lock);255 } // for256 free(values);257 } // if227 Pthread_values* value; 228 Pthread_keys* key; 229 bool destcalled = true; 230 if (values != NULL){ 231 for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) { 232 destcalled = false; 233 lock(key_lock); 234 for (int i = 0; i < PTHREAD_KEYS_MAX; i++){ 235 // for each valid key 236 if ( values[i].in_use){ 237 value = &values[i]; 238 key = &cfa_pthread_keys[i]; 239 value->in_use = false; 240 remove(key->threads, *value); 241 // if a key value has a non-NULL destructor pointer, and the thread has a non-NULL value associated with that key, 242 // the value of the key is set to NULL, and then the function pointed to is called with the previously associated value as its sole argument. 243 if (value->value != NULL && key->destructor != NULL){ 244 unlock(key_lock); 245 key->destructor(value->value); // run destructor 246 lock(key_lock); 247 destcalled = true; 248 } // if 249 value->value = NULL; 250 } // if 251 } // for 252 unlock(key_lock); 253 } // for 254 free(values); 255 } // if 258 256 } 259 257 260 258 static void ^?{}(cfaPthread & mutex t){ 261 // delete pthread local storage262 Pthread_values* values = t.pthreadData;263 pthread_deletespecific_(values);259 // delete pthread local storage 260 Pthread_values* values = t.pthreadData; 261 pthread_deletespecific_(values); 264 262 } 265 263 266 264 static void ?{}(cfaPthread &t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) { 267 268 // set up user thread stackSize269 cfaPthread_attr_t * attr = get(_attr);270 ((thread&)t){ attr ? attr->stacksize: DEFAULT_STACK_SIZE };271 272 // initialize _thread & cfaPthread id273 t.pthreadId = create(&t);274 *_thread = t.pthreadId;275 276 // if attr null, self attr will be set as default_attrs; else set to attr 277 t.attr = (attr != NULL ? *attr : default_attrs);278 279 // init start routine and arguments280 t.start_routine = start_routine;281 t.arg = arg;282 t.pthreadData = NULL;265 266 // set up user thread stackSize 267 cfaPthread_attr_t * attr = get(_attr); 268 ((thread&)t){ attr ? attr->stacksize: DEFAULT_STACK_SIZE }; 269 270 // initialize _thread & cfaPthread id 271 t.pthreadId = create(&t); 272 *_thread = t.pthreadId; 273 274 // if attr null, self attr will be set as default_attrs; else set to attr 275 t.attr = (attr != NULL ? *attr : default_attrs); 276 277 // init start routine and arguments 278 t.start_routine = start_routine; 279 t.arg = arg; 280 t.pthreadData = NULL; 283 281 } // not used 284 282 285 283 286 284 extern "C"{ 287 //######################### Pthread Attrs ######################### 288 289 int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW { 290 cfaPthread_attr_t* _attr = get(attr); 291 ?{}(*_attr); 292 *_attr = default_attrs; 293 return 0; 294 } 295 int pthread_attr_destroy(pthread_attr_t *attr) libcfa_public __THROW { 296 ^?{}(*get(attr)); 297 return 0; 298 } 299 300 int pthread_attr_setscope( pthread_attr_t *attr, int contentionscope ) libcfa_public __THROW { 301 get( attr )->contentionscope = contentionscope; 302 return 0; 303 } // pthread_attr_setscope 304 305 int pthread_attr_getscope( const pthread_attr_t *attr, int *contentionscope ) libcfa_public __THROW { 306 *contentionscope = get( attr )->contentionscope; 307 return 0; 308 } // pthread_attr_getscope 309 310 int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate ) libcfa_public __THROW { 311 get( attr )->detachstate = detachstate; 312 return 0; 313 } // pthread_attr_setdetachstate 314 315 int pthread_attr_getdetachstate( const pthread_attr_t *attr, int *detachstate ) libcfa_public __THROW { 316 *detachstate = get( attr )->detachstate; 317 return 0; 318 } // pthread_attr_getdetachstate 319 320 int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize ) libcfa_public __THROW { 321 get( attr )->stacksize = stacksize; 322 return 0; 323 } // pthread_attr_setstacksize 324 325 int pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize ) libcfa_public __THROW { 326 *stacksize = get( attr )->stacksize; 327 return 0; 328 } // pthread_attr_getstacksize 329 330 int pthread_attr_getguardsize( const pthread_attr_t * /* attr */, size_t * /* guardsize */ ) libcfa_public __THROW { 331 return 0; 332 } // pthread_attr_getguardsize 333 334 int pthread_attr_setguardsize( pthread_attr_t * /* attr */, size_t /* guardsize */ ) libcfa_public __THROW { 335 return 0; 336 } // pthread_attr_setguardsize 337 338 int pthread_attr_setstackaddr( pthread_attr_t *attr, void *stackaddr ) libcfa_public __THROW { 339 get( attr )->stackaddr = stackaddr; 340 return 0; 341 } // pthread_attr_setstackaddr 342 343 int pthread_attr_getstackaddr( const pthread_attr_t *attr, void **stackaddr ) libcfa_public __THROW { 344 *stackaddr = get( attr )->stackaddr; 345 return 0; 346 } // pthread_attr_getstackaddr 347 348 int pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW { 349 get( attr )->stackaddr = stackaddr; 350 get( attr )->stacksize = stacksize; 351 return 0; 352 } // pthread_attr_setstack 353 354 int pthread_attr_getstack( const pthread_attr_t *attr, void **stackaddr, size_t *stacksize ) libcfa_public __THROW { 355 *stackaddr = get( attr )->stackaddr; 356 *stacksize = get( attr )->stacksize; 357 return 0; 358 } // pthread_attr_getstack 359 360 // Initialize thread attribute *attr with attributes corresponding to the 361 // already running thread threadID. It shall be called on unitialized attr 362 // and destroyed with pthread_attr_destroy when no longer needed. 363 int pthread_getattr_np( pthread_t threadID, pthread_attr_t *attr ) libcfa_public __THROW { // GNU extension 364 // race condition during copy 365 cfaPthread_attr_t* _attr = get(attr); 366 ?{}(*_attr); 367 if (_attr == NULL){ 368 return ENOMEM; 369 } // if 370 *_attr = lookup( threadID )->attr; // copy all fields 371 return 0; 372 } // pthread_getattr_np 373 374 375 //######################### Threads ######################### 376 377 int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) libcfa_public __THROW { 378 cfaPthread *t = alloc(); 379 (*t){_thread, attr, start_routine, arg}; 380 //init_user_pthread(*t, _thread, attr, start_routine, arg); 381 if (t == NULL) return EAGAIN; //no resource 382 return 0; 383 } //pthread_create_ 384 385 386 int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 387 if (_thread == NULL) return EINVAL; // if thread is invalid 388 if (_thread == pthread_self()) return EDEADLK; 389 cfaPthread* p = lookup(_thread); // get user thr pointer 390 try { 391 join(*p); 392 } catchResume (ThreadCancelled(cfaPthread) * cancel) {} // if thread called pthread_exit 393 if (value_ptr != NULL ) *value_ptr = p->joinval; // fetch result 394 delete(p); 395 return 0; 396 } //pthread_join_ 397 398 int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 399 if (_thread == NULL) return EINVAL; // if thread is invalid 400 if (_thread == pthread_self()) return EDEADLK; 401 cfaPthread* p = lookup(_thread); 402 if (!p->isTerminated) return EBUSY; // thread not finished ? 403 join( *p ); 404 if (value_ptr != NULL ) *value_ptr = p->joinval; 405 delete(p); 406 return 0; 407 } //pthread_join_ 408 409 pthread_t pthread_self(void) libcfa_public __THROW { 410 return (pthread_t)((char*)active_thread()-(sizeof(cfaPthread)-sizeof(thread$))); 411 } //pthread_self_ 412 413 void pthread_exit(void * status) libcfa_public __THROW { 414 pthread_t pid = pthread_self(); 415 cfaPthread* _thread = (cfaPthread*)pid; 416 _thread->joinval = status; // set return value 417 _thread->isTerminated = 1; // set terminated flag 418 cancel_stack((pthread_exit_exp){&exp}); 419 } //pthread_exit_ 420 421 int pthread_yield( void ) __THROW { // GNU extension 422 yield(); 423 return 0; 424 } 425 426 427 //######################### Mutex ######################### 428 429 int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t *attr) libcfa_public __THROW { 430 if (_mutex == NULL) return EINVAL; 431 432 init(_mutex); 433 return 0; 434 } //pthread_mutex_init_ 435 436 437 int pthread_mutex_destroy(pthread_mutex_t *_mutex) libcfa_public __THROW{ 438 if (_mutex == NULL){ 439 return EINVAL; 440 } // if mutex invalid 441 simple_owner_lock* _lock = get(_mutex); 442 if (_lock->owner != NULL){ 443 return EBUSY; 444 } 445 destroy(_mutex); 446 return 0; 447 } //pthread_mutex_destroy_ 448 449 int pthread_mutex_lock(pthread_mutex_t *_mutex) libcfa_public __THROW{ 450 if (_mutex == NULL) { 451 return EINVAL; 452 } // if mutex invalid 453 mutex_check(_mutex); 454 simple_owner_lock* _lock = get(_mutex); 455 lock(*_lock); 456 return 0; 457 } //pthread_mutex_lock_ 458 459 int pthread_mutex_unlock(pthread_mutex_t *_mutex) libcfa_public __THROW{ 460 if (_mutex == NULL) { 461 return EINVAL; 462 } // invalid mutex 463 simple_owner_lock* _lock = get(_mutex); 464 if (_lock->owner != active_thread()){ 465 return EPERM; 466 } // current thread does not hold the mutex 467 unlock(*_lock); 468 return 0; 469 } //pthread_mutex_unlock_ 470 471 int pthread_mutex_trylock(pthread_mutex_t *_mutex) libcfa_public __THROW{ 472 if (_mutex == NULL) { 473 return EINVAL; 474 } // if mutex invalid 475 simple_owner_lock* _lock = get(_mutex); 476 if (_lock->owner != active_thread() && _lock->owner != NULL){ 477 return EBUSY; 478 } // if mutex is owned 479 lock(*_lock); 480 return 0; 481 } //pthread_mutex_trylock_ 482 483 //######################### Conditional Variable ######################### 484 485 /* conditional variable routines */ 486 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) libcfa_public __THROW { 487 if (cond == NULL) return EINVAL; 488 init(cond); 489 return 0; 490 } //pthread_cond_init 491 492 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *_mutex) libcfa_public __THROW { 493 if (cond == NULL || _mutex == NULL){ 494 return EINVAL; 495 } // invalid cond 496 wait(*get(cond), *get(_mutex)); 497 return 0; 498 } // pthread_cond_wait 499 500 int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * _mutex, const struct timespec * abstime) libcfa_public __THROW { 501 if (cond == NULL || _mutex == NULL){ 502 return EINVAL; 503 } // invalid cond 504 wait(*get(cond), *get(_mutex), *abstime); 505 return 0; 506 } // pthread_cond_timedwait 507 508 int pthread_cond_signal(pthread_cond_t *cond) libcfa_public __THROW { 509 if (cond == NULL){ 510 return EINVAL; 511 } // invalid cond 512 return notify_one(*get(cond)); 513 } // pthread_cond_signal 514 515 int pthread_cond_broadcast(pthread_cond_t *cond) libcfa_public __THROW { 516 if (cond == NULL){ 517 return EINVAL; 518 } // invalid cond 519 return notify_all(*get(cond)); 520 } // pthread_cond_broadcast 521 522 int pthread_cond_destroy(pthread_cond_t *cond) libcfa_public __THROW { 523 if (cond == NULL){ 524 return EINVAL; 525 } // invalid cond 526 destroy(cond); 527 return 0; 528 } // pthread_cond_destroy 529 530 531 532 //######################### Local storage ######################### 533 534 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) libcfa_public __THROW { 535 static_assert(sizeof(pthread_once_t) >= sizeof(int),"sizeof(pthread_once_t) < sizeof(int)"); 536 if (once_control == NULL){ 537 return EINVAL; 538 } 539 if (init_routine == NULL){ 540 return EINVAL; 541 } 542 lock(once_lock); 543 if ( *((int *)once_control) == 0 ) { 544 init_routine(); 545 *((int *)once_control) = 1; 546 } // if 547 unlock(once_lock); 548 return 0; 549 } // pthread_once 550 551 int pthread_key_create( pthread_key_t *key, void (*destructor)( void * ) ) libcfa_public __THROW { 552 lock(key_lock); 553 for ( int i = 0; i < PTHREAD_KEYS_MAX; i += 1 ) { 554 if ( ! cfa_pthread_keys[i].in_use ) { 555 cfa_pthread_keys[i].in_use = true; 556 cfa_pthread_keys[i].destructor = destructor; 557 unlock( key_lock ); 558 *key = i; 559 return 0; 560 } // if 561 } // for 562 unlock(key_lock); 563 return EAGAIN; 564 } // pthread_key_create 565 566 int pthread_key_delete( pthread_key_t key ) libcfa_public __THROW { 567 lock(key_lock); 568 if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) { 569 unlock( key_lock ); 570 return EINVAL; 571 } // if 572 cfa_pthread_keys[key].in_use = false; 573 cfa_pthread_keys[key].destructor = NULL; 574 575 // Remove key from all threads with a value. 576 Pthread_values& p; 577 Sequence(Pthread_values)& head = cfa_pthread_keys[key].threads; 578 for ( SeqIter(Pthread_values) iter = { head }; iter | p; ) { 579 remove(head, p); 580 p.in_use = false; 581 } 582 unlock(key_lock); 583 return 0; 584 } // pthread_key_delete 585 586 int pthread_setspecific( pthread_key_t key, const void *value ) libcfa_public __THROW { 587 // get current thread 588 cfaPthread* t = lookup(pthread_self()); 589 // if current thread's pthreadData is NULL; initialize it 590 Pthread_values* values; 591 if (t->pthreadData == NULL){ 592 values = anew( PTHREAD_KEYS_MAX); 593 t->pthreadData = values; 594 for (int i = 0;i < PTHREAD_KEYS_MAX; i++){ 595 t->pthreadData[i].in_use = false; 596 } // for 597 } else { 598 values = t->pthreadData; 599 } // if 600 // find corresponding key and set value 601 lock(key_lock); 602 // if invalid key 603 if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) { 604 unlock( key_lock ); 605 return EINVAL; 606 } // if 607 Pthread_values &entry = values[key]; 608 if ( ! entry.in_use ) { 609 entry.in_use = true; 610 add(cfa_pthread_keys[key].threads, entry); 611 } // if 612 entry.value = (void *)value; 613 unlock(key_lock); 614 return 0; 615 } //pthread_setspecific 616 617 void* pthread_getspecific(pthread_key_t key) libcfa_public __THROW { 618 if (key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use) return NULL; 619 620 // get current thread 621 cfaPthread* t = lookup(pthread_self()); 622 if (t->pthreadData == NULL) return NULL; 623 lock(key_lock); 624 Pthread_values &entry = ((Pthread_values *)t->pthreadData)[key]; 625 if ( ! entry.in_use ) { 626 unlock( key_lock ); 627 return NULL; 628 } // if 629 void *value = entry.value; 630 unlock(key_lock); 631 632 return value; 633 } //pthread_get_specific 634 635 //######################### Parallelism ######################### 636 void pthread_delete_kernel_threads_() libcfa_public __THROW { // see uMain::~uMain 637 Pthread_kernel_threads& p; 638 for ( StackIter(Pthread_kernel_threads) iter = {cfa_pthreads_kernel_threads}; iter | p; ) { 639 delete(&p); 640 } // for 641 } // pthread_delete_kernel_threads_ 642 643 int pthread_getconcurrency( void ) libcfa_public __THROW { // XOPEN extension 644 return cfa_pthreads_kernel_threads_zero ? 0 : cfa_pthreads_no_kernel_threads; 645 } // pthread_getconcurrency 646 647 int pthread_setconcurrency( int new_level ) libcfa_public __THROW { // XOPEN extension 648 if ( new_level < 0 ) return EINVAL; 649 if ( new_level == 0 ) { 650 cfa_pthreads_kernel_threads_zero = true; // remember set to zero, but ignore 651 return 0; // do not do kernel thread management 652 } // exit 653 cfa_pthreads_kernel_threads_zero = false; 654 lock( concurrency_lock ); 655 for ( ; new_level > cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads += 1 ) { // add processors ? 656 push(cfa_pthreads_kernel_threads, *new() ); 657 } // for 658 for ( ; new_level < cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads -= 1 ) { // remove processors ? 659 delete(&pop(cfa_pthreads_kernel_threads)); 660 } // for 661 unlock( concurrency_lock ); 662 return 0; 663 } // pthread_setconcurrency 664 665 //######################### Signal ######################### 666 667 668 int pthread_sigmask( int /* how */, const sigset_t * /* set */, sigset_t * /* oset */ ) libcfa_public __THROW { 669 return 0; 670 } // pthread_sigmask 671 672 int pthread_kill( pthread_t _thread __attribute__(( unused )), int sig ) libcfa_public __THROW { 673 if ( sig == 0 ) { 674 return 0; 675 } else { 676 abort( "pthread_kill : not implemented" ); 677 } // if 678 return 0; 679 } // pthread_kill 680 681 int pthread_sigqueue(pthread_t , int sig, const union sigval) libcfa_public __THROW { 682 return 0; 683 } // pthread_sigqueue 684 685 //######################### Scheduling ######################### 686 int pthread_detach( pthread_t threadID ) __THROW { 687 abort( "pthread_detach" ); 688 return 0; 689 } // pthread_detach 690 691 int pthread_setschedparam( pthread_t /* thread */, int /* policy */, const struct sched_param * /* param */ ) libcfa_public __THROW { 692 abort( "pthread_setschedparam : not implemented" ); 693 return 0; 694 } // pthread_setschedparam 695 696 int pthread_getschedparam( pthread_t /* thread */, int */* policy */, struct sched_param * /* param */ ) libcfa_public __THROW { 697 abort( "pthread_getschedparam : not implemented" ); 698 return 0; 699 } // pthread_getschedparam 700 701 //######################### Mutex Attr ######################### 702 703 int pthread_mutexattr_init( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW { 704 return 0; 705 } // pthread_mutexattr_init 706 707 int pthread_mutexattr_destroy( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW { 708 return 0; 709 } // pthread_mutexattr_destroy 710 711 int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW { 712 return 0; 713 } // pthread_mutexattr_setpshared 714 715 int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW { 716 return 0; 717 } // pthread_mutexattr_getpshared 718 719 int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW { 720 return 0; 721 } // pthread_mutexattr_setprotocol 722 723 int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW { 724 return 0; 725 } // pthread_mutexattr_getprotocol 726 727 int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW { 728 return 0; 729 } // pthread_mutexattr_setprioceiling 730 731 int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW { 732 return 0; 733 } // pthread_mutexattr_getprioceiling 734 735 int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW { 736 return 0; 737 } // pthread_mutex_setprioceiling 738 739 int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW { 740 return 0; 741 } // pthread_mutex_getprioceiling 742 743 int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW { 744 return 0; 745 } // pthread_mutexattr_gettype 746 747 int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW { 748 return 0; 749 } // pthread_mutexattr_settype 750 751 //######################### Mutex ######################### 752 753 int pthread_mutex_timedlock( pthread_mutex_t *__restrict /* __mutex */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW { 754 abort( "pthread_mutex_timedlock" ); 755 } // pthread_mutex_timedlock 756 757 //######################### Condition ######################### 758 759 int pthread_condattr_getclock( __const pthread_condattr_t * __restrict /* __attr */, __clockid_t *__restrict /* __clock_id */ ) libcfa_public __THROW { 760 abort( "pthread_condattr_getclock" ); 761 } // pthread_condattr_getclock 762 763 int pthread_condattr_setclock( pthread_condattr_t * /* __attr */, __clockid_t /* __clock_id */ ) libcfa_public __THROW { 764 abort( "pthread_condattr_setclock" ); 765 } // pthread_condattr_setclock 766 767 //######################### Spinlock ######################### 768 769 int pthread_spin_init( pthread_spinlock_t * /* __lock */, int /*__pshared */ ) libcfa_public __THROW { 770 abort( "pthread_spin_init" ); 771 } // pthread_spin_init 772 773 int pthread_spin_destroy( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 774 abort( "pthread_spin_destroy" ); 775 } // pthread_spin_destroy 776 777 int pthread_spin_lock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 778 abort( "pthread_spin_lock" ); 779 } // pthread_spin_lock 780 781 int pthread_spin_trylock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 782 abort( "pthread_spin_trylock" ); 783 } // pthread_spin_trylock 784 785 int pthread_spin_unlock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 786 abort( "pthread_spin_unlock" ); 787 } // pthread_spin_unlock 788 789 //######################### Barrier ######################### 790 791 int pthread_barrier_init( pthread_barrier_t *__restrict /* __barrier */, __const pthread_barrierattr_t *__restrict /* __attr */, unsigned int /* __count */ ) libcfa_public __THROW { 792 abort( "pthread_barrier_init" ); 793 } // pthread_barrier_init 794 795 int pthread_barrier_destroy( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW { 796 abort( "pthread_barrier_destroy" ); 797 } // pthread_barrier_destroy 798 799 int pthread_barrier_wait( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW { 800 abort( "pthread_barrier_wait" ); 801 } // pthread_barrier_wait 802 803 int pthread_barrierattr_init( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW { 804 abort( "pthread_barrierattr_init" ); 805 } // pthread_barrierattr_init 806 807 int pthread_barrierattr_destroy( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW { 808 abort( "pthread_barrierattr_destroy" ); 809 } // pthread_barrierattr_destroy 810 811 int pthread_barrierattr_getpshared( __const pthread_barrierattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW { 812 abort( "pthread_barrierattr_getpshared" ); 813 } // pthread_barrierattr_getpshared 814 815 int pthread_barrierattr_setpshared( pthread_barrierattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW { 816 abort( "pthread_barrierattr_setpshared" ); 817 } // pthread_barrierattr_setpshared 818 819 //######################### Clock ######################### 820 821 int pthread_getcpuclockid( pthread_t /* __thread_id */, __clockid_t * /* __clock_id */ ) libcfa_public __THROW { 822 abort( "pthread_getcpuclockid" ); 823 } // pthread_getcpuclockid 824 825 // pthread_atfork() 285 //######################### Pthread Attrs ######################### 286 287 int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW { 288 cfaPthread_attr_t* _attr = get(attr); 289 ?{}(*_attr); 290 *_attr = default_attrs; 291 return 0; 292 } 293 int pthread_attr_destroy(pthread_attr_t *attr) libcfa_public __THROW { 294 ^?{}(*get(attr)); 295 return 0; 296 } 297 298 int pthread_attr_setscope( pthread_attr_t *attr, int contentionscope ) libcfa_public __THROW { 299 get( attr )->contentionscope = contentionscope; 300 return 0; 301 } // pthread_attr_setscope 302 303 int pthread_attr_getscope( const pthread_attr_t *attr, int *contentionscope ) libcfa_public __THROW { 304 *contentionscope = get( attr )->contentionscope; 305 return 0; 306 } // pthread_attr_getscope 307 308 int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate ) libcfa_public __THROW { 309 get( attr )->detachstate = detachstate; 310 return 0; 311 } // pthread_attr_setdetachstate 312 313 int pthread_attr_getdetachstate( const pthread_attr_t *attr, int *detachstate ) libcfa_public __THROW { 314 *detachstate = get( attr )->detachstate; 315 return 0; 316 } // pthread_attr_getdetachstate 317 318 int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize ) libcfa_public __THROW { 319 get( attr )->stacksize = stacksize; 320 return 0; 321 } // pthread_attr_setstacksize 322 323 int pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize ) libcfa_public __THROW { 324 *stacksize = get( attr )->stacksize; 325 return 0; 326 } // pthread_attr_getstacksize 327 328 int pthread_attr_getguardsize( const pthread_attr_t * /* attr */, size_t * /* guardsize */ ) libcfa_public __THROW { 329 return 0; 330 } // pthread_attr_getguardsize 331 332 int pthread_attr_setguardsize( pthread_attr_t * /* attr */, size_t /* guardsize */ ) libcfa_public __THROW { 333 return 0; 334 } // pthread_attr_setguardsize 335 336 int pthread_attr_setstackaddr( pthread_attr_t *attr, void *stackaddr ) libcfa_public __THROW { 337 get( attr )->stackaddr = stackaddr; 338 return 0; 339 } // pthread_attr_setstackaddr 340 341 int pthread_attr_getstackaddr( const pthread_attr_t *attr, void **stackaddr ) libcfa_public __THROW { 342 *stackaddr = get( attr )->stackaddr; 343 return 0; 344 } // pthread_attr_getstackaddr 345 346 int pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW { 347 get( attr )->stackaddr = stackaddr; 348 get( attr )->stacksize = stacksize; 349 return 0; 350 } // pthread_attr_setstack 351 352 int pthread_attr_getstack( const pthread_attr_t *attr, void **stackaddr, size_t *stacksize ) libcfa_public __THROW { 353 *stackaddr = get( attr )->stackaddr; 354 *stacksize = get( attr )->stacksize; 355 return 0; 356 } // pthread_attr_getstack 357 358 // Initialize thread attribute *attr with attributes corresponding to the 359 // already running thread threadID. It shall be called on unitialized attr 360 // and destroyed with pthread_attr_destroy when no longer needed. 361 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 369 return 0; 370 } // pthread_getattr_np 371 372 373 //######################### Threads ######################### 374 375 int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) libcfa_public __THROW { 376 cfaPthread *t = alloc(); 377 (*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_ 382 383 384 int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW { 385 if (_thread == NULL) return EINVAL; // if thread is invalid 386 if (_thread == pthread_self()) return EDEADLK; 387 cfaPthread* p = lookup(_thread); // get user thr pointer 388 try { 389 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 ); 402 if (value_ptr != NULL ) *value_ptr = p->joinval; 403 delete(p); 404 return 0; 405 } //pthread_join_ 406 407 pthread_t pthread_self(void) libcfa_public __THROW { 408 return (pthread_t)((char*)active_thread()-(sizeof(cfaPthread)-sizeof(thread$))); 409 } //pthread_self_ 410 411 void pthread_exit(void * status) libcfa_public __THROW { 412 pthread_t pid = pthread_self(); 413 cfaPthread* _thread = (cfaPthread*)pid; 414 _thread->joinval = status; // set return value 415 _thread->isTerminated = 1; // set terminated flag 416 cancel_stack((pthread_exit_exp){&exp_vt}); 417 } //pthread_exit_ 418 419 int pthread_yield( void ) __THROW { // GNU extension 420 yield(); 421 return 0; 422 } 423 424 425 //######################### Mutex ######################### 426 427 int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t *attr) libcfa_public __THROW { 428 check_nonnull(_mutex); 429 init(_mutex); 430 return 0; 431 } //pthread_mutex_init_ 432 433 434 int pthread_mutex_destroy(pthread_mutex_t *_mutex) libcfa_public __THROW { 435 check_nonnull(_mutex); 436 simple_owner_lock* _lock = get(_mutex); 437 if (_lock->owner != NULL){ 438 return EBUSY; 439 } 440 destroy(_mutex); 441 return 0; 442 } //pthread_mutex_destroy_ 443 444 int pthread_mutex_lock(pthread_mutex_t *_mutex) libcfa_public __THROW { 445 check_nonnull(_mutex); 446 mutex_check(_mutex); 447 simple_owner_lock* _lock = get(_mutex); 448 lock(*_lock); 449 return 0; 450 } //pthread_mutex_lock_ 451 452 int pthread_mutex_unlock(pthread_mutex_t *_mutex) libcfa_public __THROW { 453 check_nonnull(_mutex); 454 simple_owner_lock* _lock = get(_mutex); 455 if (_lock->owner != active_thread()){ 456 return EPERM; 457 } // current thread does not hold the mutex 458 unlock(*_lock); 459 return 0; 460 } //pthread_mutex_unlock_ 461 462 int pthread_mutex_trylock(pthread_mutex_t *_mutex) libcfa_public __THROW { 463 check_nonnull(_mutex); 464 simple_owner_lock* _lock = get(_mutex); 465 if (_lock->owner != active_thread() && _lock->owner != NULL){ 466 return EBUSY; 467 } // if mutex is owned 468 lock(*_lock); 469 return 0; 470 } //pthread_mutex_trylock_ 471 472 //######################### Conditional Variable ######################### 473 474 /* conditional variable routines */ 475 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) libcfa_public __THROW { 476 check_nonnull(cond); 477 init(cond); 478 return 0; 479 } //pthread_cond_init 480 481 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *_mutex) libcfa_public __THROW { 482 check_nonnull(_mutex); 483 check_nonnull(cond); 484 wait(*get(cond), *get(_mutex)); 485 return 0; 486 } // pthread_cond_wait 487 488 int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * _mutex, const struct timespec * abstime) libcfa_public __THROW { 489 check_nonnull(_mutex); 490 check_nonnull(cond); 491 wait(*get(cond), *get(_mutex), *abstime); 492 return 0; 493 } // pthread_cond_timedwait 494 495 int pthread_cond_signal(pthread_cond_t *cond) libcfa_public __THROW { 496 check_nonnull(cond); 497 return notify_one(*get(cond)); 498 } // pthread_cond_signal 499 500 int pthread_cond_broadcast(pthread_cond_t *cond) libcfa_public __THROW { 501 check_nonnull(cond); 502 return notify_all(*get(cond)); 503 } // pthread_cond_broadcast 504 505 int pthread_cond_destroy(pthread_cond_t *cond) libcfa_public __THROW { 506 check_nonnull(cond); 507 destroy(cond); 508 return 0; 509 } // pthread_cond_destroy 510 511 512 513 //######################### Local storage ######################### 514 515 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) libcfa_public __THROW { 516 static_assert(sizeof(pthread_once_t) >= sizeof(int),"sizeof(pthread_once_t) < sizeof(int)"); 517 check_nonnull(once_control); 518 check_nonnull(init_routine); 519 lock(once_lock); 520 if ( *((int *)once_control) == 0 ) { 521 init_routine(); 522 *((int *)once_control) = 1; 523 } // if 524 unlock(once_lock); 525 return 0; 526 } // pthread_once 527 528 int pthread_key_create( pthread_key_t *key, void (*destructor)( void * ) ) libcfa_public __THROW { 529 lock(key_lock); 530 for ( int i = 0; i < PTHREAD_KEYS_MAX; i += 1 ) { 531 if ( ! cfa_pthread_keys[i].in_use ) { 532 cfa_pthread_keys[i].in_use = true; 533 cfa_pthread_keys[i].destructor = destructor; 534 unlock( key_lock ); 535 *key = i; 536 return 0; 537 } // if 538 } // for 539 unlock(key_lock); 540 return EAGAIN; 541 } // pthread_key_create 542 543 int pthread_key_delete( pthread_key_t key ) libcfa_public __THROW { 544 lock(key_lock); 545 if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) { 546 unlock( key_lock ); 547 return EINVAL; 548 } // if 549 cfa_pthread_keys[key].in_use = false; 550 cfa_pthread_keys[key].destructor = NULL; 551 552 // 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; ) { 556 remove(head, p); 557 p.in_use = false; 558 } 559 unlock(key_lock); 560 return 0; 561 } // pthread_key_delete 562 563 int pthread_setspecific( pthread_key_t key, const void *value ) libcfa_public __THROW { 564 // get current thread 565 cfaPthread* t = lookup(pthread_self()); 566 // if current thread's pthreadData is NULL; initialize it 567 Pthread_values* values; 568 if (t->pthreadData == NULL){ 569 values = anew( PTHREAD_KEYS_MAX); 570 t->pthreadData = values; 571 for (int i = 0;i < PTHREAD_KEYS_MAX; i++){ 572 t->pthreadData[i].in_use = false; 573 } // for 574 } else { 575 values = t->pthreadData; 576 } // if 577 // find corresponding key and set value 578 lock(key_lock); 579 // if invalid key 580 if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) { 581 unlock( key_lock ); 582 return EINVAL; 583 } // if 584 Pthread_values &entry = values[key]; 585 if ( ! entry.in_use ) { 586 entry.in_use = true; 587 add(cfa_pthread_keys[key].threads, entry); 588 } // if 589 entry.value = (void *)value; 590 unlock(key_lock); 591 return 0; 592 } //pthread_setspecific 593 594 void* pthread_getspecific(pthread_key_t key) libcfa_public __THROW { 595 if (key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use) return NULL; 596 597 // get current thread 598 cfaPthread* t = lookup(pthread_self()); 599 if (t->pthreadData == NULL) return NULL; 600 lock(key_lock); 601 Pthread_values &entry = ((Pthread_values *)t->pthreadData)[key]; 602 if ( ! entry.in_use ) { 603 unlock( key_lock ); 604 return NULL; 605 } // if 606 void *value = entry.value; 607 unlock(key_lock); 608 609 return value; 610 } //pthread_get_specific 611 612 //######################### Parallelism ######################### 613 void pthread_delete_kernel_threads_() libcfa_public __THROW { // see uMain::~uMain 614 Pthread_kernel_threads& p; 615 for ( StackIter(Pthread_kernel_threads) iter = {cfa_pthreads_kernel_threads}; iter | p; ) { 616 delete(&p); 617 } // for 618 } // pthread_delete_kernel_threads_ 619 620 int pthread_getconcurrency( void ) libcfa_public __THROW { // XOPEN extension 621 return cfa_pthreads_kernel_threads_zero ? 0 : cfa_pthreads_no_kernel_threads; 622 } // pthread_getconcurrency 623 624 int pthread_setconcurrency( int new_level ) libcfa_public __THROW { // XOPEN extension 625 if ( new_level < 0 ) return EINVAL; 626 if ( new_level == 0 ) { 627 cfa_pthreads_kernel_threads_zero = true; // remember set to zero, but ignore 628 return 0; // do not do kernel thread management 629 } // exit 630 cfa_pthreads_kernel_threads_zero = false; 631 lock( concurrency_lock ); 632 for ( ; new_level > cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads += 1 ) { // add processors ? 633 push(cfa_pthreads_kernel_threads, *new() ); 634 } // for 635 for ( ; new_level < cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads -= 1 ) { // remove processors ? 636 delete(&pop(cfa_pthreads_kernel_threads)); 637 } // for 638 unlock( concurrency_lock ); 639 return 0; 640 } // pthread_setconcurrency 641 642 //######################### Signal ######################### 643 644 645 int pthread_sigmask( int /* how */, const sigset_t * /* set */, sigset_t * /* oset */ ) libcfa_public __THROW { 646 return 0; 647 } // pthread_sigmask 648 649 int pthread_kill( pthread_t _thread __attribute__(( unused )), int sig ) libcfa_public __THROW { 650 if ( sig == 0 ) { 651 return 0; 652 } else { 653 abort( "pthread_kill : not implemented" ); 654 } // if 655 return 0; 656 } // pthread_kill 657 658 int pthread_sigqueue(pthread_t , int sig, const union sigval) libcfa_public __THROW { 659 return 0; 660 } // pthread_sigqueue 661 662 //######################### Scheduling ######################### 663 int pthread_detach( pthread_t threadID ) __THROW { 664 abort( "pthread_detach" ); 665 return 0; 666 } // pthread_detach 667 668 int pthread_setschedparam( pthread_t /* thread */, int /* policy */, const struct sched_param * /* param */ ) libcfa_public __THROW { 669 abort( "pthread_setschedparam : not implemented" ); 670 return 0; 671 } // pthread_setschedparam 672 673 int pthread_getschedparam( pthread_t /* thread */, int */* policy */, struct sched_param * /* param */ ) libcfa_public __THROW { 674 abort( "pthread_getschedparam : not implemented" ); 675 return 0; 676 } // pthread_getschedparam 677 678 //######################### Mutex Attr ######################### 679 680 int pthread_mutexattr_init( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW { 681 return 0; 682 } // pthread_mutexattr_init 683 684 int pthread_mutexattr_destroy( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW { 685 return 0; 686 } // pthread_mutexattr_destroy 687 688 int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW { 689 return 0; 690 } // pthread_mutexattr_setpshared 691 692 int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW { 693 return 0; 694 } // pthread_mutexattr_getpshared 695 696 int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW { 697 return 0; 698 } // pthread_mutexattr_setprotocol 699 700 int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW { 701 return 0; 702 } // pthread_mutexattr_getprotocol 703 704 int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW { 705 return 0; 706 } // pthread_mutexattr_setprioceiling 707 708 int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW { 709 return 0; 710 } // pthread_mutexattr_getprioceiling 711 712 int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW { 713 return 0; 714 } // pthread_mutex_setprioceiling 715 716 int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW { 717 return 0; 718 } // pthread_mutex_getprioceiling 719 720 int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW { 721 return 0; 722 } // pthread_mutexattr_gettype 723 724 int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW { 725 return 0; 726 } // pthread_mutexattr_settype 727 728 //######################### Mutex ######################### 729 730 int pthread_mutex_timedlock( pthread_mutex_t *__restrict /* __mutex */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW { 731 abort( "pthread_mutex_timedlock" ); 732 } // pthread_mutex_timedlock 733 734 //######################### Condition ######################### 735 736 int pthread_condattr_getclock( __const pthread_condattr_t * __restrict /* __attr */, __clockid_t *__restrict /* __clock_id */ ) libcfa_public __THROW { 737 abort( "pthread_condattr_getclock" ); 738 } // pthread_condattr_getclock 739 740 int pthread_condattr_setclock( pthread_condattr_t * /* __attr */, __clockid_t /* __clock_id */ ) libcfa_public __THROW { 741 abort( "pthread_condattr_setclock" ); 742 } // pthread_condattr_setclock 743 744 //######################### Spinlock ######################### 745 746 int pthread_spin_init( pthread_spinlock_t * /* __lock */, int /*__pshared */ ) libcfa_public __THROW { 747 abort( "pthread_spin_init" ); 748 } // pthread_spin_init 749 750 int pthread_spin_destroy( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 751 abort( "pthread_spin_destroy" ); 752 } // pthread_spin_destroy 753 754 int pthread_spin_lock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 755 abort( "pthread_spin_lock" ); 756 } // pthread_spin_lock 757 758 int pthread_spin_trylock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 759 abort( "pthread_spin_trylock" ); 760 } // pthread_spin_trylock 761 762 int pthread_spin_unlock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW { 763 abort( "pthread_spin_unlock" ); 764 } // pthread_spin_unlock 765 766 //######################### Barrier ######################### 767 768 int pthread_barrier_init( pthread_barrier_t *__restrict /* __barrier */, __const pthread_barrierattr_t *__restrict /* __attr */, unsigned int /* __count */ ) libcfa_public __THROW { 769 abort( "pthread_barrier_init" ); 770 } // pthread_barrier_init 771 772 int pthread_barrier_destroy( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW { 773 abort( "pthread_barrier_destroy" ); 774 } // pthread_barrier_destroy 775 776 int pthread_barrier_wait( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW { 777 abort( "pthread_barrier_wait" ); 778 } // pthread_barrier_wait 779 780 int pthread_barrierattr_init( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW { 781 abort( "pthread_barrierattr_init" ); 782 } // pthread_barrierattr_init 783 784 int pthread_barrierattr_destroy( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW { 785 abort( "pthread_barrierattr_destroy" ); 786 } // pthread_barrierattr_destroy 787 788 int pthread_barrierattr_getpshared( __const pthread_barrierattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW { 789 abort( "pthread_barrierattr_getpshared" ); 790 } // pthread_barrierattr_getpshared 791 792 int pthread_barrierattr_setpshared( pthread_barrierattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW { 793 abort( "pthread_barrierattr_setpshared" ); 794 } // pthread_barrierattr_setpshared 795 796 //######################### Clock ######################### 797 798 int pthread_getcpuclockid( pthread_t /* __thread_id */, __clockid_t * /* __clock_id */ ) libcfa_public __THROW { 799 abort( "pthread_getcpuclockid" ); 800 } // pthread_getcpuclockid 801 802 // pthread_atfork() 826 803 827 804 // UNIX98 828 805 829 //######################### Read/Write #########################830 831 int pthread_rwlock_init( pthread_rwlock_t *__restrict /* __rwlock */, __const pthread_rwlockattr_t *__restrict /* __attr */ ) libcfa_public __THROW {832 abort( "pthread_rwlock_init" );833 } // pthread_rwlock_init834 835 int pthread_rwlock_destroy( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {836 abort( "pthread_rwlock_destroy" );837 } // pthread_rwlock_destroy838 839 int pthread_rwlock_rdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {840 abort( "pthread_rwlock_rdlock" );841 } // pthread_rwlock_rdlock842 843 int pthread_rwlock_tryrdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {844 abort( "pthread_rwlock_tryrdlock" );845 } // pthread_rwlock_tryrdlock846 847 int pthread_rwlock_wrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {848 abort( "pthread_rwlock_wrlock" );849 } // pthread_rwlock_wrlock850 851 int pthread_rwlock_trywrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {852 abort( "pthread_rwlock_trywrlock" );853 } // pthread_rwlock_trywrlock854 855 int pthread_rwlock_unlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {856 abort( "pthread_rwlock_unlock" );857 } // pthread_rwlock_unlock858 859 int pthread_rwlockattr_init( pthread_rwlockattr_t * /* __attr */ ) libcfa_public __THROW {860 abort( "pthread_rwlockattr_init" );861 } // pthread_rwlockattr_init862 863 int pthread_rwlockattr_destroy( pthread_rwlockattr_t * /*__attr */ ) libcfa_public __THROW {864 abort( "pthread_rwlockattr_destroy" );865 } // pthread_rwlockattr_destroy866 867 int pthread_rwlockattr_getpshared( __const pthread_rwlockattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW {868 abort( "pthread_rwlockattr_getpshared" );869 } // pthread_rwlockattr_getpshared870 871 int pthread_rwlockattr_setpshared( pthread_rwlockattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {872 abort( "pthread_rwlockattr_setpshared" );873 } // pthread_rwlockattr_setpshared874 875 int pthread_rwlockattr_getkind_np( __const pthread_rwlockattr_t * /* __attr */, int * /* __pref */ ) libcfa_public __THROW {876 abort( "pthread_rwlockattr_getkind_np" );877 } // pthread_rwlockattr_getkind_np878 879 int pthread_rwlockattr_setkind_np( pthread_rwlockattr_t * /* __attr */, int /* __pref */ ) libcfa_public __THROW {880 abort( "pthread_rwlockattr_setkind_np" );881 } // pthread_rwlockattr_setkind_np806 //######################### Read/Write ######################### 807 808 int pthread_rwlock_init( pthread_rwlock_t *__restrict /* __rwlock */, __const pthread_rwlockattr_t *__restrict /* __attr */ ) libcfa_public __THROW { 809 abort( "pthread_rwlock_init" ); 810 } // pthread_rwlock_init 811 812 int pthread_rwlock_destroy( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW { 813 abort( "pthread_rwlock_destroy" ); 814 } // pthread_rwlock_destroy 815 816 int pthread_rwlock_rdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW { 817 abort( "pthread_rwlock_rdlock" ); 818 } // pthread_rwlock_rdlock 819 820 int pthread_rwlock_tryrdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW { 821 abort( "pthread_rwlock_tryrdlock" ); 822 } // pthread_rwlock_tryrdlock 823 824 int pthread_rwlock_wrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW { 825 abort( "pthread_rwlock_wrlock" ); 826 } // pthread_rwlock_wrlock 827 828 int pthread_rwlock_trywrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW { 829 abort( "pthread_rwlock_trywrlock" ); 830 } // pthread_rwlock_trywrlock 831 832 int pthread_rwlock_unlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW { 833 abort( "pthread_rwlock_unlock" ); 834 } // pthread_rwlock_unlock 835 836 int pthread_rwlockattr_init( pthread_rwlockattr_t * /* __attr */ ) libcfa_public __THROW { 837 abort( "pthread_rwlockattr_init" ); 838 } // pthread_rwlockattr_init 839 840 int pthread_rwlockattr_destroy( pthread_rwlockattr_t * /*__attr */ ) libcfa_public __THROW { 841 abort( "pthread_rwlockattr_destroy" ); 842 } // pthread_rwlockattr_destroy 843 844 int pthread_rwlockattr_getpshared( __const pthread_rwlockattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW { 845 abort( "pthread_rwlockattr_getpshared" ); 846 } // pthread_rwlockattr_getpshared 847 848 int pthread_rwlockattr_setpshared( pthread_rwlockattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW { 849 abort( "pthread_rwlockattr_setpshared" ); 850 } // pthread_rwlockattr_setpshared 851 852 int pthread_rwlockattr_getkind_np( __const pthread_rwlockattr_t * /* __attr */, int * /* __pref */ ) libcfa_public __THROW { 853 abort( "pthread_rwlockattr_getkind_np" ); 854 } // pthread_rwlockattr_getkind_np 855 856 int pthread_rwlockattr_setkind_np( pthread_rwlockattr_t * /* __attr */, int /* __pref */ ) libcfa_public __THROW { 857 abort( "pthread_rwlockattr_setkind_np" ); 858 } // pthread_rwlockattr_setkind_np 882 859 883 860 // UNIX98 + XOPEN 884 861 885 int pthread_rwlock_timedrdlock( pthread_rwlock_t *__restrict /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {886 abort( "pthread_rwlock_timedrdlock" );887 } // pthread_rwlock_timedrdlock888 889 int pthread_rwlock_timedwrlock( pthread_rwlock_t *__restrict /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {890 abort( "pthread_rwlock_timedwrlock" );891 } // pthread_rwlock_timedwrlock862 int pthread_rwlock_timedrdlock( pthread_rwlock_t *__restrict /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW { 863 abort( "pthread_rwlock_timedrdlock" ); 864 } // pthread_rwlock_timedrdlock 865 866 int pthread_rwlock_timedwrlock( pthread_rwlock_t *__restrict /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW { 867 abort( "pthread_rwlock_timedwrlock" ); 868 } // pthread_rwlock_timedwrlock 892 869 893 870 // GNU 894 871 895 //######################### Parallelism #########################896 897 int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {898 abort( "pthread_setaffinity_np" );899 } // pthread_setaffinity_np900 901 int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {902 abort( "pthread_getaffinity_np" );903 } // pthread_getaffinity_np904 905 int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {906 abort( "pthread_attr_setaffinity_np" );907 } // pthread_attr_setaffinity_np908 909 int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {910 abort( "pthread_attr_getaffinity_np" );911 } // pthread_attr_getaffinity_np912 913 //######################### Cancellation #########################914 915 void _pthread_cleanup_push_defer( struct _pthread_cleanup_buffer * /* __buffer */, void( * /* __routine */ )( void * ), void * /* __arg */ ) libcfa_public __THROW {916 abort( "_pthread_cleanup_push_defer" );917 } // _pthread_cleanup_push_defer918 919 void _pthread_cleanup_pop_restore( struct _pthread_cleanup_buffer * /* __buffer */, int /* __execute */ ) libcfa_public __THROW {920 abort( "_pthread_cleanup_pop_restore" );921 } // _pthread_cleanup_pop_res922 923 int pthread_cancel( pthread_t threadID ) libcfa_public __THROW {924 abort("pthread cancel not implemented");925 return 0;926 } // pthread_cancel927 928 int pthread_setcancelstate( int state, int *oldstate ) libcfa_public __THROW {929 abort("pthread_setcancelstate not implemented");930 return 0;931 } // pthread_setcancelstate932 933 int pthread_setcanceltype( int type, int *oldtype ) libcfa_public __THROW {934 abort("pthread_setcanceltype not implemented");935 return 0;936 } // pthread_setcanceltype872 //######################### Parallelism ######################### 873 874 int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 875 abort( "pthread_setaffinity_np" ); 876 } // pthread_setaffinity_np 877 878 int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 879 abort( "pthread_getaffinity_np" ); 880 } // pthread_getaffinity_np 881 882 int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 883 abort( "pthread_attr_setaffinity_np" ); 884 } // pthread_attr_setaffinity_np 885 886 int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW { 887 abort( "pthread_attr_getaffinity_np" ); 888 } // pthread_attr_getaffinity_np 889 890 //######################### Cancellation ######################### 891 892 void _pthread_cleanup_push_defer( struct _pthread_cleanup_buffer * /* __buffer */, void( * /* __routine */ )( void * ), void * /* __arg */ ) libcfa_public __THROW { 893 abort( "_pthread_cleanup_push_defer" ); 894 } // _pthread_cleanup_push_defer 895 896 void _pthread_cleanup_pop_restore( struct _pthread_cleanup_buffer * /* __buffer */, int /* __execute */ ) libcfa_public __THROW { 897 abort( "_pthread_cleanup_pop_restore" ); 898 } // _pthread_cleanup_pop_res 899 900 int pthread_cancel( pthread_t threadID ) libcfa_public __THROW { 901 abort("pthread cancel not implemented"); 902 return 0; 903 } // pthread_cancel 904 905 int pthread_setcancelstate( int state, int *oldstate ) libcfa_public __THROW { 906 abort("pthread_setcancelstate not implemented"); 907 return 0; 908 } // pthread_setcancelstate 909 910 int pthread_setcanceltype( int type, int *oldtype ) libcfa_public __THROW { 911 abort("pthread_setcanceltype not implemented"); 912 return 0; 913 } // pthread_setcanceltype 937 914 } // extern "C" 938 915 -
libcfa/src/interpose.cfa
r95dab9e r9cd5bd2 111 111 void (* exit)( int ) __attribute__(( __noreturn__ )); 112 112 void (* abort)( void ) __attribute__(( __noreturn__ )); 113 int (*pthread_create)(pthread_t *_thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);114 int (*pthread_join)(pthread_t _thread, void **retval);115 pthread_t (*pthread_self)(void);116 int (*pthread_attr_init)(pthread_attr_t *attr);117 int (*pthread_attr_destroy)(pthread_attr_t *attr);118 int (*pthread_attr_setstack)( pthread_attr_t *attr, void *stackaddr, size_t stacksize );119 int (*pthread_attr_getstacksize)( const pthread_attr_t *attr, size_t *stacksize );120 int (*pthread_sigmask)(int how, const sigset_t *set, sigset_t *oldset);121 int (*pthread_sigqueue)(pthread_t _thread, int sig, const union sigval value);122 113 } __cabi_libc; 123 114 -
libcfa/src/interpose_thread.cfa
r95dab9e r9cd5bd2 17 17 #include <stdio.h> 18 18 #include <string.h> // strlen 19 #include <signal.h> 20 #include <pthread.h> 19 21 extern "C" { 20 22 #include <dlfcn.h> // dlopen, dlsym
Note:
See TracChangeset
for help on using the changeset viewer.