source: libcfa/src/concurrency/pthread.cfa @ 20be782

pthread-emulation
Last change on this file since 20be782 was 20be782, checked in by z277zhu <z277zhu@…>, 4 months ago

add pthread

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