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

Last change on this file since b28ce93 was 6b33e89, checked in by Peter A. Buhr <pabuhr@…>, 5 months ago

change backquote call to regular call

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