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

ADTast-experimental
Last change on this file since ed52dd5 was f5f2768, checked in by Peter A. Buhr <pabuhr@…>, 18 months ago

make _GNU_SOURCE default, change IO to use SOCKADDR_ARG and CONST_SOCKADDR_ARG, move sys/socket.h to first include because of anonymous naming problem

  • 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
[9cd5bd2]18#include <signal.h>
[a7d696f]19#include <pthread.h>
[20be782]20#include <errno.h>
21#include "locks.hfa"
22#include "bits/stack.hfa"
[a7d696f]23
24
[9cd5bd2]25#define check_nonnull(x) asm("": "+rm"(x)); if( x == 0p ) return EINVAL;
[a7d696f]26
[20be782]27/* pthread key, pthread once inner routine mutual exclusion */
[a7d696f]28static simple_owner_lock once_lock,key_lock,magic_mutex_check, concurrency_lock;
[20be782]29
[a7d696f]30//######################### Local Storage Helpers #########################
31
[9cd5bd2]32enum { PTHREAD_KEYS_MAX = 1024 };
33
[8bd886e]34struct pthread_values{
[9cd5bd2]35        inline Seqable;
[f5f2768]36        void * value;
[9cd5bd2]37        bool in_use;
[a7d696f]38};
39
[8bd886e]40static inline {
41        pthread_values *& Back( pthread_values * n ) {
42                return (pthread_values *)Back( (Seqable *)n );
43        }
[a7d696f]44
[8bd886e]45        pthread_values *& Next( pthread_values * n ) {
46                return (pthread_values *)Next( (Colable *)n );
47        }
[a7d696f]48}
49
[8bd886e]50struct pthread_keys {
[9cd5bd2]51        bool in_use;
52        void (*destructor)( void * );
[8bd886e]53        Sequence(pthread_values) threads;
54};
[a7d696f]55
[f5f2768]56static void ?{}(pthread_keys& k) {
[9cd5bd2]57        k.threads{};
[a7d696f]58}
59
60// Create storage separately to ensure no constructors are called.
[8bd886e]61static pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));
[a7d696f]62
[f5f2768]63static void init_pthread_storage() {
64        for ( int i = 0; i < PTHREAD_KEYS_MAX; i++) {
[9cd5bd2]65                cfa_pthread_keys_storage[i]{};
66        }
[a7d696f]67}
68
[8bd886e]69#define cfa_pthread_keys ((pthread_keys *)cfa_pthread_keys_storage)
[a7d696f]70
71/* Controlling the iterations of destructors for thread-specific data.  */
72#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS     4
73/* Number of iterations this implementation does.  */
74#define PTHREAD_DESTRUCTOR_ITERATIONS   _POSIX_THREAD_DESTRUCTOR_ITERATIONS
75
76//######################### Parallelism Helpers #########################
77
78struct Pthread_kernel_threads{
[9cd5bd2]79        inline Colable;
80        processor p;
[a7d696f]81};
82
83Pthread_kernel_threads *& Next( Pthread_kernel_threads * n ) {
[9cd5bd2]84        return (Pthread_kernel_threads *)Next( (Colable *)n );
[a7d696f]85}
86
87static Stack(Pthread_kernel_threads) cfa_pthreads_kernel_threads;
88static bool cfa_pthreads_kernel_threads_zero = false;   // set to zero ?
89static int cfa_pthreads_no_kernel_threads = 1;  // number of kernel threads
90
91
92//######################### Cond Helpers #########################
93
94typedef pthread_cond_var(simple_owner_lock) cfa2pthr_cond_var_t;
95
96/* condvar helper routines */
[f5f2768]97static void init(pthread_cond_t * pcond) {
[9cd5bd2]98        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
[f5f2768]99        cfa2pthr_cond_var_t * _cond = (cfa2pthr_cond_var_t*)pcond;
[9cd5bd2]100        ?{}(*_cond);
[a7d696f]101}
102
[f5f2768]103static cfa2pthr_cond_var_t * get(pthread_cond_t * pcond) {
[9cd5bd2]104        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
105        return (cfa2pthr_cond_var_t*)pcond;
[a7d696f]106}
107
[f5f2768]108static void destroy(pthread_cond_t* cond) {
[9cd5bd2]109        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
110        ^?{}(*get(cond));
[a7d696f]111}
112
113
114//######################### Mutex Helper #########################
115
116/* mutex helper routines */
[f5f2768]117static void mutex_check(pthread_mutex_t* t) {
[8bd886e]118        // Use double check to improve performance.
119        // Check is safe on x86; volatile prevents compiler reordering
[a7d696f]120        volatile pthread_mutex_t *const mutex_ = t;
[8bd886e]121
[a7d696f]122        // SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h
123        int _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
[8bd886e]124
[20be782]125        // if pthread_mutex_t is initialized by PTHREAD_MUTEX_INITIALIZER, _lock_val should be 0
[8bd886e]126        if ( _lock_val == 0 ) {
127                lock(magic_mutex_check);
[9cd5bd2]128                _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
[8bd886e]129                if ( _lock_val == 0 ) {
130                        pthread_mutex_init( t, NULL );
131                }
132                unlock(magic_mutex_check);
133        }
[a7d696f]134} // mutex_check
135
136
[f5f2768]137static void init(pthread_mutex_t* plock) {
[9cd5bd2]138        static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
139        simple_owner_lock* _lock = (simple_owner_lock*)plock;
140        ?{}(*_lock);
[a7d696f]141}
142
[f5f2768]143static simple_owner_lock* get(pthread_mutex_t* plock) {
[9cd5bd2]144        static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
145        return (simple_owner_lock*)plock;
[a7d696f]146}
147
[f5f2768]148static void destroy(pthread_mutex_t* plock) {
[9cd5bd2]149        static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
150        ^?{}(*get(plock));
[a7d696f]151}
152
153//######################### Attr helpers #########################
154struct cfaPthread_attr_t {                                                              // thread attributes
155                int contentionscope;
156                int detachstate;
157                size_t stacksize;
158                void *stackaddr;
159                int policy;
160                int inheritsched;
161                struct sched_param param;
162} typedef cfaPthread_attr_t;
163
164static const cfaPthread_attr_t default_attrs{
[9cd5bd2]165        0,
166        0,
167        (size_t)65000,
168        (void *)NULL,
169        0,
170        0,
171        {0}
[a7d696f]172};
173
[f5f2768]174static cfaPthread_attr_t* get(const pthread_attr_t* attr) {
[9cd5bd2]175        static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t),"sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)");
176        return (cfaPthread_attr_t*)attr;
[a7d696f]177}
178
179
180//######################### Threads Helper #########################
181
[20be782]182// exception for cancel_stack in pthread_exit
[a7d696f]183exception pthread_exit_exp {};
[9cd5bd2]184static vtable(pthread_exit_exp) exp_vt;
[a7d696f]185
186thread cfaPthread{
[9cd5bd2]187        cfaPthread_attr_t attr;
188        pthread_t pthreadId;
[8bd886e]189
190        // pthreads return value
191        void *joinval;
192
193        // pthread attributes
194        pthread_attr_t pthread_attr;
195
196        void *(*start_routine)(void *);
197        void *start_arg;
198
199        // thread local data
200        pthread_values* pthreadData;
201
202        // flag used for tryjoin
203        bool isTerminated;
[a7d696f]204};
205
206/* thread part routines */
207//  cfaPthread entry point
[f5f2768]208void main( cfaPthread & _thread ) with( _thread ) {
209        joinval = start_routine( start_arg );
[9cd5bd2]210        isTerminated = true;
[a7d696f]211}
212
[f5f2768]213static cfaPthread * lookup( pthread_t p ) {
[9cd5bd2]214        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");
215        return (cfaPthread*)p;
[a7d696f]216}
217
[8bd886e]218static void pthread_deletespecific_( pthread_values* values )  { // see uMachContext::invokeTask
219        pthread_values* value;
220        pthread_keys* key;
[9cd5bd2]221        bool destcalled = true;
[f5f2768]222        if (values != NULL) {
[9cd5bd2]223                for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) {
224                        destcalled = false;
225                        lock(key_lock);
[f5f2768]226                        for ( int i = 0; i < PTHREAD_KEYS_MAX; i++) {
[9cd5bd2]227                                // for each valid key
[f5f2768]228                                if ( values[i].in_use) {
[9cd5bd2]229                                        value = &values[i];
230                                        key = &cfa_pthread_keys[i];
231                                        value->in_use = false;
232                                        remove(key->threads, *value);
233                                        // if  a  key  value  has  a  non-NULL  destructor pointer,  and  the  thread  has  a  non-NULL  value associated with that key,
234                                        // 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.
[f5f2768]235                                        if (value->value != NULL && key->destructor != NULL) {
[9cd5bd2]236                                                unlock(key_lock);
237                                                key->destructor(value->value); // run destructor
238                                                lock(key_lock);
239                                                destcalled = true;
240                                        }   // if
241                                        value->value = NULL;
242                                }   // if
243                        }   // for
244                        unlock(key_lock);
245                }   // for
246                free(values);
247        }   // if
[a7d696f]248}
249
[f5f2768]250static void ^?{}(cfaPthread & mutex t) {
[9cd5bd2]251        // delete pthread local storage
[8bd886e]252        pthread_values * values = t.pthreadData;
[9cd5bd2]253        pthread_deletespecific_(values);
[a7d696f]254}
255
256static void ?{}(cfaPthread &t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) {
[8bd886e]257        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread*)");
[9cd5bd2]258
259        // set up user thread stackSize
260        cfaPthread_attr_t * attr = get(_attr);
[f5f2768]261        ((thread&)t) { attr ? attr->stacksize: DEFAULT_STACK_SIZE };
[9cd5bd2]262
263        // initialize _thread & cfaPthread id
[8bd886e]264        *_thread = t.pthreadId = (pthread_t)(&t);
[9cd5bd2]265
266        // if attr null, self attr will be set as default_attrs; else set to attr
267        t.attr = (attr != NULL ? *attr : default_attrs);
268
269        // init start routine and arguments
270        t.start_routine = start_routine;
[8bd886e]271        t.start_arg = arg;
[9cd5bd2]272        t.pthreadData = NULL;
[8bd886e]273}
[a7d696f]274
275
276extern "C"{
[9cd5bd2]277        //######################### Pthread Attrs #########################
278
279        int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW {
280                cfaPthread_attr_t* _attr = get(attr);
[8bd886e]281                ?{}(*_attr, default_attrs);
[9cd5bd2]282                return 0;
283        }
284        int pthread_attr_destroy(pthread_attr_t *attr) libcfa_public __THROW {
285                ^?{}(*get(attr));
286                return 0;
287        }
288
289        int pthread_attr_setscope( pthread_attr_t *attr, int contentionscope ) libcfa_public __THROW {
290                get( attr )->contentionscope = contentionscope;
291                return 0;
292        } // pthread_attr_setscope
293
294        int pthread_attr_getscope( const pthread_attr_t *attr, int *contentionscope ) libcfa_public __THROW {
295                *contentionscope = get( attr )->contentionscope;
296                return 0;
297        } // pthread_attr_getscope
298
299        int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate ) libcfa_public __THROW {
300                get( attr )->detachstate = detachstate;
301                return 0;
302        } // pthread_attr_setdetachstate
303
304        int pthread_attr_getdetachstate( const pthread_attr_t *attr, int *detachstate ) libcfa_public __THROW {
305                *detachstate = get( attr )->detachstate;
306                return 0;
307        } // pthread_attr_getdetachstate
308
309        int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize ) libcfa_public __THROW {
310                get( attr )->stacksize = stacksize;
311                return 0;
312        } // pthread_attr_setstacksize
313
314        int pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize ) libcfa_public __THROW {
315                *stacksize = get( attr )->stacksize;
316                return 0;
317        } // pthread_attr_getstacksize
318
319        int pthread_attr_getguardsize( const pthread_attr_t * /* attr */, size_t * /* guardsize */ ) libcfa_public __THROW {
320                return 0;
321        } // pthread_attr_getguardsize
322
323        int pthread_attr_setguardsize( pthread_attr_t * /* attr */, size_t /* guardsize */ ) libcfa_public __THROW {
324                return 0;
325        } // pthread_attr_setguardsize
326
327        int pthread_attr_setstackaddr( pthread_attr_t *attr, void *stackaddr ) libcfa_public __THROW {
328                get( attr )->stackaddr = stackaddr;
329                return 0;
330        } // pthread_attr_setstackaddr
331
332        int pthread_attr_getstackaddr( const pthread_attr_t *attr, void **stackaddr ) libcfa_public __THROW {
333                *stackaddr = get( attr )->stackaddr;
334                return 0;
335        } // pthread_attr_getstackaddr
336
337        int pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW {
338                get( attr )->stackaddr = stackaddr;
339                get( attr )->stacksize = stacksize;
340                return 0;
341        } // pthread_attr_setstack
342
343        int pthread_attr_getstack( const pthread_attr_t *attr, void **stackaddr, size_t *stacksize ) libcfa_public __THROW {
344                *stackaddr = get( attr )->stackaddr;
345                *stacksize = get( attr )->stacksize;
346                return 0;
347        } // pthread_attr_getstack
348
349        // Initialize thread attribute *attr with attributes corresponding to the
350        // already running thread threadID. It shall be called on unitialized attr
351        // and destroyed with pthread_attr_destroy when no longer needed.
352        int pthread_getattr_np( pthread_t threadID, pthread_attr_t *attr ) libcfa_public __THROW { // GNU extension
[8bd886e]353                check_nonnull(attr);
354
355                // copy all fields
356                *get(attr) = lookup( threadID )->attr;
357
[9cd5bd2]358                return 0;
359        } // pthread_getattr_np
360
361
362        //######################### Threads #########################
363
364        int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) libcfa_public __THROW {
365                cfaPthread *t = alloc();
[f5f2768]366                (*t) {_thread, attr, start_routine, arg};
[9cd5bd2]367                return 0;
[8bd886e]368        }
[9cd5bd2]369
370
371        int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
[8bd886e]372                // if thread is invalid
373                if (_thread == NULL) return EINVAL;
[9cd5bd2]374                if (_thread == pthread_self()) return EDEADLK;
[8bd886e]375
376                // get user thr pointer
377                cfaPthread* p = lookup(_thread);
[9cd5bd2]378                try {
379                        join(*p);
[8bd886e]380                }
381                // if thread called pthread_exit
382                catchResume (ThreadCancelled(cfaPthread) * cancel) {}
383
384                // fetch result
385                if (value_ptr != NULL ) *value_ptr = p->joinval;
[9cd5bd2]386                delete(p);
387                return 0;
[8bd886e]388        }
[9cd5bd2]389
390        int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
[8bd886e]391                // if thread is invalid
392                if (_thread == NULL) return EINVAL;
[9cd5bd2]393                if (_thread == pthread_self()) return EDEADLK;
[8bd886e]394
[9cd5bd2]395                cfaPthread* p = lookup(_thread);
[8bd886e]396
397                // thread not finished ?
398                if (!p->isTerminated) return EBUSY;
399
[9cd5bd2]400                join( *p );
[8bd886e]401
[9cd5bd2]402                if (value_ptr != NULL ) *value_ptr = p->joinval;
403                delete(p);
404                return 0;
[8bd886e]405        }
[9cd5bd2]406
407        pthread_t pthread_self(void) libcfa_public __THROW {
[8bd886e]408                return (pthread_t)((uintptr_t)active_thread() - (sizeof(cfaPthread) - sizeof(thread$)));
409        }
[9cd5bd2]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
[f5f2768]416                cancel_stack((pthread_exit_exp) {&exp_vt});
[9cd5bd2]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);
[f5f2768]437                if (_lock->owner != NULL) {
[9cd5bd2]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);
[f5f2768]455                if (_lock->owner != active_thread()) {
[9cd5bd2]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);
[f5f2768]465                if (_lock->owner != active_thread() && _lock->owner != NULL) {
[9cd5bd2]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.
[8bd886e]553                pthread_values& p;
554                Sequence(pthread_values)& head = cfa_pthread_keys[key].threads;
555                for ( SeqIter(pthread_values) iter = { head }; iter | p; ) {
[9cd5bd2]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
[8bd886e]567                pthread_values* values;
[f5f2768]568                if (t->pthreadData == NULL) {
[9cd5bd2]569                        values = anew( PTHREAD_KEYS_MAX);
570                        t->pthreadData = values;
[f5f2768]571                        for ( int i = 0;i < PTHREAD_KEYS_MAX; i++) {
[9cd5bd2]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
[8bd886e]584                pthread_values &entry = values[key];
[9cd5bd2]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);
[8bd886e]601                pthread_values &entry = ((pthread_values *)t->pthreadData)[key];
[9cd5bd2]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 #########################
[8bd886e]613        void pthread_delete_kernel_threads_() __THROW { // see uMain::~uMain
[9cd5bd2]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
[8bd886e]620        int pthread_getconcurrency( void ) __THROW {    // XOPEN extension
[9cd5bd2]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
[8bd886e]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;
[9cd5bd2]640        } // pthread_setconcurrency
641
642        //######################### Signal #########################
643
644
645         int pthread_sigmask( int /* how */, const sigset_t * /* set */, sigset_t * /* oset */ ) libcfa_public __THROW {
[8bd886e]646                abort( "pthread_sigmask : not implemented" );
647                return 0;
[9cd5bd2]648         } // pthread_sigmask
649
650        int pthread_kill( pthread_t _thread __attribute__(( unused )), int sig ) libcfa_public __THROW {
651                if ( sig == 0 ) {
652                        return 0;
653                } else {
654                        abort( "pthread_kill : not implemented" );
655                } // if
656                return 0;
657        } // pthread_kill
658
659        int pthread_sigqueue(pthread_t , int sig, const union sigval) libcfa_public __THROW {
[8bd886e]660                abort( "pthread_sigqueue : not implemented" );
[9cd5bd2]661                return 0;
662        } // pthread_sigqueue
663
664        //######################### Scheduling #########################
665        int pthread_detach( pthread_t threadID ) __THROW {
[8bd886e]666                abort( "pthread_detach : not implemented" );
[9cd5bd2]667                return 0;
668        } // pthread_detach
669
670        int pthread_setschedparam( pthread_t /* thread */, int /* policy */, const struct sched_param * /* param */ ) libcfa_public __THROW {
671                abort( "pthread_setschedparam : not implemented" );
672                return 0;
673        } // pthread_setschedparam
674
675        int pthread_getschedparam( pthread_t /* thread */, int */* policy */, struct sched_param * /* param */ ) libcfa_public __THROW {
676                abort( "pthread_getschedparam : not implemented" );
677                return 0;
678        } // pthread_getschedparam
679
680         //######################### Mutex Attr #########################
681
682        int pthread_mutexattr_init( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW {
683                return 0;
684        } // pthread_mutexattr_init
685
686        int pthread_mutexattr_destroy( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW {
[8bd886e]687                return 0;
[9cd5bd2]688        } // pthread_mutexattr_destroy
[a7d696f]689
[9cd5bd2]690        int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW {
[8bd886e]691                return 0;
[9cd5bd2]692        } // pthread_mutexattr_setpshared
[a7d696f]693
[9cd5bd2]694        int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW {
[8bd886e]695                return 0;
[9cd5bd2]696        } // pthread_mutexattr_getpshared
[a7d696f]697
[9cd5bd2]698        int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW {
[8bd886e]699                return 0;
[9cd5bd2]700        } // pthread_mutexattr_setprotocol
[a7d696f]701
[9cd5bd2]702        int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW {
[8bd886e]703                return 0;
[9cd5bd2]704        } // pthread_mutexattr_getprotocol
[a7d696f]705
[9cd5bd2]706        int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW {
[8bd886e]707                return 0;
[9cd5bd2]708        } // pthread_mutexattr_setprioceiling
[a7d696f]709
[9cd5bd2]710        int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW {
[8bd886e]711                return 0;
[9cd5bd2]712        } // pthread_mutexattr_getprioceiling
[a7d696f]713
[9cd5bd2]714        int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW {
[8bd886e]715                return 0;
[9cd5bd2]716        } // pthread_mutex_setprioceiling
[a7d696f]717
[9cd5bd2]718        int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW {
[8bd886e]719                return 0;
[9cd5bd2]720        } // pthread_mutex_getprioceiling
[a7d696f]721
[9cd5bd2]722        int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW {
[8bd886e]723                return 0;
[9cd5bd2]724        } // pthread_mutexattr_gettype
[a7d696f]725
[9cd5bd2]726        int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW {
[8bd886e]727                return 0;
[9cd5bd2]728        } // pthread_mutexattr_settype
[a7d696f]729
[9cd5bd2]730        //######################### Mutex #########################
[a7d696f]731
[9cd5bd2]732        int pthread_mutex_timedlock( pthread_mutex_t *__restrict /* __mutex */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
733                abort( "pthread_mutex_timedlock" );
734        } // pthread_mutex_timedlock
[a7d696f]735
[9cd5bd2]736        //######################### Condition #########################
[a7d696f]737
[9cd5bd2]738        int pthread_condattr_getclock( __const pthread_condattr_t * __restrict /* __attr */, __clockid_t *__restrict /* __clock_id */ ) libcfa_public __THROW {
739                abort( "pthread_condattr_getclock" );
740        } // pthread_condattr_getclock
[a7d696f]741
[9cd5bd2]742        int pthread_condattr_setclock( pthread_condattr_t * /* __attr */, __clockid_t /* __clock_id */ ) libcfa_public __THROW {
743                abort( "pthread_condattr_setclock" );
744        } // pthread_condattr_setclock
[a7d696f]745
[9cd5bd2]746        //######################### Spinlock #########################
[a7d696f]747
[9cd5bd2]748        int pthread_spin_init( pthread_spinlock_t * /* __lock */, int /*__pshared */ ) libcfa_public __THROW {
749                abort( "pthread_spin_init" );
750        } // pthread_spin_init
[a7d696f]751
[9cd5bd2]752        int pthread_spin_destroy( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
753                abort( "pthread_spin_destroy" );
754        } // pthread_spin_destroy
[a7d696f]755
[9cd5bd2]756        int pthread_spin_lock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
757                abort( "pthread_spin_lock" );
758        } // pthread_spin_lock
[a7d696f]759
[9cd5bd2]760        int pthread_spin_trylock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
761                abort( "pthread_spin_trylock" );
762        } // pthread_spin_trylock
[a7d696f]763
[9cd5bd2]764        int pthread_spin_unlock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
765                abort( "pthread_spin_unlock" );
766        } // pthread_spin_unlock
[a7d696f]767
[9cd5bd2]768        //######################### Barrier #########################
[a7d696f]769
[9cd5bd2]770        int pthread_barrier_init( pthread_barrier_t *__restrict /* __barrier */, __const pthread_barrierattr_t *__restrict /* __attr */, unsigned int /* __count */ ) libcfa_public __THROW {
771                abort( "pthread_barrier_init" );
772        } // pthread_barrier_init
[a7d696f]773
[9cd5bd2]774        int pthread_barrier_destroy( pthread_barrier_t * /* __barrier */ ) libcfa_public  __THROW {
775                abort( "pthread_barrier_destroy" );
776        } // pthread_barrier_destroy
[a7d696f]777
[9cd5bd2]778        int pthread_barrier_wait( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW {
779                abort( "pthread_barrier_wait" );
780        } // pthread_barrier_wait
[a7d696f]781
[9cd5bd2]782        int pthread_barrierattr_init( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
783                abort( "pthread_barrierattr_init" );
784        } // pthread_barrierattr_init
[a7d696f]785
[9cd5bd2]786        int pthread_barrierattr_destroy( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
787                abort( "pthread_barrierattr_destroy" );
788        } // pthread_barrierattr_destroy
[a7d696f]789
[9cd5bd2]790        int pthread_barrierattr_getpshared( __const pthread_barrierattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW {
791                abort( "pthread_barrierattr_getpshared" );
792        } // pthread_barrierattr_getpshared
[a7d696f]793
[9cd5bd2]794        int pthread_barrierattr_setpshared( pthread_barrierattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
795                abort( "pthread_barrierattr_setpshared" );
796        } // pthread_barrierattr_setpshared
[a7d696f]797
[9cd5bd2]798        //######################### Clock #########################
[a7d696f]799
[9cd5bd2]800        int pthread_getcpuclockid( pthread_t /* __thread_id */, __clockid_t * /* __clock_id */ ) libcfa_public __THROW {
801                abort( "pthread_getcpuclockid" );
802        } // pthread_getcpuclockid
[a7d696f]803
[9cd5bd2]804        // pthread_atfork()
[a7d696f]805
806// UNIX98
807
[9cd5bd2]808        //######################### Read/Write #########################
[a7d696f]809
[9cd5bd2]810        int pthread_rwlock_init( pthread_rwlock_t *__restrict /* __rwlock */, __const pthread_rwlockattr_t *__restrict /* __attr */ ) libcfa_public __THROW {
811                abort( "pthread_rwlock_init" );
812        } // pthread_rwlock_init
[a7d696f]813
[9cd5bd2]814        int pthread_rwlock_destroy( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
815                abort( "pthread_rwlock_destroy" );
816        } // pthread_rwlock_destroy
[a7d696f]817
[9cd5bd2]818        int pthread_rwlock_rdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
819                abort( "pthread_rwlock_rdlock" );
820        } // pthread_rwlock_rdlock
[a7d696f]821
[9cd5bd2]822        int pthread_rwlock_tryrdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
823                abort( "pthread_rwlock_tryrdlock" );
824        } // pthread_rwlock_tryrdlock
[a7d696f]825
[9cd5bd2]826        int pthread_rwlock_wrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
827                abort( "pthread_rwlock_wrlock" );
828        } // pthread_rwlock_wrlock
[a7d696f]829
[9cd5bd2]830        int pthread_rwlock_trywrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
831                abort( "pthread_rwlock_trywrlock" );
832        } // pthread_rwlock_trywrlock
[a7d696f]833
[9cd5bd2]834        int pthread_rwlock_unlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
835                abort( "pthread_rwlock_unlock" );
836        } // pthread_rwlock_unlock
[a7d696f]837
[9cd5bd2]838        int pthread_rwlockattr_init( pthread_rwlockattr_t * /* __attr */ ) libcfa_public __THROW {
839                abort( "pthread_rwlockattr_init" );
840        } // pthread_rwlockattr_init
[a7d696f]841
[9cd5bd2]842        int pthread_rwlockattr_destroy( pthread_rwlockattr_t * /*__attr */ ) libcfa_public __THROW {
843                abort( "pthread_rwlockattr_destroy" );
844        } // pthread_rwlockattr_destroy
[a7d696f]845
[9cd5bd2]846        int pthread_rwlockattr_getpshared( __const pthread_rwlockattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW {
847                abort( "pthread_rwlockattr_getpshared" );
848        } // pthread_rwlockattr_getpshared
[a7d696f]849
[9cd5bd2]850        int pthread_rwlockattr_setpshared( pthread_rwlockattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
851                abort( "pthread_rwlockattr_setpshared" );
852        } // pthread_rwlockattr_setpshared
[a7d696f]853
[9cd5bd2]854        int pthread_rwlockattr_getkind_np( __const pthread_rwlockattr_t * /* __attr */, int * /* __pref */ ) libcfa_public __THROW {
855                abort( "pthread_rwlockattr_getkind_np" );
856        } // pthread_rwlockattr_getkind_np
[a7d696f]857
[9cd5bd2]858        int pthread_rwlockattr_setkind_np( pthread_rwlockattr_t * /* __attr */, int /* __pref */ ) libcfa_public __THROW {
859                abort( "pthread_rwlockattr_setkind_np" );
860        } // pthread_rwlockattr_setkind_np
[a7d696f]861
862// UNIX98 + XOPEN
863
[9cd5bd2]864        int pthread_rwlock_timedrdlock( pthread_rwlock_t *__restrict  /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
865                abort( "pthread_rwlock_timedrdlock" );
866        } // pthread_rwlock_timedrdlock
[a7d696f]867
[9cd5bd2]868        int pthread_rwlock_timedwrlock( pthread_rwlock_t *__restrict  /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
869                abort( "pthread_rwlock_timedwrlock" );
870        } // pthread_rwlock_timedwrlock
[a7d696f]871
872// GNU
873
[9cd5bd2]874        //######################### Parallelism #########################
[a7d696f]875
[f5f2768]876        // int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
877        //      abort( "pthread_setaffinity_np" );
878        // } // pthread_setaffinity_np
[a7d696f]879
[f5f2768]880        // int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
881        //      abort( "pthread_getaffinity_np" );
882        // } // pthread_getaffinity_np
[a7d696f]883
[f5f2768]884        // int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
885        //      abort( "pthread_attr_setaffinity_np" );
886        // } // pthread_attr_setaffinity_np
[a7d696f]887
[f5f2768]888        // int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
889        //      abort( "pthread_attr_getaffinity_np" );
890        // } // pthread_attr_getaffinity_np
[a7d696f]891
[9cd5bd2]892        //######################### Cancellation #########################
[a7d696f]893
[9cd5bd2]894        void _pthread_cleanup_push_defer( struct _pthread_cleanup_buffer * /* __buffer */, void( * /* __routine */ )( void * ), void * /* __arg */ ) libcfa_public __THROW {
895                abort( "_pthread_cleanup_push_defer" );
896        } // _pthread_cleanup_push_defer
[a7d696f]897
[9cd5bd2]898        void _pthread_cleanup_pop_restore( struct _pthread_cleanup_buffer * /* __buffer */, int /* __execute */ ) libcfa_public __THROW {
899                abort( "_pthread_cleanup_pop_restore" );
900        } // _pthread_cleanup_pop_res
[a7d696f]901
[9cd5bd2]902        int pthread_cancel( pthread_t threadID ) libcfa_public __THROW {
903                abort("pthread cancel not implemented");
904                return 0;
905        } // pthread_cancel
[a7d696f]906
[9cd5bd2]907        int pthread_setcancelstate( int state, int *oldstate ) libcfa_public __THROW {
908                abort("pthread_setcancelstate not implemented");
909                return 0;
910        } // pthread_setcancelstate
[a7d696f]911
[9cd5bd2]912        int pthread_setcanceltype( int type, int *oldtype ) libcfa_public __THROW {
913                abort("pthread_setcanceltype not implemented");
914                return 0;
915        } // pthread_setcanceltype
[20be782]916} // extern "C"
917
[a7d696f]918#pragma GCC diagnostic pop
919
Note: See TracBrowser for help on using the repository browser.