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

Last change on this file since e7a8f65 was ff443e5, checked in by Peter A. Buhr <pabuhr@…>, 21 months ago

forgot to add to last commit

  • Property mode set to 100644
File size: 30.6 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
18#include <signal.h>
19#include <pthread.h>
20#include <errno.h>
21#include "locks.hfa"
22#include "bits/stack.hfa"
23
24
25#define check_nonnull(x) asm("": "+rm"(x)); if( x == 0p ) return EINVAL;
26
27/* pthread key, pthread once inner routine mutual exclusion */
28static simple_owner_lock once_lock,key_lock,magic_mutex_check, concurrency_lock;
29
30//######################### Local Storage Helpers #########################
31
32enum { PTHREAD_KEYS_MAX = 1024 };
33
34struct pthread_values{
35        inline Seqable;
36        void * value;
37        bool in_use;
38};
39
40static inline {
41        pthread_values *& Back( pthread_values * n ) {
42                return (pthread_values *)Back( (Seqable *)n );
43        }
44
45        pthread_values *& Next( pthread_values * n ) {
46                return (pthread_values *)Next( (Colable *)n );
47        }
48}
49
50struct pthread_keys {
51        bool in_use;
52        void (* destructor)( void * );
53        Sequence(pthread_values) threads;
54};
55
56static void ?{}(pthread_keys& k) {
57        k.threads{};
58}
59
60// Create storage separately to ensure no constructors are called.
61static pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));
62
63static void init_pthread_storage() {
64        for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) {
65                cfa_pthread_keys_storage[i]{};
66        }
67}
68
69#define cfa_pthread_keys ((pthread_keys *)cfa_pthread_keys_storage)
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{
79        inline Colable;
80        processor p;
81};
82
83Pthread_kernel_threads *& Next( Pthread_kernel_threads * n ) {
84        return (Pthread_kernel_threads *)Next( (Colable *)n );
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 */
97static void init(pthread_cond_t * pcond) {
98        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
99        cfa2pthr_cond_var_t * _cond = (cfa2pthr_cond_var_t *)pcond;
100        ?{}(*_cond);
101}
102
103static cfa2pthr_cond_var_t * get(pthread_cond_t * pcond) {
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;
106}
107
108static void destroy(pthread_cond_t * cond) {
109        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
110        ^?{}(*get(cond));
111}
112
113
114//######################### Mutex Helper #########################
115
116/* mutex helper routines */
117static void mutex_check(pthread_mutex_t * t) {
118        // Use double check to improve performance.
119        // Check is safe on x86; volatile prevents compiler reordering
120        volatile pthread_mutex_t * const mutex_ = t;
121
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;
124
125        // if pthread_mutex_t is initialized by PTHREAD_MUTEX_INITIALIZER, _lock_val should be 0
126        if ( _lock_val == 0 ) {
127                lock(magic_mutex_check);
128                _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
129                if ( _lock_val == 0 ) {
130                        pthread_mutex_init( t, NULL );
131                }
132                unlock(magic_mutex_check);
133        }
134} // mutex_check
135
136
137static void init(pthread_mutex_t * plock) {
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);
141}
142
143static simple_owner_lock * get(pthread_mutex_t * plock) {
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;
146}
147
148static void destroy(pthread_mutex_t * plock) {
149        static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
150        ^?{}(*get(plock));
151}
152
153//######################### Attr helpers #########################
154typedef struct 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} cfaPthread_attr_t;
163
164static const cfaPthread_attr_t default_attrs {
165        0,
166        0,
167        65_000,
168        NULL,
169        0,
170        0,
171        {0}
172};
173
174static cfaPthread_attr_t * get(const pthread_attr_t * attr) {
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;
177}
178
179
180//######################### Threads Helper #########################
181
182// exception for cancel_stack in pthread_exit
183exception pthread_exit_exp {};
184static vtable(pthread_exit_exp) exp_vt;
185
186thread cfaPthread{
187        cfaPthread_attr_t attr;
188        pthread_t pthreadId;
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;
204};
205
206/* thread part routines */
207//  cfaPthread entry point
208void main(cfaPthread & _thread) with(_thread) {
209        joinval = start_routine(start_arg);
210        isTerminated = true;
211}
212
213static cfaPthread * lookup( pthread_t p ) {
214        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *),"sizeof(pthread_t) < sizeof(cfaPthread *)");
215        return (cfaPthread *)p;
216}
217
218static void pthread_deletespecific_( pthread_values * values )  { // see uMachContext::invokeTask
219        pthread_values * value;
220        pthread_keys * key;
221        bool destcalled = true;
222        if (values != NULL) {
223                for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) {
224                        destcalled = false;
225                        lock(key_lock);
226                        for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) {
227                                // for each valid key
228                                if ( values[i].in_use) {
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.
235                                        if (value->value != NULL && key->destructor != NULL) {
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
248}
249
250static void ^?{}(cfaPthread & mutex t) {
251        // delete pthread local storage
252        pthread_values * values = t.pthreadData;
253        pthread_deletespecific_(values);
254}
255
256static void ?{}(cfaPthread & t, pthread_t * _thread, const pthread_attr_t * _attr,void *(* start_routine)(void *), void * arg) {
257        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread *)");
258
259        // set up user thread stackSize
260        cfaPthread_attr_t * attr = get(_attr);
261        ((thread&)t){ attr ? attr->stacksize: DEFAULT_STACK_SIZE };
262
263        // initialize _thread & cfaPthread id
264        *_thread = t.pthreadId = (pthread_t)(&t);
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;
271        t.start_arg = arg;
272        t.pthreadData = NULL;
273}
274
275
276extern "C"{
277        //######################### Pthread Attrs #########################
278
279        int pthread_attr_init(pthread_attr_t * attr) libcfa_public __THROW {
280                cfaPthread_attr_t * _attr = get(attr);
281                ?{}(*_attr, default_attrs);
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
353                check_nonnull(attr);
354
355                // copy all fields
356                *get(attr) = lookup( threadID )->attr;
357
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();
366                (*t){_thread, attr, start_routine, arg};
367                return 0;
368        }
369
370        int pthread_join(pthread_t _thread, void ** value_ptr) libcfa_public __THROW {
371                // if thread is invalid
372                if (_thread == NULL) return EINVAL;
373                if (_thread == pthread_self()) return EDEADLK;
374
375                // get user thr pointer
376                cfaPthread * p = lookup(_thread);
377                try {
378                        join(*p);
379                }
380                // if thread called pthread_exit
381                catchResume (ThreadCancelled(cfaPthread) * cancel) {}
382
383                // fetch result
384                if (value_ptr != NULL ) *value_ptr = p->joinval;
385                delete(p);
386                return 0;
387        }
388
389        int pthread_tryjoin_np(pthread_t _thread, void ** value_ptr) libcfa_public __THROW {
390                // if thread is invalid
391                if (_thread == NULL) return EINVAL;
392                if (_thread == pthread_self()) return EDEADLK;
393
394                cfaPthread * p = lookup(_thread);
395
396                // thread not finished ?
397                if (!p->isTerminated) return EBUSY;
398
399                join( *p );
400
401                if (value_ptr != NULL ) *value_ptr = p->joinval;
402                delete(p);
403                return 0;
404        }
405
406        pthread_t pthread_self(void) libcfa_public __THROW {
407                return (pthread_t)((uintptr_t)active_thread() - (sizeof(cfaPthread) - sizeof(thread$)));
408        }
409
410        void pthread_exit(void * status) libcfa_public __THROW {
411                pthread_t pid = pthread_self();
412                cfaPthread * _thread = (cfaPthread *)pid;
413                _thread->joinval = status;  // set return value
414                _thread->isTerminated = 1;  // set terminated flag
415                cancel_stack((pthread_exit_exp){&exp_vt});
416        }   //pthread_exit_
417
418        int pthread_yield( void ) __THROW {                     // GNU extension
419                yield();
420                return 0;
421        }
422
423
424        //######################### Mutex #########################
425
426        int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t * attr) libcfa_public __THROW {
427                check_nonnull(_mutex);
428                init(_mutex);
429                return 0;
430        }   //pthread_mutex_init_
431
432
433        int pthread_mutex_destroy(pthread_mutex_t *_mutex) libcfa_public __THROW {
434                check_nonnull(_mutex);
435                simple_owner_lock * _lock = get(_mutex);
436                if (_lock->owner != NULL) {
437                        return EBUSY;
438                }
439                destroy(_mutex);
440                return 0;
441        }   //pthread_mutex_destroy_
442
443        int pthread_mutex_lock(pthread_mutex_t *_mutex) libcfa_public __THROW {
444                check_nonnull(_mutex);
445                mutex_check(_mutex);
446                simple_owner_lock * _lock = get(_mutex);
447                lock(*_lock);
448                return 0;
449        }   //pthread_mutex_lock_
450
451        int pthread_mutex_unlock(pthread_mutex_t *_mutex) libcfa_public __THROW {
452                check_nonnull(_mutex);
453                simple_owner_lock * _lock = get(_mutex);
454                if (_lock->owner != active_thread()) {
455                        return EPERM;
456                } // current thread does not hold the mutex
457                unlock(*_lock);
458                return 0;
459        }   //pthread_mutex_unlock_
460
461        int pthread_mutex_trylock(pthread_mutex_t *_mutex) libcfa_public __THROW {
462                check_nonnull(_mutex);
463                simple_owner_lock * _lock = get(_mutex);
464                if (_lock->owner != active_thread() && _lock->owner != NULL) {
465                        return EBUSY;
466                }   // if mutex is owned
467                lock(*_lock);
468                return 0;
469        }   //pthread_mutex_trylock_
470
471        //######################### Conditional Variable #########################
472
473        /* conditional variable routines */
474        int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr) libcfa_public __THROW {
475                check_nonnull(cond);
476                init(cond);
477                return 0;
478        }  //pthread_cond_init
479
480        int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t *_mutex) libcfa_public __THROW {
481                check_nonnull(_mutex);
482                check_nonnull(cond);
483                wait(*get(cond), *get(_mutex));
484                return 0;
485        } // pthread_cond_wait
486
487        int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * _mutex, const struct timespec * abstime) libcfa_public __THROW {
488                check_nonnull(_mutex);
489                check_nonnull(cond);
490                wait(*get(cond), *get(_mutex), *abstime);
491                return 0;
492        } // pthread_cond_timedwait
493
494        int pthread_cond_signal(pthread_cond_t * cond) libcfa_public __THROW {
495                check_nonnull(cond);
496                return notify_one(*get(cond));
497        } // pthread_cond_signal
498
499        int pthread_cond_broadcast(pthread_cond_t * cond) libcfa_public __THROW {
500                check_nonnull(cond);
501                return notify_all(*get(cond));
502        } // pthread_cond_broadcast
503
504        int pthread_cond_destroy(pthread_cond_t * cond) libcfa_public __THROW {
505                check_nonnull(cond);
506                destroy(cond);
507                return 0;
508        } // pthread_cond_destroy
509
510
511
512        //######################### Local storage #########################
513
514        int pthread_once(pthread_once_t * once_control, void (* init_routine)(void)) libcfa_public __THROW {
515                static_assert(sizeof(pthread_once_t) >= sizeof(int),"sizeof(pthread_once_t) < sizeof(int)");
516                check_nonnull(once_control);
517                check_nonnull(init_routine);
518                lock(once_lock);
519                if ( *((int *)once_control) == 0 ) {
520                        init_routine();
521                        *((int *)once_control) = 1;
522                } // if
523                unlock(once_lock);
524                return 0;
525        } // pthread_once
526
527        int pthread_key_create( pthread_key_t * key, void (* destructor)( void * ) ) libcfa_public __THROW {
528                lock(key_lock);
529                for ( int i = 0; i < PTHREAD_KEYS_MAX; i += 1 ) {
530                        if ( ! cfa_pthread_keys[i].in_use ) {
531                                cfa_pthread_keys[i].in_use = true;
532                                cfa_pthread_keys[i].destructor = destructor;
533                                unlock( key_lock );
534                                *key = i;
535                                return 0;
536                        } // if
537                } // for
538                unlock(key_lock);
539                return EAGAIN;
540        }   // pthread_key_create
541
542        int pthread_key_delete( pthread_key_t key ) libcfa_public __THROW {
543                lock(key_lock);
544                if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) {
545                        unlock( key_lock );
546                        return EINVAL;
547                } // if
548                cfa_pthread_keys[key].in_use = false;
549                cfa_pthread_keys[key].destructor = NULL;
550
551                // Remove key from all threads with a value.
552                pthread_values& p;
553                Sequence(pthread_values)& head = cfa_pthread_keys[key].threads;
554                for ( SeqIter(pthread_values) iter = { head }; iter | p; ) {
555                        remove(head, p);
556                        p.in_use = false;
557                }
558                unlock(key_lock);
559                return 0;
560        }   // pthread_key_delete
561
562        int pthread_setspecific( pthread_key_t key, const void * value ) libcfa_public __THROW {
563                // get current thread
564                cfaPthread * t = lookup(pthread_self());
565                // if current thread's pthreadData is NULL; initialize it
566                pthread_values * values;
567                if (t->pthreadData == NULL) {
568                        values = anew( PTHREAD_KEYS_MAX);
569                        t->pthreadData = values;
570                        for ( int i = 0;i < PTHREAD_KEYS_MAX; i++ ) {
571                                t->pthreadData[i].in_use = false;
572                        }   // for
573                }   else {
574                        values = t->pthreadData;
575                }   // if
576                // find corresponding key and set value
577                lock(key_lock);
578                // if invalid key
579                if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) {
580                        unlock( key_lock );
581                        return EINVAL;
582                } // if
583                pthread_values &entry = values[key];
584                if ( ! entry.in_use ) {
585                        entry.in_use = true;
586                        add(cfa_pthread_keys[key].threads, entry);
587                } // if
588                entry.value = (void *)value;
589                unlock(key_lock);
590                return 0;
591        } //pthread_setspecific
592
593        void * pthread_getspecific(pthread_key_t key) libcfa_public __THROW {
594                if (key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use) return NULL;
595
596                // get current thread
597                cfaPthread * t = lookup(pthread_self());
598                if (t->pthreadData == NULL) return NULL;
599                lock(key_lock);
600                pthread_values & entry = ((pthread_values *)t->pthreadData)[key];
601                if ( ! entry.in_use ) {
602                        unlock( key_lock );
603                        return NULL;
604                } // if
605                void * value = entry.value;
606                unlock(key_lock);
607
608                return value;
609        }   //pthread_get_specific
610
611        //######################### Parallelism #########################
612        void pthread_delete_kernel_threads_() __THROW { // see uMain::~uMain
613                Pthread_kernel_threads& p;
614                for ( StackIter(Pthread_kernel_threads) iter = {cfa_pthreads_kernel_threads}; iter | p; ) {
615                        delete(&p);
616                } // for
617        } // pthread_delete_kernel_threads_
618
619        int pthread_getconcurrency( void ) __THROW {    // XOPEN extension
620                return cfa_pthreads_kernel_threads_zero ? 0 : cfa_pthreads_no_kernel_threads;
621        } // pthread_getconcurrency
622
623        int pthread_setconcurrency( int new_level ) libcfa_public __THROW { // XOPEN extension
624                if ( new_level < 0 ) return EINVAL;
625                if ( new_level == 0 ) {
626                        cfa_pthreads_kernel_threads_zero = true;        // remember set to zero, but ignore
627                        return 0;                                       // do not do kernel thread management
628                } // exit
629                cfa_pthreads_kernel_threads_zero = false;
630                lock( concurrency_lock );
631                for ( ; new_level > cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads += 1 ) { // add processors ?
632                        push(cfa_pthreads_kernel_threads, *new() );
633                } // for
634                for ( ; new_level < cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads -= 1 ) { // remove processors ?
635                        delete(&pop(cfa_pthreads_kernel_threads));
636                } // for
637                unlock( concurrency_lock );
638                return 0;
639        } // pthread_setconcurrency
640
641        //######################### Signal #########################
642
643
644         int pthread_sigmask( int /* how */, const sigset_t * /* set */, sigset_t * /* oset */ ) libcfa_public __THROW {
645                abort( "pthread_sigmask : not implemented" );
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                abort( "pthread_sigqueue : not implemented" );
660                return 0;
661        } // pthread_sigqueue
662
663        //######################### Scheduling #########################
664        int pthread_detach( pthread_t threadID ) __THROW {
665                abort( "pthread_detach : not implemented" );
666                return 0;
667        } // pthread_detach
668
669        int pthread_setschedparam( pthread_t /* thread */, int /* policy */, const struct sched_param * /* param */ ) libcfa_public __THROW {
670                abort( "pthread_setschedparam : not implemented" );
671                return 0;
672        } // pthread_setschedparam
673
674        int pthread_getschedparam( pthread_t /* thread */, int */* policy */, struct sched_param * /* param */ ) libcfa_public __THROW {
675                abort( "pthread_getschedparam : not implemented" );
676                return 0;
677        } // pthread_getschedparam
678
679         //######################### Mutex Attr #########################
680
681        int pthread_mutexattr_init( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW {
682                return 0;
683        } // pthread_mutexattr_init
684
685        int pthread_mutexattr_destroy( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW {
686                return 0;
687        } // pthread_mutexattr_destroy
688
689        int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW {
690                return 0;
691        } // pthread_mutexattr_setpshared
692
693        int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW {
694                return 0;
695        } // pthread_mutexattr_getpshared
696
697        int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW {
698                return 0;
699        } // pthread_mutexattr_setprotocol
700
701        int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW {
702                return 0;
703        } // pthread_mutexattr_getprotocol
704
705        int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW {
706                return 0;
707        } // pthread_mutexattr_setprioceiling
708
709        int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW {
710                return 0;
711        } // pthread_mutexattr_getprioceiling
712
713        int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW {
714                return 0;
715        } // pthread_mutex_setprioceiling
716
717        int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW {
718                return 0;
719        } // pthread_mutex_getprioceiling
720
721        int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW {
722                return 0;
723        } // pthread_mutexattr_gettype
724
725        int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW {
726                return 0;
727        } // pthread_mutexattr_settype
728
729        //######################### Mutex #########################
730
731        int pthread_mutex_timedlock( pthread_mutex_t *__restrict /* __mutex */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
732                abort( "pthread_mutex_timedlock" );
733        } // pthread_mutex_timedlock
734
735        //######################### Condition #########################
736
737        int pthread_condattr_getclock( __const pthread_condattr_t * __restrict /* __attr */, __clockid_t *__restrict /* __clock_id */ ) libcfa_public __THROW {
738                abort( "pthread_condattr_getclock" );
739        } // pthread_condattr_getclock
740
741        int pthread_condattr_setclock( pthread_condattr_t * /* __attr */, __clockid_t /* __clock_id */ ) libcfa_public __THROW {
742                abort( "pthread_condattr_setclock" );
743        } // pthread_condattr_setclock
744
745        //######################### Spinlock #########################
746
747        int pthread_spin_init( pthread_spinlock_t * /* __lock */, int /*__pshared */ ) libcfa_public __THROW {
748                abort( "pthread_spin_init" );
749        } // pthread_spin_init
750
751        int pthread_spin_destroy( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
752                abort( "pthread_spin_destroy" );
753        } // pthread_spin_destroy
754
755        int pthread_spin_lock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
756                abort( "pthread_spin_lock" );
757        } // pthread_spin_lock
758
759        int pthread_spin_trylock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
760                abort( "pthread_spin_trylock" );
761        } // pthread_spin_trylock
762
763        int pthread_spin_unlock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
764                abort( "pthread_spin_unlock" );
765        } // pthread_spin_unlock
766
767        //######################### Barrier #########################
768
769        int pthread_barrier_init( pthread_barrier_t *__restrict /* __barrier */, __const pthread_barrierattr_t *__restrict /* __attr */, unsigned int /* __count */ ) libcfa_public __THROW {
770                abort( "pthread_barrier_init" );
771        } // pthread_barrier_init
772
773        int pthread_barrier_destroy( pthread_barrier_t * /* __barrier */ ) libcfa_public  __THROW {
774                abort( "pthread_barrier_destroy" );
775        } // pthread_barrier_destroy
776
777        int pthread_barrier_wait( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW {
778                abort( "pthread_barrier_wait" );
779        } // pthread_barrier_wait
780
781        int pthread_barrierattr_init( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
782                abort( "pthread_barrierattr_init" );
783        } // pthread_barrierattr_init
784
785        int pthread_barrierattr_destroy( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
786                abort( "pthread_barrierattr_destroy" );
787        } // pthread_barrierattr_destroy
788
789        int pthread_barrierattr_getpshared( __const pthread_barrierattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW {
790                abort( "pthread_barrierattr_getpshared" );
791        } // pthread_barrierattr_getpshared
792
793        int pthread_barrierattr_setpshared( pthread_barrierattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
794                abort( "pthread_barrierattr_setpshared" );
795        } // pthread_barrierattr_setpshared
796
797        //######################### Clock #########################
798
799        int pthread_getcpuclockid( pthread_t /* __thread_id */, __clockid_t * /* __clock_id */ ) libcfa_public __THROW {
800                abort( "pthread_getcpuclockid" );
801        } // pthread_getcpuclockid
802
803        // pthread_atfork()
804
805// UNIX98
806
807        //######################### Read/Write #########################
808
809        int pthread_rwlock_init( pthread_rwlock_t *__restrict /* __rwlock */, __const pthread_rwlockattr_t *__restrict /* __attr */ ) libcfa_public __THROW {
810                abort( "pthread_rwlock_init" );
811        } // pthread_rwlock_init
812
813        int pthread_rwlock_destroy( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
814                abort( "pthread_rwlock_destroy" );
815        } // pthread_rwlock_destroy
816
817        int pthread_rwlock_rdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
818                abort( "pthread_rwlock_rdlock" );
819        } // pthread_rwlock_rdlock
820
821        int pthread_rwlock_tryrdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
822                abort( "pthread_rwlock_tryrdlock" );
823        } // pthread_rwlock_tryrdlock
824
825        int pthread_rwlock_wrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
826                abort( "pthread_rwlock_wrlock" );
827        } // pthread_rwlock_wrlock
828
829        int pthread_rwlock_trywrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
830                abort( "pthread_rwlock_trywrlock" );
831        } // pthread_rwlock_trywrlock
832
833        int pthread_rwlock_unlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
834                abort( "pthread_rwlock_unlock" );
835        } // pthread_rwlock_unlock
836
837        int pthread_rwlockattr_init( pthread_rwlockattr_t * /* __attr */ ) libcfa_public __THROW {
838                abort( "pthread_rwlockattr_init" );
839        } // pthread_rwlockattr_init
840
841        int pthread_rwlockattr_destroy( pthread_rwlockattr_t * /*__attr */ ) libcfa_public __THROW {
842                abort( "pthread_rwlockattr_destroy" );
843        } // pthread_rwlockattr_destroy
844
845        int pthread_rwlockattr_getpshared( __const pthread_rwlockattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW {
846                abort( "pthread_rwlockattr_getpshared" );
847        } // pthread_rwlockattr_getpshared
848
849        int pthread_rwlockattr_setpshared( pthread_rwlockattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
850                abort( "pthread_rwlockattr_setpshared" );
851        } // pthread_rwlockattr_setpshared
852
853        int pthread_rwlockattr_getkind_np( __const pthread_rwlockattr_t * /* __attr */, int * /* __pref */ ) libcfa_public __THROW {
854                abort( "pthread_rwlockattr_getkind_np" );
855        } // pthread_rwlockattr_getkind_np
856
857        int pthread_rwlockattr_setkind_np( pthread_rwlockattr_t * /* __attr */, int /* __pref */ ) libcfa_public __THROW {
858                abort( "pthread_rwlockattr_setkind_np" );
859        } // pthread_rwlockattr_setkind_np
860
861// UNIX98 + XOPEN
862
863        int pthread_rwlock_timedrdlock( pthread_rwlock_t *__restrict  /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
864                abort( "pthread_rwlock_timedrdlock" );
865        } // pthread_rwlock_timedrdlock
866
867        int pthread_rwlock_timedwrlock( pthread_rwlock_t *__restrict  /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
868                abort( "pthread_rwlock_timedwrlock" );
869        } // pthread_rwlock_timedwrlock
870
871// GNU
872
873        //######################### Parallelism #########################
874
875        // int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
876        //      abort( "pthread_setaffinity_np" );
877        // } // pthread_setaffinity_np
878
879        // int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
880        //      abort( "pthread_getaffinity_np" );
881        // } // pthread_getaffinity_np
882
883        // int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
884        //      abort( "pthread_attr_setaffinity_np" );
885        // } // pthread_attr_setaffinity_np
886
887        // int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
888        //      abort( "pthread_attr_getaffinity_np" );
889        // } // pthread_attr_getaffinity_np
890
891        //######################### Cancellation #########################
892
893        void _pthread_cleanup_push_defer( struct _pthread_cleanup_buffer * /* __buffer */, void( * /* __routine */ )( void * ), void * /* __arg */ ) libcfa_public __THROW {
894                abort( "_pthread_cleanup_push_defer" );
895        } // _pthread_cleanup_push_defer
896
897        void _pthread_cleanup_pop_restore( struct _pthread_cleanup_buffer * /* __buffer */, int /* __execute */ ) libcfa_public __THROW {
898                abort( "_pthread_cleanup_pop_restore" );
899        } // _pthread_cleanup_pop_res
900
901        int pthread_cancel( pthread_t threadID ) libcfa_public __THROW {
902                abort("pthread cancel not implemented");
903                return 0;
904        } // pthread_cancel
905
906        int pthread_setcancelstate( int state, int * oldstate ) libcfa_public __THROW {
907                abort("pthread_setcancelstate not implemented");
908                return 0;
909        } // pthread_setcancelstate
910
911        int pthread_setcanceltype( int type, int * oldtype ) libcfa_public __THROW {
912                abort("pthread_setcanceltype not implemented");
913                return 0;
914        } // pthread_setcanceltype
915} // extern "C"
916
917#pragma GCC diagnostic pop
Note: See TracBrowser for help on using the repository browser.