source: libcfa/src/concurrency/pthread.cfa @ 9cd5bd2

ADTast-experimentalpthread-emulation
Last change on this file since 9cd5bd2 was 9cd5bd2, checked in by Thierry Delisle <tdelisle@…>, 19 months ago

Added an assembly to prevent null-checks from being optimized out.
Attempted to reduce the scope of needed headers.
Cleaned tabbing.

  • Property mode set to 100644
File size: 31.1 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
[a7d696f]35struct Pthread_values{
[9cd5bd2]36        inline Seqable;
37        void* value;
38        bool in_use;
[a7d696f]39};
40
41
[20be782]42static Pthread_values *& Back( Pthread_values * n ) {
[9cd5bd2]43        return (Pthread_values *)Back( (Seqable *)n );
[a7d696f]44}
[20be782]45static Pthread_values *& Next( Pthread_values * n ) {
[9cd5bd2]46        return (Pthread_values *)Next( (Colable *)n );
[a7d696f]47}
48
49struct Pthread_keys{
[9cd5bd2]50        bool in_use;
51        void (*destructor)( void * );
52        Sequence(Pthread_values) threads;
[a7d696f]53};  // Pthread keys
54
55static void ?{}(Pthread_keys& k){
[9cd5bd2]56        k.threads{};
[a7d696f]57}
58
59// Create storage separately to ensure no constructors are called.
60static Pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));
61
[20be782]62static void init_pthread_storage(){
[9cd5bd2]63        for (int i = 0; i < PTHREAD_KEYS_MAX; i++){
64                cfa_pthread_keys_storage[i]{};
65        }
[a7d696f]66}
67
68#define cfa_pthread_keys ((Pthread_keys *)cfa_pthread_keys_storage)
69
70/* Controlling the iterations of destructors for thread-specific data.  */
71#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS     4
72/* Number of iterations this implementation does.  */
73#define PTHREAD_DESTRUCTOR_ITERATIONS   _POSIX_THREAD_DESTRUCTOR_ITERATIONS
74
75//######################### Parallelism Helpers #########################
76
77struct Pthread_kernel_threads{
[9cd5bd2]78        inline Colable;
79        processor p;
[a7d696f]80};
81
82Pthread_kernel_threads *& Next( Pthread_kernel_threads * n ) {
[9cd5bd2]83        return (Pthread_kernel_threads *)Next( (Colable *)n );
[a7d696f]84}
85
86static Stack(Pthread_kernel_threads) cfa_pthreads_kernel_threads;
87static bool cfa_pthreads_kernel_threads_zero = false;   // set to zero ?
88static int cfa_pthreads_no_kernel_threads = 1;  // number of kernel threads
89
90
91//######################### Cond Helpers #########################
92
93typedef pthread_cond_var(simple_owner_lock) cfa2pthr_cond_var_t;
94
95/* condvar helper routines */
96static void init(pthread_cond_t* pcond){
[9cd5bd2]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);
[a7d696f]100}
101
102static cfa2pthr_cond_var_t* get(pthread_cond_t* pcond){
[9cd5bd2]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;
[a7d696f]105}
106
107static void destroy(pthread_cond_t* cond){
[9cd5bd2]108        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
109        ^?{}(*get(cond));
[a7d696f]110}
111
112
113//######################### Mutex Helper #########################
114
115/* mutex helper routines */
116static void mutex_check(pthread_mutex_t* t){
117        // Use double check to improve performance. Check is safe on x86; volatile prevents compiler reordering
118        volatile pthread_mutex_t *const mutex_ = t;
119        // SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h
120        int _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
[20be782]121        // if pthread_mutex_t is initialized by PTHREAD_MUTEX_INITIALIZER, _lock_val should be 0
[a7d696f]122        if ( _lock_val == 0 ) {                 // static initialized ?
[9cd5bd2]123                lock(magic_mutex_check);        // race
124                _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
125                if ( _lock_val == 0 ) {         // static initialized ?
[a7d696f]126                pthread_mutex_init( t, NULL );
[9cd5bd2]127                } // if
128                unlock(magic_mutex_check);      // race
[a7d696f]129        } // if
130} // mutex_check
131
132
133static void init(pthread_mutex_t* plock){
[9cd5bd2]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);
[a7d696f]137}
138
139static simple_owner_lock* get(pthread_mutex_t* plock){
[9cd5bd2]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;
[a7d696f]142}
143
144static void destroy(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        ^?{}(*get(plock));
[a7d696f]147}
148
149//######################### Attr helpers #########################
150struct cfaPthread_attr_t {                                                              // thread attributes
151                int contentionscope;
152                int detachstate;
153                size_t stacksize;
154                void *stackaddr;
155                int policy;
156                int inheritsched;
157                struct sched_param param;
158} typedef cfaPthread_attr_t;
159
160static const cfaPthread_attr_t default_attrs{
[9cd5bd2]161        0,
162        0,
163        (size_t)65000,
164        (void *)NULL,
165        0,
166        0,
167        {0}
[a7d696f]168};
169
170
171/*
[20be782]172static const cfaPthread_attr_t default_attrs = {
[9cd5bd2]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}
[a7d696f]180};
181*/
182
183
[20be782]184
[a7d696f]185static cfaPthread_attr_t* get(const pthread_attr_t* attr){
[9cd5bd2]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;
[a7d696f]188}
189
190
191//######################### Threads Helper #########################
192
[20be782]193// exception for cancel_stack in pthread_exit
[a7d696f]194exception pthread_exit_exp {};
[9cd5bd2]195static vtable(pthread_exit_exp) exp_vt;
[a7d696f]196
197thread cfaPthread{
[9cd5bd2]198        cfaPthread_attr_t attr;
199        pthread_t pthreadId;
200        void *joinval;                                                                          // pthreads return value
[a7d696f]201        pthread_attr_t pthread_attr;                                            // pthread attributes
[9cd5bd2]202        void *(*start_routine)(void *);                     // routine start
203        void *arg;                                                              // thread parameter
204        Pthread_values* pthreadData;
205        bool isTerminated;                                  // flag used for tryjoin
[a7d696f]206};
207
208/* thread part routines */
209//  cfaPthread entry point
210void main(cfaPthread& _thread) with(_thread){
[9cd5bd2]211        joinval =  start_routine(arg);
212        isTerminated = true;
[a7d696f]213}
214
215// generate pthread_t by cfaPthread ptr
216static pthread_t create( cfaPthread *p ) {
[9cd5bd2]217        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");
[20be782]218        return (pthread_t)p;
[a7d696f]219}
220
221static cfaPthread *lookup( pthread_t p ){
[9cd5bd2]222        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");
223        return (cfaPthread*)p;
[a7d696f]224}
225
[20be782]226static void pthread_deletespecific_( Pthread_values* values )  { // see uMachContext::invokeTask
[9cd5bd2]227        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
[a7d696f]256}
257
[20be782]258static void ^?{}(cfaPthread & mutex t){
[9cd5bd2]259        // delete pthread local storage
260        Pthread_values* values = t.pthreadData;
261        pthread_deletespecific_(values);
[a7d696f]262}
263
264static void ?{}(cfaPthread &t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) {
[9cd5bd2]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;
[a7d696f]281}   // not used
282
283
284extern "C"{
[9cd5bd2]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 {
[a7d696f]685        return 0;
[9cd5bd2]686        } // pthread_mutexattr_destroy
[a7d696f]687
[9cd5bd2]688        int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW {
[a7d696f]689        return 0;
[9cd5bd2]690        } // pthread_mutexattr_setpshared
[a7d696f]691
[9cd5bd2]692        int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW {
[a7d696f]693        return 0;
[9cd5bd2]694        } // pthread_mutexattr_getpshared
[a7d696f]695
[9cd5bd2]696        int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW {
[a7d696f]697        return 0;
[9cd5bd2]698        } // pthread_mutexattr_setprotocol
[a7d696f]699
[9cd5bd2]700        int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW {
[a7d696f]701        return 0;
[9cd5bd2]702        } // pthread_mutexattr_getprotocol
[a7d696f]703
[9cd5bd2]704        int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW {
[a7d696f]705        return 0;
[9cd5bd2]706        } // pthread_mutexattr_setprioceiling
[a7d696f]707
[9cd5bd2]708        int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW {
[a7d696f]709        return 0;
[9cd5bd2]710        } // pthread_mutexattr_getprioceiling
[a7d696f]711
[9cd5bd2]712        int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW {
[a7d696f]713        return 0;
[9cd5bd2]714        } // pthread_mutex_setprioceiling
[a7d696f]715
[9cd5bd2]716        int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW {
[a7d696f]717        return 0;
[9cd5bd2]718        } // pthread_mutex_getprioceiling
[a7d696f]719
[9cd5bd2]720        int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW {
[a7d696f]721        return 0;
[9cd5bd2]722        } // pthread_mutexattr_gettype
[a7d696f]723
[9cd5bd2]724        int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW {
[a7d696f]725        return 0;
[9cd5bd2]726        } // pthread_mutexattr_settype
[a7d696f]727
[9cd5bd2]728        //######################### Mutex #########################
[a7d696f]729
[9cd5bd2]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
[a7d696f]733
[9cd5bd2]734        //######################### Condition #########################
[a7d696f]735
[9cd5bd2]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
[a7d696f]739
[9cd5bd2]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
[a7d696f]743
[9cd5bd2]744        //######################### Spinlock #########################
[a7d696f]745
[9cd5bd2]746        int pthread_spin_init( pthread_spinlock_t * /* __lock */, int /*__pshared */ ) libcfa_public __THROW {
747                abort( "pthread_spin_init" );
748        } // pthread_spin_init
[a7d696f]749
[9cd5bd2]750        int pthread_spin_destroy( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
751                abort( "pthread_spin_destroy" );
752        } // pthread_spin_destroy
[a7d696f]753
[9cd5bd2]754        int pthread_spin_lock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
755                abort( "pthread_spin_lock" );
756        } // pthread_spin_lock
[a7d696f]757
[9cd5bd2]758        int pthread_spin_trylock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
759                abort( "pthread_spin_trylock" );
760        } // pthread_spin_trylock
[a7d696f]761
[9cd5bd2]762        int pthread_spin_unlock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
763                abort( "pthread_spin_unlock" );
764        } // pthread_spin_unlock
[a7d696f]765
[9cd5bd2]766        //######################### Barrier #########################
[a7d696f]767
[9cd5bd2]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
[a7d696f]771
[9cd5bd2]772        int pthread_barrier_destroy( pthread_barrier_t * /* __barrier */ ) libcfa_public  __THROW {
773                abort( "pthread_barrier_destroy" );
774        } // pthread_barrier_destroy
[a7d696f]775
[9cd5bd2]776        int pthread_barrier_wait( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW {
777                abort( "pthread_barrier_wait" );
778        } // pthread_barrier_wait
[a7d696f]779
[9cd5bd2]780        int pthread_barrierattr_init( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
781                abort( "pthread_barrierattr_init" );
782        } // pthread_barrierattr_init
[a7d696f]783
[9cd5bd2]784        int pthread_barrierattr_destroy( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
785                abort( "pthread_barrierattr_destroy" );
786        } // pthread_barrierattr_destroy
[a7d696f]787
[9cd5bd2]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
[a7d696f]791
[9cd5bd2]792        int pthread_barrierattr_setpshared( pthread_barrierattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
793                abort( "pthread_barrierattr_setpshared" );
794        } // pthread_barrierattr_setpshared
[a7d696f]795
[9cd5bd2]796        //######################### Clock #########################
[a7d696f]797
[9cd5bd2]798        int pthread_getcpuclockid( pthread_t /* __thread_id */, __clockid_t * /* __clock_id */ ) libcfa_public __THROW {
799                abort( "pthread_getcpuclockid" );
800        } // pthread_getcpuclockid
[a7d696f]801
[9cd5bd2]802        // pthread_atfork()
[a7d696f]803
804// UNIX98
805
[9cd5bd2]806        //######################### Read/Write #########################
[a7d696f]807
[9cd5bd2]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
[a7d696f]811
[9cd5bd2]812        int pthread_rwlock_destroy( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
813                abort( "pthread_rwlock_destroy" );
814        } // pthread_rwlock_destroy
[a7d696f]815
[9cd5bd2]816        int pthread_rwlock_rdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
817                abort( "pthread_rwlock_rdlock" );
818        } // pthread_rwlock_rdlock
[a7d696f]819
[9cd5bd2]820        int pthread_rwlock_tryrdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
821                abort( "pthread_rwlock_tryrdlock" );
822        } // pthread_rwlock_tryrdlock
[a7d696f]823
[9cd5bd2]824        int pthread_rwlock_wrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
825                abort( "pthread_rwlock_wrlock" );
826        } // pthread_rwlock_wrlock
[a7d696f]827
[9cd5bd2]828        int pthread_rwlock_trywrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
829                abort( "pthread_rwlock_trywrlock" );
830        } // pthread_rwlock_trywrlock
[a7d696f]831
[9cd5bd2]832        int pthread_rwlock_unlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
833                abort( "pthread_rwlock_unlock" );
834        } // pthread_rwlock_unlock
[a7d696f]835
[9cd5bd2]836        int pthread_rwlockattr_init( pthread_rwlockattr_t * /* __attr */ ) libcfa_public __THROW {
837                abort( "pthread_rwlockattr_init" );
838        } // pthread_rwlockattr_init
[a7d696f]839
[9cd5bd2]840        int pthread_rwlockattr_destroy( pthread_rwlockattr_t * /*__attr */ ) libcfa_public __THROW {
841                abort( "pthread_rwlockattr_destroy" );
842        } // pthread_rwlockattr_destroy
[a7d696f]843
[9cd5bd2]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
[a7d696f]847
[9cd5bd2]848        int pthread_rwlockattr_setpshared( pthread_rwlockattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
849                abort( "pthread_rwlockattr_setpshared" );
850        } // pthread_rwlockattr_setpshared
[a7d696f]851
[9cd5bd2]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
[a7d696f]855
[9cd5bd2]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
[a7d696f]859
860// UNIX98 + XOPEN
861
[9cd5bd2]862        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
[a7d696f]865
[9cd5bd2]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
[a7d696f]869
870// GNU
871
[9cd5bd2]872        //######################### Parallelism #########################
[a7d696f]873
[9cd5bd2]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
[a7d696f]877
[9cd5bd2]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
[a7d696f]881
[9cd5bd2]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
[a7d696f]885
[9cd5bd2]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
[a7d696f]889
[9cd5bd2]890        //######################### Cancellation #########################
[a7d696f]891
[9cd5bd2]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
[a7d696f]895
[9cd5bd2]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
[a7d696f]899
[9cd5bd2]900        int pthread_cancel( pthread_t threadID ) libcfa_public __THROW {
901                abort("pthread cancel not implemented");
902                return 0;
903        } // pthread_cancel
[a7d696f]904
[9cd5bd2]905        int pthread_setcancelstate( int state, int *oldstate ) libcfa_public __THROW {
906                abort("pthread_setcancelstate not implemented");
907                return 0;
908        } // pthread_setcancelstate
[a7d696f]909
[9cd5bd2]910        int pthread_setcanceltype( int type, int *oldtype ) libcfa_public __THROW {
911                abort("pthread_setcanceltype not implemented");
912                return 0;
913        } // pthread_setcanceltype
[20be782]914} // extern "C"
915
[a7d696f]916#pragma GCC diagnostic pop
917
Note: See TracBrowser for help on using the repository browser.