source: libcfa/src/concurrency/pthread.cfa@ 0ac8d07

Last change on this file since 0ac8d07 was 555af62, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

add include bits/sequence.hfa to pthread.cfa after removing it from weakso_lock.hfa

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