source: libcfa/src/concurrency/pthread.cfa@ ccf1d99

ADT ast-experimental
Last change on this file since ccf1d99 was 8bd886e, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Some clean-up in pthread emulation

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