source: libcfa/src/concurrency/pthread.cfa @ 7eac70e

ADTast-experimental
Last change on this file since 7eac70e was 8bd886e, checked in by Thierry Delisle <tdelisle@…>, 2 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.