source: libcfa/src/concurrency/pthread.cfa@ 3859adb

Last change on this file since 3859adb was 9cbb2d4, checked in by Peter A. Buhr <pabuhr@…>, 4 days ago

remove enum for PTHREAD_KEYS_MAX and replace with #include <limits.h>

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