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

ADT ast-experimental pthread-emulation
Last change on this file since 20be782 was 20be782, checked in by z277zhu <z277zhu@…>, 3 years 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.