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

ADT ast-experimental
Last change on this file since efdd18c was a0a949c, checked in by Peter A. Buhr <pabuhr@…>, 3 years ago

formatting, remove unnecessary #include files and code

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