Index: libcfa/src/Makefile.am
===================================================================
--- libcfa/src/Makefile.am	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/Makefile.am	(revision 1a452638e119559b489523986faa60a438969248)
@@ -127,4 +127,5 @@
 
 thread_libsrc = ${inst_thread_headers_src} ${inst_thread_headers_src:.hfa=.cfa} \
+	interpose_thread.cfa \
 	bits/signal.hfa \
 	concurrency/clib/cfathread.cfa \
@@ -145,5 +146,6 @@
 	concurrency/stats.cfa \
 	concurrency/stats.hfa \
-	concurrency/stats.hfa
+	concurrency/stats.hfa \
+	concurrency/pthread.cfa
 
 else
Index: libcfa/src/concurrency/clib/cfathread.cfa
===================================================================
--- libcfa/src/concurrency/clib/cfathread.cfa	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/concurrency/clib/cfathread.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -172,9 +172,9 @@
 
 		pthread_attr_t attr;
-		if (int ret = pthread_attr_init(&attr); 0 != ret) {
+		if (int ret = __cfaabi_pthread_attr_init(&attr); 0 != ret) {
 			abort | "failed to create master epoll thread attr: " | ret | strerror(ret);
 		}
 
-		if (int ret = pthread_create(&master_poller, &attr, master_epoll, 0p); 0 != ret) {
+		if (int ret = __cfaabi_pthread_create(&master_poller, &attr, master_epoll, 0p); 0 != ret) {
 			abort | "failed to create master epoll thread: " | ret | strerror(ret);
 		}
Index: libcfa/src/concurrency/io.cfa
===================================================================
--- libcfa/src/concurrency/io.cfa	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/concurrency/io.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -610,5 +610,5 @@
 		if( we ) {
 			sigval_t value = { PREEMPT_IO };
-			pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value);
+			__cfaabi_pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value);
 		}
 
Index: libcfa/src/concurrency/io/setup.cfa
===================================================================
--- libcfa/src/concurrency/io/setup.cfa	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/concurrency/io/setup.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -344,5 +344,5 @@
 	// 	iopoll.run = false;
 	// 	sigval val = { 1 };
-	// 	pthread_sigqueue( iopoll.thrd, SIGUSR1, val );
+	// 	__cfaabi_pthread_sigqueue( iopoll.thrd, SIGUSR1, val );
 
 	// 	// Make sure all this is done
Index: libcfa/src/concurrency/kernel/private.hfa
===================================================================
--- libcfa/src/concurrency/kernel/private.hfa	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/concurrency/kernel/private.hfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -20,4 +20,6 @@
 #endif
 
+#include <signal.h>
+
 #include "kernel.hfa"
 #include "thread.hfa"
@@ -48,5 +50,4 @@
 	#endif
 #endif
-
 // #define READYQ_USE_LINEAR_AVG
 #define READYQ_USE_LOGDBL_AVG
@@ -62,4 +63,16 @@
 #error must pick a scheme for averaging
 #endif
+
+extern "C" {
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_create(pthread_t *_thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_join(pthread_t _thread, void **retval);
+	__attribute__((visibility("protected"))) pthread_t __cfaabi_pthread_self(void);
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_attr_init(pthread_attr_t *attr);
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_attr_destroy(pthread_attr_t *attr);
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize );
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize );
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_sigqueue(pthread_t _thread, int sig, const union sigval value);
+	__attribute__((visibility("protected"))) int __cfaabi_pthread_sigmask( int how, const sigset_t *set, sigset_t *oset);
+}
 
 //-----------------------------------------------------------------------------
Index: libcfa/src/concurrency/kernel/startup.cfa
===================================================================
--- libcfa/src/concurrency/kernel/startup.cfa	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/concurrency/kernel/startup.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -222,5 +222,5 @@
 		( this.runner ){};
 		init( this, "Main Processor", *mainCluster, 0p );
-		kernel_thread = pthread_self();
+		kernel_thread = __cfaabi_pthread_self();
 
 		runner{ &this };
@@ -283,6 +283,15 @@
 }
 
+extern "C"{
+	void pthread_delete_kernel_threads_();
+}
+
+
 static void __kernel_shutdown(void) {
 	if(!cfa_main_returned) return;
+
+	//delete kernel threads for pthread_concurrency
+	pthread_delete_kernel_threads_();
+
 	/* paranoid */ verify( __preemption_enabled() );
 	disable_interrupts();
@@ -777,5 +786,5 @@
 	pthread_attr_t attr;
 
-	check( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
+	check( __cfaabi_pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
 
 	size_t stacksize = max( PTHREAD_STACK_MIN, DEFAULT_STACK_SIZE );
@@ -804,11 +813,11 @@
 	#endif
 
-	check( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
-	check( pthread_create( pthread, &attr, start, arg ), "pthread_create" );
+	check( __cfaabi_pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
+	check( __cfaabi_pthread_create( pthread, &attr, start, arg ), "pthread_create" );
 	return stack;
 }
 
 void __destroy_pthread( pthread_t pthread, void * stack, void ** retval ) {
-	int err = pthread_join( pthread, retval );
+	int err = __cfaabi_pthread_join( pthread, retval );
 	if( err != 0 ) abort("KERNEL ERROR: joining pthread %p caused error %s\n", (void*)pthread, strerror(err));
 
@@ -816,9 +825,9 @@
 		pthread_attr_t attr;
 
-		check( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
+		check( __cfaabi_pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
 
 		size_t stacksize;
 		// default stack size, normally defined by shell limit
-		check( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
+		check( __cfaabi_pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
 		assert( stacksize >= PTHREAD_STACK_MIN );
 		stacksize += __page_size;
Index: libcfa/src/concurrency/preemption.cfa
===================================================================
--- libcfa/src/concurrency/preemption.cfa	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/concurrency/preemption.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -352,5 +352,5 @@
 	sigset_t oldset;
 	int ret;
-	ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
+	ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
 	if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
 
@@ -385,5 +385,5 @@
 	sigaddset( &mask, sig );
 
-	if ( pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
+	if ( __cfaabi_pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
 	    abort( "internal error, pthread_sigmask" );
 	}
@@ -396,5 +396,5 @@
 	sigaddset( &mask, sig );
 
-	if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
+	if ( __cfaabi_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
 		abort( "internal error, pthread_sigmask" );
 	}
@@ -404,5 +404,5 @@
 static void preempt( processor * this ) {
 	sigval_t value = { PREEMPT_NORMAL };
-	pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
+	__cfaabi_pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
 }
 
@@ -415,5 +415,5 @@
 	sigset_t oldset;
 	int ret;
-	ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
+	ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
 	if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
 
@@ -434,5 +434,5 @@
 	sigset_t oldset;
 	int ret;
-	ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
+	ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
 	if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
 
@@ -505,5 +505,5 @@
 	sigval val;
 	val.sival_int = 0;
-	pthread_sigqueue( alarm_thread, SIGALRM, val );
+	__cfaabi_pthread_sigqueue( alarm_thread, SIGALRM, val );
 
 	// Wait for the preemption thread to finish
@@ -579,5 +579,5 @@
 	static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" );
 	#endif
-	if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
+	if ( __cfaabi_pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
 		abort( "internal error, sigprocmask" );
 	}
@@ -607,5 +607,5 @@
 	sigset_t mask;
 	sigfillset(&mask);
-	if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
+	if ( __cfaabi_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
 	    abort( "internal error, pthread_sigmask" );
 	}
Index: libcfa/src/concurrency/pthread.cfa
===================================================================
--- libcfa/src/concurrency/pthread.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ libcfa/src/concurrency/pthread.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,917 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// pthread.cfa --
+//
+// Author           : Zhenyan Zhu
+// Created On       : Sat Aug 6 16:29:18 2022
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#define __cforall_thread__
+#define _GNU_SOURCE
+
+#include <signal.h>
+#include <pthread.h>
+#include <errno.h>
+#include "locks.hfa"
+#include "bits/stack.hfa"
+
+
+#define check_nonnull(x) asm("": "+rm"(x)); if( x == 0p ) return EINVAL;
+
+/* pthread key, pthread once inner routine mutual exclusion */
+static simple_owner_lock once_lock,key_lock,magic_mutex_check, concurrency_lock;
+
+//######################### Local Storage Helpers #########################
+
+enum { PTHREAD_KEYS_MAX = 1024 };
+
+struct Pthread_values{
+	inline Seqable;
+	void* value;
+	bool in_use;
+};
+
+
+static Pthread_values *& Back( Pthread_values * n ) {
+	return (Pthread_values *)Back( (Seqable *)n );
+}
+static Pthread_values *& Next( Pthread_values * n ) {
+	return (Pthread_values *)Next( (Colable *)n );
+}
+
+struct Pthread_keys{
+	bool in_use;
+	void (*destructor)( void * );
+	Sequence(Pthread_values) threads;
+};  // Pthread keys
+
+static void ?{}(Pthread_keys& k){
+	k.threads{};
+}
+
+// Create storage separately to ensure no constructors are called.
+static Pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));
+
+static void init_pthread_storage(){
+	for (int i = 0; i < PTHREAD_KEYS_MAX; i++){
+		cfa_pthread_keys_storage[i]{};
+	}
+}
+
+#define cfa_pthread_keys ((Pthread_keys *)cfa_pthread_keys_storage)
+
+/* Controlling the iterations of destructors for thread-specific data.  */
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4
+/* Number of iterations this implementation does.  */
+#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+//######################### Parallelism Helpers #########################
+
+struct Pthread_kernel_threads{
+	inline Colable;
+	processor p;
+};
+
+Pthread_kernel_threads *& Next( Pthread_kernel_threads * n ) {
+	return (Pthread_kernel_threads *)Next( (Colable *)n );
+}
+
+static Stack(Pthread_kernel_threads) cfa_pthreads_kernel_threads;
+static bool cfa_pthreads_kernel_threads_zero = false;	// set to zero ?
+static int cfa_pthreads_no_kernel_threads = 1;	// number of kernel threads
+
+
+//######################### Cond Helpers #########################
+
+typedef pthread_cond_var(simple_owner_lock) cfa2pthr_cond_var_t;
+
+/* condvar helper routines */
+static void init(pthread_cond_t* pcond){
+	static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
+	cfa2pthr_cond_var_t* _cond = (cfa2pthr_cond_var_t*)pcond;
+	?{}(*_cond);
+}
+
+static cfa2pthr_cond_var_t* get(pthread_cond_t* pcond){
+	static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
+	return (cfa2pthr_cond_var_t*)pcond;
+}
+
+static void destroy(pthread_cond_t* cond){
+	static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
+	^?{}(*get(cond));
+}
+
+
+//######################### Mutex Helper #########################
+
+/* mutex helper routines */
+static void mutex_check(pthread_mutex_t* t){
+	// Use double check to improve performance. Check is safe on x86; volatile prevents compiler reordering
+	volatile pthread_mutex_t *const mutex_ = t;
+	// SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h
+	int _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
+	// if pthread_mutex_t is initialized by PTHREAD_MUTEX_INITIALIZER, _lock_val should be 0
+	if ( _lock_val == 0 ) {			// static initialized ?
+		lock(magic_mutex_check);	// race
+		_lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
+		if ( _lock_val == 0 ) {		// static initialized ?
+		pthread_mutex_init( t, NULL );
+		} // if
+		unlock(magic_mutex_check);	// race
+	} // if
+} // mutex_check
+
+
+static void init(pthread_mutex_t* plock){
+	static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
+	simple_owner_lock* _lock = (simple_owner_lock*)plock;
+	?{}(*_lock);
+}
+
+static simple_owner_lock* get(pthread_mutex_t* plock){
+	static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
+	return (simple_owner_lock*)plock;
+}
+
+static void destroy(pthread_mutex_t* plock){
+	static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
+	^?{}(*get(plock));
+}
+
+//######################### Attr helpers #########################
+struct cfaPthread_attr_t {								// thread attributes
+		int contentionscope;
+		int detachstate;
+		size_t stacksize;
+		void *stackaddr;
+		int policy;
+		int inheritsched;
+		struct sched_param param;
+} typedef cfaPthread_attr_t;
+
+static const cfaPthread_attr_t default_attrs{
+	0,
+	0,
+	(size_t)65000,
+	(void *)NULL,
+	0,
+	0,
+	{0}
+};
+
+
+/*
+static const cfaPthread_attr_t default_attrs = {
+	PTHREAD_SCOPE_SYSTEM,
+	PTHREAD_CREATE_JOINABLE,
+	(size_t)DEFAULT_STACK_SIZE,
+	(void *)NULL,
+	0,
+	PTHREAD_EXPLICIT_SCHED,
+	{0}
+};
+*/
+
+
+
+static cfaPthread_attr_t* get(const pthread_attr_t* attr){
+	static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t),"sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)");
+	return (cfaPthread_attr_t*)attr;
+}
+
+
+//######################### Threads Helper #########################
+
+// exception for cancel_stack in pthread_exit
+exception pthread_exit_exp {};
+static vtable(pthread_exit_exp) exp_vt;
+
+thread cfaPthread{
+	cfaPthread_attr_t attr;
+	pthread_t pthreadId;
+	void *joinval;										// pthreads return value
+	pthread_attr_t pthread_attr;						// pthread attributes
+	void *(*start_routine)(void *);                     // routine start
+	void *arg;					                        // thread parameter
+	Pthread_values* pthreadData;
+	bool isTerminated;                                  // flag used for tryjoin
+};
+
+/* thread part routines */
+//  cfaPthread entry point
+void main(cfaPthread& _thread) with(_thread){
+	joinval =  start_routine(arg);
+	isTerminated = true;
+}
+
+// generate pthread_t by cfaPthread ptr
+static pthread_t create( cfaPthread *p ) {
+	static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");
+	return (pthread_t)p;
+}
+
+static cfaPthread *lookup( pthread_t p ){
+	static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");
+	return (cfaPthread*)p;
+}
+
+static void pthread_deletespecific_( Pthread_values* values )  { // see uMachContext::invokeTask
+	Pthread_values* value;
+	Pthread_keys* key;
+	bool destcalled = true;
+	if (values != NULL){
+		for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) {
+			destcalled = false;
+			lock(key_lock);
+			for (int i = 0; i < PTHREAD_KEYS_MAX; i++){
+				// for each valid key
+				if ( values[i].in_use){
+					value = &values[i];
+					key = &cfa_pthread_keys[i];
+					value->in_use = false;
+					remove(key->threads, *value);
+					// if  a  key  value  has  a  non-NULL  destructor pointer,  and  the  thread  has  a  non-NULL  value associated with that key,
+					// 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.
+					if (value->value != NULL && key->destructor != NULL){
+						unlock(key_lock);
+						key->destructor(value->value); // run destructor
+						lock(key_lock);
+						destcalled = true;
+					}   // if
+					value->value = NULL;
+				}   // if
+			}   // for
+			unlock(key_lock);
+		}   // for
+		free(values);
+	}   // if
+}
+
+static void ^?{}(cfaPthread & mutex t){
+	// delete pthread local storage
+	Pthread_values* values = t.pthreadData;
+	pthread_deletespecific_(values);
+}
+
+static void ?{}(cfaPthread &t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) {
+
+	// set up user thread stackSize
+	cfaPthread_attr_t * attr = get(_attr);
+	((thread&)t){ attr ? attr->stacksize: DEFAULT_STACK_SIZE };
+
+	// initialize _thread & cfaPthread id
+	t.pthreadId = create(&t);
+	*_thread = t.pthreadId;
+
+	// if attr null, self attr will be set as default_attrs; else set to attr
+	t.attr = (attr != NULL ? *attr : default_attrs);
+
+	// init start routine and arguments
+	t.start_routine = start_routine;
+	t.arg = arg;
+	t.pthreadData = NULL;
+}   // not used
+
+
+extern "C"{
+	//######################### Pthread Attrs #########################
+
+	int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW {
+		cfaPthread_attr_t* _attr = get(attr);
+		?{}(*_attr);
+		*_attr = default_attrs;
+		return 0;
+	}
+	int pthread_attr_destroy(pthread_attr_t *attr) libcfa_public __THROW {
+		^?{}(*get(attr));
+		return 0;
+	}
+
+	int pthread_attr_setscope( pthread_attr_t *attr, int contentionscope ) libcfa_public __THROW {
+		get( attr )->contentionscope = contentionscope;
+		return 0;
+	} // pthread_attr_setscope
+
+	int pthread_attr_getscope( const pthread_attr_t *attr, int *contentionscope ) libcfa_public __THROW {
+		*contentionscope = get( attr )->contentionscope;
+		return 0;
+	} // pthread_attr_getscope
+
+	int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate ) libcfa_public __THROW {
+		get( attr )->detachstate = detachstate;
+		return 0;
+	} // pthread_attr_setdetachstate
+
+	int pthread_attr_getdetachstate( const pthread_attr_t *attr, int *detachstate ) libcfa_public __THROW {
+		*detachstate = get( attr )->detachstate;
+		return 0;
+	} // pthread_attr_getdetachstate
+
+	int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize ) libcfa_public __THROW {
+		get( attr )->stacksize = stacksize;
+		return 0;
+	} // pthread_attr_setstacksize
+
+	int pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize ) libcfa_public __THROW {
+		*stacksize = get( attr )->stacksize;
+		return 0;
+	} // pthread_attr_getstacksize
+
+	int pthread_attr_getguardsize( const pthread_attr_t * /* attr */, size_t * /* guardsize */ ) libcfa_public __THROW {
+		return 0;
+	} // pthread_attr_getguardsize
+
+	int pthread_attr_setguardsize( pthread_attr_t * /* attr */, size_t /* guardsize */ ) libcfa_public __THROW {
+		return 0;
+	} // pthread_attr_setguardsize
+
+	int pthread_attr_setstackaddr( pthread_attr_t *attr, void *stackaddr ) libcfa_public __THROW {
+		get( attr )->stackaddr = stackaddr;
+		return 0;
+	} // pthread_attr_setstackaddr
+
+	int pthread_attr_getstackaddr( const pthread_attr_t *attr, void **stackaddr ) libcfa_public __THROW {
+		*stackaddr = get( attr )->stackaddr;
+		return 0;
+	} // pthread_attr_getstackaddr
+
+	int pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW {
+		get( attr )->stackaddr = stackaddr;
+		get( attr )->stacksize = stacksize;
+		return 0;
+	} // pthread_attr_setstack
+
+	int pthread_attr_getstack( const pthread_attr_t *attr, void **stackaddr, size_t *stacksize ) libcfa_public __THROW {
+		*stackaddr = get( attr )->stackaddr;
+		*stacksize = get( attr )->stacksize;
+		return 0;
+	} // pthread_attr_getstack
+
+	// Initialize thread attribute *attr with attributes corresponding to the
+	// already running thread threadID. It shall be called on unitialized attr
+	// and destroyed with pthread_attr_destroy when no longer needed.
+	int pthread_getattr_np( pthread_t threadID, pthread_attr_t *attr ) libcfa_public __THROW { // GNU extension
+		// race condition during copy
+		cfaPthread_attr_t* _attr = get(attr);
+		?{}(*_attr);
+		if (_attr == NULL){
+			return ENOMEM;
+		}   // if
+		*_attr = lookup( threadID )->attr; // copy all fields
+		return 0;
+	} // pthread_getattr_np
+
+
+	//######################### Threads #########################
+
+	int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) libcfa_public __THROW {
+		cfaPthread *t = alloc();
+		(*t){_thread, attr, start_routine, arg};
+		//init_user_pthread(*t, _thread, attr, start_routine, arg);
+		if (t == NULL) return EAGAIN; //no resource
+		return 0;
+	}   //pthread_create_
+
+
+	int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
+		if (_thread == NULL) return EINVAL;   // if thread is invalid
+		if (_thread == pthread_self()) return EDEADLK;
+		cfaPthread* p = lookup(_thread);    // get user thr pointer
+		try {
+			join(*p);
+		} catchResume (ThreadCancelled(cfaPthread) * cancel) {} // if thread called pthread_exit
+		if (value_ptr != NULL ) *value_ptr = p->joinval;   // fetch result
+		delete(p);
+		return 0;
+	}   //pthread_join_
+
+	int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
+		if (_thread == NULL) return EINVAL;  // if thread is invalid
+		if (_thread == pthread_self()) return EDEADLK;
+		cfaPthread* p = lookup(_thread);
+		if (!p->isTerminated) return EBUSY; // thread not finished ?
+		join( *p );
+		if (value_ptr != NULL ) *value_ptr = p->joinval;
+		delete(p);
+		return 0;
+	}   //pthread_join_
+
+	pthread_t pthread_self(void) libcfa_public __THROW {
+		return (pthread_t)((char*)active_thread()-(sizeof(cfaPthread)-sizeof(thread$)));
+	}   //pthread_self_
+
+	void pthread_exit(void * status) libcfa_public __THROW {
+		pthread_t pid = pthread_self();
+		cfaPthread* _thread = (cfaPthread*)pid;
+		_thread->joinval = status;  // set return value
+		_thread->isTerminated = 1;  // set terminated flag
+		cancel_stack((pthread_exit_exp){&exp_vt});
+	}   //pthread_exit_
+
+	int pthread_yield( void ) __THROW {			// GNU extension
+		yield();
+		return 0;
+	}
+
+
+	//######################### Mutex #########################
+
+	int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t *attr) libcfa_public __THROW {
+		check_nonnull(_mutex);
+		init(_mutex);
+		return 0;
+	}   //pthread_mutex_init_
+
+
+	int pthread_mutex_destroy(pthread_mutex_t *_mutex) libcfa_public __THROW {
+		check_nonnull(_mutex);
+		simple_owner_lock* _lock = get(_mutex);
+		if (_lock->owner != NULL){
+			return EBUSY;
+		}
+		destroy(_mutex);
+		return 0;
+	}   //pthread_mutex_destroy_
+
+	int pthread_mutex_lock(pthread_mutex_t *_mutex) libcfa_public __THROW {
+		check_nonnull(_mutex);
+		mutex_check(_mutex);
+		simple_owner_lock* _lock = get(_mutex);
+		lock(*_lock);
+		return 0;
+	}   //pthread_mutex_lock_
+
+	int pthread_mutex_unlock(pthread_mutex_t *_mutex) libcfa_public __THROW {
+		check_nonnull(_mutex);
+		simple_owner_lock* _lock = get(_mutex);
+		if (_lock->owner != active_thread()){
+			return EPERM;
+		} // current thread does not hold the mutex
+		unlock(*_lock);
+		return 0;
+	}   //pthread_mutex_unlock_
+
+	int pthread_mutex_trylock(pthread_mutex_t *_mutex) libcfa_public __THROW {
+		check_nonnull(_mutex);
+		simple_owner_lock* _lock = get(_mutex);
+		if (_lock->owner != active_thread() && _lock->owner != NULL){
+			return EBUSY;
+		}   // if mutex is owned
+		lock(*_lock);
+		return 0;
+	}   //pthread_mutex_trylock_
+
+	//######################### Conditional Variable #########################
+
+	/* conditional variable routines */
+	int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) libcfa_public __THROW {
+		check_nonnull(cond);
+		init(cond);
+		return 0;
+	}  //pthread_cond_init
+
+	int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *_mutex) libcfa_public __THROW {
+		check_nonnull(_mutex);
+		check_nonnull(cond);
+		wait(*get(cond), *get(_mutex));
+		return 0;
+	} // pthread_cond_wait
+
+	int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * _mutex, const struct timespec * abstime) libcfa_public __THROW {
+		check_nonnull(_mutex);
+		check_nonnull(cond);
+		wait(*get(cond), *get(_mutex), *abstime);
+		return 0;
+	} // pthread_cond_timedwait
+
+	int pthread_cond_signal(pthread_cond_t *cond) libcfa_public __THROW {
+		check_nonnull(cond);
+		return notify_one(*get(cond));
+	} // pthread_cond_signal
+
+	int pthread_cond_broadcast(pthread_cond_t *cond) libcfa_public __THROW {
+		check_nonnull(cond);
+		return notify_all(*get(cond));
+	} // pthread_cond_broadcast
+
+	int pthread_cond_destroy(pthread_cond_t *cond) libcfa_public __THROW {
+		check_nonnull(cond);
+		destroy(cond);
+		return 0;
+	} // pthread_cond_destroy
+
+
+
+	//######################### Local storage #########################
+
+	int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) libcfa_public __THROW {
+		static_assert(sizeof(pthread_once_t) >= sizeof(int),"sizeof(pthread_once_t) < sizeof(int)");
+		check_nonnull(once_control);
+		check_nonnull(init_routine);
+		lock(once_lock);
+		if ( *((int *)once_control) == 0 ) {
+			init_routine();
+			*((int *)once_control) = 1;
+		} // if
+		unlock(once_lock);
+		return 0;
+	} // pthread_once
+
+	int pthread_key_create( pthread_key_t *key, void (*destructor)( void * ) ) libcfa_public __THROW {
+		lock(key_lock);
+		for ( int i = 0; i < PTHREAD_KEYS_MAX; i += 1 ) {
+			if ( ! cfa_pthread_keys[i].in_use ) {
+				cfa_pthread_keys[i].in_use = true;
+				cfa_pthread_keys[i].destructor = destructor;
+				unlock( key_lock );
+				*key = i;
+				return 0;
+			} // if
+		} // for
+		unlock(key_lock);
+		return EAGAIN;
+	}   // pthread_key_create
+
+	int pthread_key_delete( pthread_key_t key ) libcfa_public __THROW {
+		lock(key_lock);
+		if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) {
+			unlock( key_lock );
+			return EINVAL;
+		} // if
+		cfa_pthread_keys[key].in_use = false;
+		cfa_pthread_keys[key].destructor = NULL;
+
+		// Remove key from all threads with a value.
+		Pthread_values& p;
+		Sequence(Pthread_values)& head = cfa_pthread_keys[key].threads;
+		for ( SeqIter(Pthread_values) iter = { head }; iter | p; ) {
+			remove(head, p);
+			p.in_use = false;
+		}
+		unlock(key_lock);
+		return 0;
+	}   // pthread_key_delete
+
+	int pthread_setspecific( pthread_key_t key, const void *value ) libcfa_public __THROW {
+		// get current thread
+		cfaPthread* t = lookup(pthread_self());
+		// if current thread's pthreadData is NULL; initialize it
+		Pthread_values* values;
+		if (t->pthreadData == NULL){
+			values = anew( PTHREAD_KEYS_MAX);
+			t->pthreadData = values;
+			for (int i = 0;i < PTHREAD_KEYS_MAX; i++){
+				t->pthreadData[i].in_use = false;
+			}   // for
+		}   else {
+			values = t->pthreadData;
+		}   // if
+		// find corresponding key and set value
+		lock(key_lock);
+		// if invalid key
+		if ( key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use ) {
+			unlock( key_lock );
+			return EINVAL;
+		} // if
+		Pthread_values &entry = values[key];
+		if ( ! entry.in_use ) {
+			entry.in_use = true;
+			add(cfa_pthread_keys[key].threads, entry);
+		} // if
+		entry.value = (void *)value;
+		unlock(key_lock);
+		return 0;
+	} //pthread_setspecific
+
+	void* pthread_getspecific(pthread_key_t key) libcfa_public __THROW {
+		if (key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use) return NULL;
+
+		// get current thread
+		cfaPthread* t = lookup(pthread_self());
+		if (t->pthreadData == NULL) return NULL;
+		lock(key_lock);
+		Pthread_values &entry = ((Pthread_values *)t->pthreadData)[key];
+		if ( ! entry.in_use ) {
+			unlock( key_lock );
+			return NULL;
+		} // if
+		void *value = entry.value;
+		unlock(key_lock);
+
+		return value;
+	}   //pthread_get_specific
+
+	//######################### Parallelism #########################
+	void pthread_delete_kernel_threads_() libcfa_public __THROW {	// see uMain::~uMain
+		Pthread_kernel_threads& p;
+		for ( StackIter(Pthread_kernel_threads) iter = {cfa_pthreads_kernel_threads}; iter | p; ) {
+			delete(&p);
+		} // for
+	} // pthread_delete_kernel_threads_
+
+	int pthread_getconcurrency( void ) libcfa_public __THROW {	// XOPEN extension
+		return cfa_pthreads_kernel_threads_zero ? 0 : cfa_pthreads_no_kernel_threads;
+	} // pthread_getconcurrency
+
+	int pthread_setconcurrency( int new_level ) libcfa_public __THROW { // XOPEN extension
+	  if ( new_level < 0 ) return EINVAL;
+	  if ( new_level == 0 ) {
+		cfa_pthreads_kernel_threads_zero = true;	// remember set to zero, but ignore
+		return 0;					// do not do kernel thread management
+	  } // exit
+	  cfa_pthreads_kernel_threads_zero = false;
+	  lock( concurrency_lock );
+	  for ( ; new_level > cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads += 1 ) { // add processors ?
+		push(cfa_pthreads_kernel_threads, *new() );
+	  } // for
+	  for ( ; new_level < cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads -= 1 ) { // remove processors ?
+		delete(&pop(cfa_pthreads_kernel_threads));
+	  } // for
+	  unlock( concurrency_lock );
+	  return 0;
+	} // pthread_setconcurrency
+
+	//######################### Signal #########################
+
+
+	 int pthread_sigmask( int /* how */, const sigset_t * /* set */, sigset_t * /* oset */ ) libcfa_public __THROW {
+		 return 0;
+	 } // pthread_sigmask
+
+	int pthread_kill( pthread_t _thread __attribute__(( unused )), int sig ) libcfa_public __THROW {
+		if ( sig == 0 ) {
+			return 0;
+		} else {
+			abort( "pthread_kill : not implemented" );
+		} // if
+		return 0;
+	} // pthread_kill
+
+	int pthread_sigqueue(pthread_t , int sig, const union sigval) libcfa_public __THROW {
+		return 0;
+	} // pthread_sigqueue
+
+	//######################### Scheduling #########################
+	int pthread_detach( pthread_t threadID ) __THROW {
+		abort( "pthread_detach" );
+		return 0;
+	} // pthread_detach
+
+	int pthread_setschedparam( pthread_t /* thread */, int /* policy */, const struct sched_param * /* param */ ) libcfa_public __THROW {
+		abort( "pthread_setschedparam : not implemented" );
+		return 0;
+	} // pthread_setschedparam
+
+	int pthread_getschedparam( pthread_t /* thread */, int */* policy */, struct sched_param * /* param */ ) libcfa_public __THROW {
+		abort( "pthread_getschedparam : not implemented" );
+		return 0;
+	} // pthread_getschedparam
+
+	 //######################### Mutex Attr #########################
+
+	int pthread_mutexattr_init( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW {
+		return 0;
+	} // pthread_mutexattr_init
+
+	int pthread_mutexattr_destroy( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_destroy
+
+	int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_setpshared
+
+	int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_getpshared
+
+	int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_setprotocol
+
+	int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_getprotocol
+
+	int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_setprioceiling
+
+	int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_getprioceiling
+
+	int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutex_setprioceiling
+
+	int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutex_getprioceiling
+
+	int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_gettype
+
+	int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW {
+	return 0;
+	} // pthread_mutexattr_settype
+
+	//######################### Mutex #########################
+
+	int pthread_mutex_timedlock( pthread_mutex_t *__restrict /* __mutex */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
+		abort( "pthread_mutex_timedlock" );
+	} // pthread_mutex_timedlock
+
+	//######################### Condition #########################
+
+	int pthread_condattr_getclock( __const pthread_condattr_t * __restrict /* __attr */, __clockid_t *__restrict /* __clock_id */ ) libcfa_public __THROW {
+		abort( "pthread_condattr_getclock" );
+	} // pthread_condattr_getclock
+
+	int pthread_condattr_setclock( pthread_condattr_t * /* __attr */, __clockid_t /* __clock_id */ ) libcfa_public __THROW {
+		abort( "pthread_condattr_setclock" );
+	} // pthread_condattr_setclock
+
+	//######################### Spinlock #########################
+
+	int pthread_spin_init( pthread_spinlock_t * /* __lock */, int /*__pshared */ ) libcfa_public __THROW {
+		abort( "pthread_spin_init" );
+	} // pthread_spin_init
+
+	int pthread_spin_destroy( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
+		abort( "pthread_spin_destroy" );
+	} // pthread_spin_destroy
+
+	int pthread_spin_lock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
+		abort( "pthread_spin_lock" );
+	} // pthread_spin_lock
+
+	int pthread_spin_trylock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
+		abort( "pthread_spin_trylock" );
+	} // pthread_spin_trylock
+
+	int pthread_spin_unlock( pthread_spinlock_t * /* __lock */ ) libcfa_public __THROW {
+		abort( "pthread_spin_unlock" );
+	} // pthread_spin_unlock
+
+	//######################### Barrier #########################
+
+	int pthread_barrier_init( pthread_barrier_t *__restrict /* __barrier */, __const pthread_barrierattr_t *__restrict /* __attr */, unsigned int /* __count */ ) libcfa_public __THROW {
+		abort( "pthread_barrier_init" );
+	} // pthread_barrier_init
+
+	int pthread_barrier_destroy( pthread_barrier_t * /* __barrier */ ) libcfa_public  __THROW {
+		abort( "pthread_barrier_destroy" );
+	} // pthread_barrier_destroy
+
+	int pthread_barrier_wait( pthread_barrier_t * /* __barrier */ ) libcfa_public __THROW {
+		abort( "pthread_barrier_wait" );
+	} // pthread_barrier_wait
+
+	int pthread_barrierattr_init( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
+		abort( "pthread_barrierattr_init" );
+	} // pthread_barrierattr_init
+
+	int pthread_barrierattr_destroy( pthread_barrierattr_t * /* __attr */ ) libcfa_public __THROW {
+		abort( "pthread_barrierattr_destroy" );
+	} // pthread_barrierattr_destroy
+
+	int pthread_barrierattr_getpshared( __const pthread_barrierattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW {
+		abort( "pthread_barrierattr_getpshared" );
+	} // pthread_barrierattr_getpshared
+
+	int pthread_barrierattr_setpshared( pthread_barrierattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
+		abort( "pthread_barrierattr_setpshared" );
+	} // pthread_barrierattr_setpshared
+
+	//######################### Clock #########################
+
+	int pthread_getcpuclockid( pthread_t /* __thread_id */, __clockid_t * /* __clock_id */ ) libcfa_public __THROW {
+		abort( "pthread_getcpuclockid" );
+	} // pthread_getcpuclockid
+
+	// pthread_atfork()
+
+// UNIX98
+
+	//######################### Read/Write #########################
+
+	int pthread_rwlock_init( pthread_rwlock_t *__restrict /* __rwlock */, __const pthread_rwlockattr_t *__restrict /* __attr */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_init" );
+	} // pthread_rwlock_init
+
+	int pthread_rwlock_destroy( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_destroy" );
+	} // pthread_rwlock_destroy
+
+	int pthread_rwlock_rdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_rdlock" );
+	} // pthread_rwlock_rdlock
+
+	int pthread_rwlock_tryrdlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_tryrdlock" );
+	} // pthread_rwlock_tryrdlock
+
+	int pthread_rwlock_wrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_wrlock" );
+	} // pthread_rwlock_wrlock
+
+	int pthread_rwlock_trywrlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_trywrlock" );
+	} // pthread_rwlock_trywrlock
+
+	int pthread_rwlock_unlock( pthread_rwlock_t * /* __rwlock */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_unlock" );
+	} // pthread_rwlock_unlock
+
+	int pthread_rwlockattr_init( pthread_rwlockattr_t * /* __attr */ ) libcfa_public __THROW {
+		abort( "pthread_rwlockattr_init" );
+	} // pthread_rwlockattr_init
+
+	int pthread_rwlockattr_destroy( pthread_rwlockattr_t * /*__attr */ ) libcfa_public __THROW {
+		abort( "pthread_rwlockattr_destroy" );
+	} // pthread_rwlockattr_destroy
+
+	int pthread_rwlockattr_getpshared( __const pthread_rwlockattr_t * __restrict /* __attr */, int *__restrict /* __pshared */ ) libcfa_public __THROW {
+		abort( "pthread_rwlockattr_getpshared" );
+	} // pthread_rwlockattr_getpshared
+
+	int pthread_rwlockattr_setpshared( pthread_rwlockattr_t * /* __attr */, int /* __pshared */ ) libcfa_public __THROW {
+		abort( "pthread_rwlockattr_setpshared" );
+	} // pthread_rwlockattr_setpshared
+
+	int pthread_rwlockattr_getkind_np( __const pthread_rwlockattr_t * /* __attr */, int * /* __pref */ ) libcfa_public __THROW {
+		abort( "pthread_rwlockattr_getkind_np" );
+	} // pthread_rwlockattr_getkind_np
+
+	int pthread_rwlockattr_setkind_np( pthread_rwlockattr_t * /* __attr */, int /* __pref */ ) libcfa_public __THROW {
+		abort( "pthread_rwlockattr_setkind_np" );
+	} // pthread_rwlockattr_setkind_np
+
+// UNIX98 + XOPEN
+
+	int pthread_rwlock_timedrdlock( pthread_rwlock_t *__restrict  /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_timedrdlock" );
+	} // pthread_rwlock_timedrdlock
+
+	int pthread_rwlock_timedwrlock( pthread_rwlock_t *__restrict  /* __rwlock */, __const struct timespec *__restrict /* __abstime */ ) libcfa_public __THROW {
+		abort( "pthread_rwlock_timedwrlock" );
+	} // pthread_rwlock_timedwrlock
+
+// GNU
+
+	//######################### Parallelism #########################
+
+	int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
+		abort( "pthread_setaffinity_np" );
+	} // pthread_setaffinity_np
+
+	int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
+		abort( "pthread_getaffinity_np" );
+	} // pthread_getaffinity_np
+
+	int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
+		abort( "pthread_attr_setaffinity_np" );
+	} // pthread_attr_setaffinity_np
+
+	int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
+		abort( "pthread_attr_getaffinity_np" );
+	} // pthread_attr_getaffinity_np
+
+	//######################### Cancellation #########################
+
+	void _pthread_cleanup_push_defer( struct _pthread_cleanup_buffer * /* __buffer */, void( * /* __routine */ )( void * ), void * /* __arg */ ) libcfa_public __THROW {
+		abort( "_pthread_cleanup_push_defer" );
+	} // _pthread_cleanup_push_defer
+
+	void _pthread_cleanup_pop_restore( struct _pthread_cleanup_buffer * /* __buffer */, int /* __execute */ ) libcfa_public __THROW {
+		abort( "_pthread_cleanup_pop_restore" );
+	} // _pthread_cleanup_pop_res
+
+	int pthread_cancel( pthread_t threadID ) libcfa_public __THROW {
+		abort("pthread cancel not implemented");
+		return 0;
+	} // pthread_cancel
+
+	int pthread_setcancelstate( int state, int *oldstate ) libcfa_public __THROW {
+		abort("pthread_setcancelstate not implemented");
+		return 0;
+	} // pthread_setcancelstate
+
+	int pthread_setcanceltype( int type, int *oldtype ) libcfa_public __THROW {
+		abort("pthread_setcanceltype not implemented");
+		return 0;
+	} // pthread_setcanceltype
+} // extern "C"
+
+#pragma GCC diagnostic pop
+
Index: libcfa/src/interpose.cfa
===================================================================
--- libcfa/src/interpose.cfa	(revision bc899d6a44ef2923a2bd54f336bb656b8624bc30)
+++ libcfa/src/interpose.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -42,8 +42,30 @@
 
 typedef void (* generic_fptr_t)(void);
+static generic_fptr_t do_interpose_symbol( void * library, const char symbol[], const char version[] ) {
+	const char * error;
+
+	union { generic_fptr_t fptr; void * ptr; } originalFunc;
+
+	#if defined( _GNU_SOURCE )
+		if ( version ) {
+			originalFunc.ptr = dlvsym( library, symbol, version );
+		} else {
+			originalFunc.ptr = dlsym( library, symbol );
+		}
+	#else
+		originalFunc.ptr = dlsym( library, symbol );
+	#endif // _GNU_SOURCE
+
+	error = dlerror();
+	if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
+
+	return originalFunc.fptr;
+}
+
 static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
 	const char * error;
 
 	static void * library;
+	static void * pthread_library;
 	if ( ! library ) {
 		#if defined( RTLD_NEXT )
@@ -58,21 +80,18 @@
 		#endif
 	} // if
-
-	union { generic_fptr_t fptr; void * ptr; } originalFunc;
-
-	#if defined( _GNU_SOURCE )
-		if ( version ) {
-			originalFunc.ptr = dlvsym( library, symbol, version );
-		} else {
-			originalFunc.ptr = dlsym( library, symbol );
-		}
-	#else
-		originalFunc.ptr = dlsym( library, symbol );
-	#endif // _GNU_SOURCE
-
-	error = dlerror();
-	if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
-
-	return originalFunc.fptr;
+	if ( ! pthread_library ) {
+		#if defined( RTLD_NEXT )
+			pthread_library = RTLD_NEXT;
+		#else
+			// missing RTLD_NEXT => must hard-code library name, assuming libstdc++
+			pthread_library = dlopen( "libpthread.so", RTLD_LAZY );
+			error = dlerror();
+			if ( error ) {
+				abort( "interpose_symbol : failed to open libpthread, %s\n", error );
+			}
+		#endif
+	} // if
+
+	return do_interpose_symbol(library, symbol, version);
 }
 
@@ -97,4 +116,5 @@
 
 extern "C" {
+	void __cfathreadabi_interpose_startup( generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ) ) __attribute__((weak));
 	void __cfaabi_interpose_startup( void ) {
 		const char *version = 0p;
@@ -108,4 +128,6 @@
 		INTERPOSE_LIBC( exit , version );
 #pragma GCC diagnostic pop
+
+		if(__cfathreadabi_interpose_startup) __cfathreadabi_interpose_startup( do_interpose_symbol );
 
 		// As a precaution (and necessity), errors that result in termination are delivered on a separate stack because
Index: libcfa/src/interpose_thread.cfa
===================================================================
--- libcfa/src/interpose_thread.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ libcfa/src/interpose_thread.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,125 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// interpose_thread.c --
+//
+// Author           : Thierry Delisle
+// Created On       : Wed Sep 21 11:55:16 2022
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include <stdarg.h>										// va_start, va_end
+#include <stdio.h>
+#include <string.h>										// strlen
+#include <signal.h>
+#include <pthread.h>
+extern "C" {
+#include <dlfcn.h>										// dlopen, dlsym
+#include <execinfo.h>									// backtrace, messages
+}
+
+#include "bits/debug.hfa"
+#include "bits/defs.hfa"
+#include <assert.h>
+
+//=============================================================================================
+// Interposing helpers
+//=============================================================================================
+
+typedef void (* generic_fptr_t)(void);
+
+generic_fptr_t interpose_symbol(
+	generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ),
+	const char symbol[],
+	const char version[]
+) libcfa_public {
+	const char * error;
+
+	static void * library;
+	if ( ! library ) {
+		#if defined( RTLD_NEXT )
+			library = RTLD_NEXT;
+		#else
+			// missing RTLD_NEXT => must hard-code library name, assuming libstdc++
+			library = dlopen( "libpthread.so", RTLD_LAZY );
+			error = dlerror();
+			if ( error ) {
+				abort( "interpose_symbol : failed to open libpthread, %s\n", error );
+			}
+		#endif
+	} // if
+
+	return do_interpose_symbol(library, symbol, version);
+}
+
+#define INTERPOSE( x, ver ) __cabi_libpthread.x = (typeof(__cabi_libpthread.x))interpose_symbol( do_interpose_symbol, #x, ver )
+
+//=============================================================================================
+// Interposition Startup logic
+//=============================================================================================
+
+static struct {
+	int (*pthread_create)(pthread_t *_thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
+	int (*pthread_join)(pthread_t _thread, void **retval);
+	pthread_t (*pthread_self)(void);
+	int (*pthread_attr_init)(pthread_attr_t *attr);
+	int (*pthread_attr_destroy)(pthread_attr_t *attr);
+	int (*pthread_attr_setstack)( pthread_attr_t *attr, void *stackaddr, size_t stacksize );
+	int (*pthread_attr_getstacksize)( const pthread_attr_t *attr, size_t *stacksize );
+	int (*pthread_sigmask)(int how, const sigset_t *set, sigset_t *oldset);
+	int (*pthread_sigqueue)(pthread_t _thread, int sig, const union sigval value);
+} __cabi_libpthread;
+
+extern "C" {
+	void __cfathreadabi_interpose_startup( generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ) ) libcfa_public {
+		const char *version = 0p;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
+		INTERPOSE( pthread_create , version );
+		INTERPOSE( pthread_join , version );
+		INTERPOSE( pthread_self , version );
+		INTERPOSE( pthread_attr_init , version );
+		INTERPOSE( pthread_attr_destroy , version );
+		INTERPOSE( pthread_attr_setstack , version );
+		INTERPOSE( pthread_attr_getstacksize , version );
+		INTERPOSE( pthread_sigmask , version );
+		INTERPOSE( pthread_sigqueue , version );
+#pragma GCC diagnostic pop
+	}
+
+	int __cfaabi_pthread_create(pthread_t *_thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg){
+		return __cabi_libpthread.pthread_create(_thread, attr, start_routine, arg);
+	}
+
+	int __cfaabi_pthread_join(pthread_t _thread, void **retval){
+		return __cabi_libpthread.pthread_join(_thread, retval);
+	}
+
+	pthread_t __cfaabi_pthread_self(void){
+		return __cabi_libpthread.pthread_self();
+	}
+	int __cfaabi_pthread_attr_init(pthread_attr_t *attr){
+		return __cabi_libpthread.pthread_attr_init(attr);
+	}
+	int __cfaabi_pthread_attr_destroy(pthread_attr_t *attr){
+		return __cabi_libpthread.pthread_attr_destroy(attr);
+	}
+	int __cfaabi_pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize ){
+		return __cabi_libpthread.pthread_attr_setstack(attr, stackaddr, stacksize);
+	}
+	int read_pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize ){
+		return __cabi_libpthread.pthread_attr_getstacksize(attr, stacksize);
+	}
+	int __cfaabi_pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset){
+		return __cabi_libpthread.pthread_sigmask(how, set, oldset);
+	}
+	int __cfaabi_pthread_sigqueue(pthread_t _thread, int sig, const union sigval value){
+		return __cabi_libpthread.pthread_sigqueue(_thread, sig, value);
+	}
+}
Index: tests/concurrent/pthread/.expect/bounded_buffer.txt
===================================================================
--- tests/concurrent/pthread/.expect/bounded_buffer.txt	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/.expect/bounded_buffer.txt	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,2 @@
+producer total value is 23426
+consumer total value is 23426
Index: tests/concurrent/pthread/.expect/pthread_attr_test.txt
===================================================================
--- tests/concurrent/pthread/.expect/pthread_attr_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/.expect/pthread_attr_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,1 @@
+stack size is 123456789
Index: tests/concurrent/pthread/.expect/pthread_cond_test.txt
===================================================================
--- tests/concurrent/pthread/.expect/pthread_cond_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/.expect/pthread_cond_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,1001 @@
+S1 done 0
+S1 done 1
+S1 done 2
+S1 done 3
+S1 done 4
+S1 done 5
+S1 done 6
+S1 done 7
+S1 done 8
+S1 done 9
+S1 done 10
+S1 done 11
+S1 done 12
+S1 done 13
+S1 done 14
+S1 done 15
+S1 done 16
+S1 done 17
+S1 done 18
+S1 done 19
+S1 done 20
+S1 done 21
+S1 done 22
+S1 done 23
+S1 done 24
+S1 done 25
+S1 done 26
+S1 done 27
+S1 done 28
+S1 done 29
+S1 done 30
+S1 done 31
+S1 done 32
+S1 done 33
+S1 done 34
+S1 done 35
+S1 done 36
+S1 done 37
+S1 done 38
+S1 done 39
+S1 done 40
+S1 done 41
+S1 done 42
+S1 done 43
+S1 done 44
+S1 done 45
+S1 done 46
+S1 done 47
+S1 done 48
+S1 done 49
+S1 done 50
+S1 done 51
+S1 done 52
+S1 done 53
+S1 done 54
+S1 done 55
+S1 done 56
+S1 done 57
+S1 done 58
+S1 done 59
+S1 done 60
+S1 done 61
+S1 done 62
+S1 done 63
+S1 done 64
+S1 done 65
+S1 done 66
+S1 done 67
+S1 done 68
+S1 done 69
+S1 done 70
+S1 done 71
+S1 done 72
+S1 done 73
+S1 done 74
+S1 done 75
+S1 done 76
+S1 done 77
+S1 done 78
+S1 done 79
+S1 done 80
+S1 done 81
+S1 done 82
+S1 done 83
+S1 done 84
+S1 done 85
+S1 done 86
+S1 done 87
+S1 done 88
+S1 done 89
+S1 done 90
+S1 done 91
+S1 done 92
+S1 done 93
+S1 done 94
+S1 done 95
+S1 done 96
+S1 done 97
+S1 done 98
+S1 done 99
+S1 done 100
+S1 done 101
+S1 done 102
+S1 done 103
+S1 done 104
+S1 done 105
+S1 done 106
+S1 done 107
+S1 done 108
+S1 done 109
+S1 done 110
+S1 done 111
+S1 done 112
+S1 done 113
+S1 done 114
+S1 done 115
+S1 done 116
+S1 done 117
+S1 done 118
+S1 done 119
+S1 done 120
+S1 done 121
+S1 done 122
+S1 done 123
+S1 done 124
+S1 done 125
+S1 done 126
+S1 done 127
+S1 done 128
+S1 done 129
+S1 done 130
+S1 done 131
+S1 done 132
+S1 done 133
+S1 done 134
+S1 done 135
+S1 done 136
+S1 done 137
+S1 done 138
+S1 done 139
+S1 done 140
+S1 done 141
+S1 done 142
+S1 done 143
+S1 done 144
+S1 done 145
+S1 done 146
+S1 done 147
+S1 done 148
+S1 done 149
+S1 done 150
+S1 done 151
+S1 done 152
+S1 done 153
+S1 done 154
+S1 done 155
+S1 done 156
+S1 done 157
+S1 done 158
+S1 done 159
+S1 done 160
+S1 done 161
+S1 done 162
+S1 done 163
+S1 done 164
+S1 done 165
+S1 done 166
+S1 done 167
+S1 done 168
+S1 done 169
+S1 done 170
+S1 done 171
+S1 done 172
+S1 done 173
+S1 done 174
+S1 done 175
+S1 done 176
+S1 done 177
+S1 done 178
+S1 done 179
+S1 done 180
+S1 done 181
+S1 done 182
+S1 done 183
+S1 done 184
+S1 done 185
+S1 done 186
+S1 done 187
+S1 done 188
+S1 done 189
+S1 done 190
+S1 done 191
+S1 done 192
+S1 done 193
+S1 done 194
+S1 done 195
+S1 done 196
+S1 done 197
+S1 done 198
+S1 done 199
+S1 done 200
+S1 done 201
+S1 done 202
+S1 done 203
+S1 done 204
+S1 done 205
+S1 done 206
+S1 done 207
+S1 done 208
+S1 done 209
+S1 done 210
+S1 done 211
+S1 done 212
+S1 done 213
+S1 done 214
+S1 done 215
+S1 done 216
+S1 done 217
+S1 done 218
+S1 done 219
+S1 done 220
+S1 done 221
+S1 done 222
+S1 done 223
+S1 done 224
+S1 done 225
+S1 done 226
+S1 done 227
+S1 done 228
+S1 done 229
+S1 done 230
+S1 done 231
+S1 done 232
+S1 done 233
+S1 done 234
+S1 done 235
+S1 done 236
+S1 done 237
+S1 done 238
+S1 done 239
+S1 done 240
+S1 done 241
+S1 done 242
+S1 done 243
+S1 done 244
+S1 done 245
+S1 done 246
+S1 done 247
+S1 done 248
+S1 done 249
+S1 done 250
+S1 done 251
+S1 done 252
+S1 done 253
+S1 done 254
+S1 done 255
+S1 done 256
+S1 done 257
+S1 done 258
+S1 done 259
+S1 done 260
+S1 done 261
+S1 done 262
+S1 done 263
+S1 done 264
+S1 done 265
+S1 done 266
+S1 done 267
+S1 done 268
+S1 done 269
+S1 done 270
+S1 done 271
+S1 done 272
+S1 done 273
+S1 done 274
+S1 done 275
+S1 done 276
+S1 done 277
+S1 done 278
+S1 done 279
+S1 done 280
+S1 done 281
+S1 done 282
+S1 done 283
+S1 done 284
+S1 done 285
+S1 done 286
+S1 done 287
+S1 done 288
+S1 done 289
+S1 done 290
+S1 done 291
+S1 done 292
+S1 done 293
+S1 done 294
+S1 done 295
+S1 done 296
+S1 done 297
+S1 done 298
+S1 done 299
+S1 done 300
+S1 done 301
+S1 done 302
+S1 done 303
+S1 done 304
+S1 done 305
+S1 done 306
+S1 done 307
+S1 done 308
+S1 done 309
+S1 done 310
+S1 done 311
+S1 done 312
+S1 done 313
+S1 done 314
+S1 done 315
+S1 done 316
+S1 done 317
+S1 done 318
+S1 done 319
+S1 done 320
+S1 done 321
+S1 done 322
+S1 done 323
+S1 done 324
+S1 done 325
+S1 done 326
+S1 done 327
+S1 done 328
+S1 done 329
+S1 done 330
+S1 done 331
+S1 done 332
+S1 done 333
+S1 done 334
+S1 done 335
+S1 done 336
+S1 done 337
+S1 done 338
+S1 done 339
+S1 done 340
+S1 done 341
+S1 done 342
+S1 done 343
+S1 done 344
+S1 done 345
+S1 done 346
+S1 done 347
+S1 done 348
+S1 done 349
+S1 done 350
+S1 done 351
+S1 done 352
+S1 done 353
+S1 done 354
+S1 done 355
+S1 done 356
+S1 done 357
+S1 done 358
+S1 done 359
+S1 done 360
+S1 done 361
+S1 done 362
+S1 done 363
+S1 done 364
+S1 done 365
+S1 done 366
+S1 done 367
+S1 done 368
+S1 done 369
+S1 done 370
+S1 done 371
+S1 done 372
+S1 done 373
+S1 done 374
+S1 done 375
+S1 done 376
+S1 done 377
+S1 done 378
+S1 done 379
+S1 done 380
+S1 done 381
+S1 done 382
+S1 done 383
+S1 done 384
+S1 done 385
+S1 done 386
+S1 done 387
+S1 done 388
+S1 done 389
+S1 done 390
+S1 done 391
+S1 done 392
+S1 done 393
+S1 done 394
+S1 done 395
+S1 done 396
+S1 done 397
+S1 done 398
+S1 done 399
+S1 done 400
+S1 done 401
+S1 done 402
+S1 done 403
+S1 done 404
+S1 done 405
+S1 done 406
+S1 done 407
+S1 done 408
+S1 done 409
+S1 done 410
+S1 done 411
+S1 done 412
+S1 done 413
+S1 done 414
+S1 done 415
+S1 done 416
+S1 done 417
+S1 done 418
+S1 done 419
+S1 done 420
+S1 done 421
+S1 done 422
+S1 done 423
+S1 done 424
+S1 done 425
+S1 done 426
+S1 done 427
+S1 done 428
+S1 done 429
+S1 done 430
+S1 done 431
+S1 done 432
+S1 done 433
+S1 done 434
+S1 done 435
+S1 done 436
+S1 done 437
+S1 done 438
+S1 done 439
+S1 done 440
+S1 done 441
+S1 done 442
+S1 done 443
+S1 done 444
+S1 done 445
+S1 done 446
+S1 done 447
+S1 done 448
+S1 done 449
+S1 done 450
+S1 done 451
+S1 done 452
+S1 done 453
+S1 done 454
+S1 done 455
+S1 done 456
+S1 done 457
+S1 done 458
+S1 done 459
+S1 done 460
+S1 done 461
+S1 done 462
+S1 done 463
+S1 done 464
+S1 done 465
+S1 done 466
+S1 done 467
+S1 done 468
+S1 done 469
+S1 done 470
+S1 done 471
+S1 done 472
+S1 done 473
+S1 done 474
+S1 done 475
+S1 done 476
+S1 done 477
+S1 done 478
+S1 done 479
+S1 done 480
+S1 done 481
+S1 done 482
+S1 done 483
+S1 done 484
+S1 done 485
+S1 done 486
+S1 done 487
+S1 done 488
+S1 done 489
+S1 done 490
+S1 done 491
+S1 done 492
+S1 done 493
+S1 done 494
+S1 done 495
+S1 done 496
+S1 done 497
+S1 done 498
+S1 done 499
+S1 done 500
+S1 done 501
+S1 done 502
+S1 done 503
+S1 done 504
+S1 done 505
+S1 done 506
+S1 done 507
+S1 done 508
+S1 done 509
+S1 done 510
+S1 done 511
+S1 done 512
+S1 done 513
+S1 done 514
+S1 done 515
+S1 done 516
+S1 done 517
+S1 done 518
+S1 done 519
+S1 done 520
+S1 done 521
+S1 done 522
+S1 done 523
+S1 done 524
+S1 done 525
+S1 done 526
+S1 done 527
+S1 done 528
+S1 done 529
+S1 done 530
+S1 done 531
+S1 done 532
+S1 done 533
+S1 done 534
+S1 done 535
+S1 done 536
+S1 done 537
+S1 done 538
+S1 done 539
+S1 done 540
+S1 done 541
+S1 done 542
+S1 done 543
+S1 done 544
+S1 done 545
+S1 done 546
+S1 done 547
+S1 done 548
+S1 done 549
+S1 done 550
+S1 done 551
+S1 done 552
+S1 done 553
+S1 done 554
+S1 done 555
+S1 done 556
+S1 done 557
+S1 done 558
+S1 done 559
+S1 done 560
+S1 done 561
+S1 done 562
+S1 done 563
+S1 done 564
+S1 done 565
+S1 done 566
+S1 done 567
+S1 done 568
+S1 done 569
+S1 done 570
+S1 done 571
+S1 done 572
+S1 done 573
+S1 done 574
+S1 done 575
+S1 done 576
+S1 done 577
+S1 done 578
+S1 done 579
+S1 done 580
+S1 done 581
+S1 done 582
+S1 done 583
+S1 done 584
+S1 done 585
+S1 done 586
+S1 done 587
+S1 done 588
+S1 done 589
+S1 done 590
+S1 done 591
+S1 done 592
+S1 done 593
+S1 done 594
+S1 done 595
+S1 done 596
+S1 done 597
+S1 done 598
+S1 done 599
+S1 done 600
+S1 done 601
+S1 done 602
+S1 done 603
+S1 done 604
+S1 done 605
+S1 done 606
+S1 done 607
+S1 done 608
+S1 done 609
+S1 done 610
+S1 done 611
+S1 done 612
+S1 done 613
+S1 done 614
+S1 done 615
+S1 done 616
+S1 done 617
+S1 done 618
+S1 done 619
+S1 done 620
+S1 done 621
+S1 done 622
+S1 done 623
+S1 done 624
+S1 done 625
+S1 done 626
+S1 done 627
+S1 done 628
+S1 done 629
+S1 done 630
+S1 done 631
+S1 done 632
+S1 done 633
+S1 done 634
+S1 done 635
+S1 done 636
+S1 done 637
+S1 done 638
+S1 done 639
+S1 done 640
+S1 done 641
+S1 done 642
+S1 done 643
+S1 done 644
+S1 done 645
+S1 done 646
+S1 done 647
+S1 done 648
+S1 done 649
+S1 done 650
+S1 done 651
+S1 done 652
+S1 done 653
+S1 done 654
+S1 done 655
+S1 done 656
+S1 done 657
+S1 done 658
+S1 done 659
+S1 done 660
+S1 done 661
+S1 done 662
+S1 done 663
+S1 done 664
+S1 done 665
+S1 done 666
+S1 done 667
+S1 done 668
+S1 done 669
+S1 done 670
+S1 done 671
+S1 done 672
+S1 done 673
+S1 done 674
+S1 done 675
+S1 done 676
+S1 done 677
+S1 done 678
+S1 done 679
+S1 done 680
+S1 done 681
+S1 done 682
+S1 done 683
+S1 done 684
+S1 done 685
+S1 done 686
+S1 done 687
+S1 done 688
+S1 done 689
+S1 done 690
+S1 done 691
+S1 done 692
+S1 done 693
+S1 done 694
+S1 done 695
+S1 done 696
+S1 done 697
+S1 done 698
+S1 done 699
+S1 done 700
+S1 done 701
+S1 done 702
+S1 done 703
+S1 done 704
+S1 done 705
+S1 done 706
+S1 done 707
+S1 done 708
+S1 done 709
+S1 done 710
+S1 done 711
+S1 done 712
+S1 done 713
+S1 done 714
+S1 done 715
+S1 done 716
+S1 done 717
+S1 done 718
+S1 done 719
+S1 done 720
+S1 done 721
+S1 done 722
+S1 done 723
+S1 done 724
+S1 done 725
+S1 done 726
+S1 done 727
+S1 done 728
+S1 done 729
+S1 done 730
+S1 done 731
+S1 done 732
+S1 done 733
+S1 done 734
+S1 done 735
+S1 done 736
+S1 done 737
+S1 done 738
+S1 done 739
+S1 done 740
+S1 done 741
+S1 done 742
+S1 done 743
+S1 done 744
+S1 done 745
+S1 done 746
+S1 done 747
+S1 done 748
+S1 done 749
+S1 done 750
+S1 done 751
+S1 done 752
+S1 done 753
+S1 done 754
+S1 done 755
+S1 done 756
+S1 done 757
+S1 done 758
+S1 done 759
+S1 done 760
+S1 done 761
+S1 done 762
+S1 done 763
+S1 done 764
+S1 done 765
+S1 done 766
+S1 done 767
+S1 done 768
+S1 done 769
+S1 done 770
+S1 done 771
+S1 done 772
+S1 done 773
+S1 done 774
+S1 done 775
+S1 done 776
+S1 done 777
+S1 done 778
+S1 done 779
+S1 done 780
+S1 done 781
+S1 done 782
+S1 done 783
+S1 done 784
+S1 done 785
+S1 done 786
+S1 done 787
+S1 done 788
+S1 done 789
+S1 done 790
+S1 done 791
+S1 done 792
+S1 done 793
+S1 done 794
+S1 done 795
+S1 done 796
+S1 done 797
+S1 done 798
+S1 done 799
+S1 done 800
+S1 done 801
+S1 done 802
+S1 done 803
+S1 done 804
+S1 done 805
+S1 done 806
+S1 done 807
+S1 done 808
+S1 done 809
+S1 done 810
+S1 done 811
+S1 done 812
+S1 done 813
+S1 done 814
+S1 done 815
+S1 done 816
+S1 done 817
+S1 done 818
+S1 done 819
+S1 done 820
+S1 done 821
+S1 done 822
+S1 done 823
+S1 done 824
+S1 done 825
+S1 done 826
+S1 done 827
+S1 done 828
+S1 done 829
+S1 done 830
+S1 done 831
+S1 done 832
+S1 done 833
+S1 done 834
+S1 done 835
+S1 done 836
+S1 done 837
+S1 done 838
+S1 done 839
+S1 done 840
+S1 done 841
+S1 done 842
+S1 done 843
+S1 done 844
+S1 done 845
+S1 done 846
+S1 done 847
+S1 done 848
+S1 done 849
+S1 done 850
+S1 done 851
+S1 done 852
+S1 done 853
+S1 done 854
+S1 done 855
+S1 done 856
+S1 done 857
+S1 done 858
+S1 done 859
+S1 done 860
+S1 done 861
+S1 done 862
+S1 done 863
+S1 done 864
+S1 done 865
+S1 done 866
+S1 done 867
+S1 done 868
+S1 done 869
+S1 done 870
+S1 done 871
+S1 done 872
+S1 done 873
+S1 done 874
+S1 done 875
+S1 done 876
+S1 done 877
+S1 done 878
+S1 done 879
+S1 done 880
+S1 done 881
+S1 done 882
+S1 done 883
+S1 done 884
+S1 done 885
+S1 done 886
+S1 done 887
+S1 done 888
+S1 done 889
+S1 done 890
+S1 done 891
+S1 done 892
+S1 done 893
+S1 done 894
+S1 done 895
+S1 done 896
+S1 done 897
+S1 done 898
+S1 done 899
+S1 done 900
+S1 done 901
+S1 done 902
+S1 done 903
+S1 done 904
+S1 done 905
+S1 done 906
+S1 done 907
+S1 done 908
+S1 done 909
+S1 done 910
+S1 done 911
+S1 done 912
+S1 done 913
+S1 done 914
+S1 done 915
+S1 done 916
+S1 done 917
+S1 done 918
+S1 done 919
+S1 done 920
+S1 done 921
+S1 done 922
+S1 done 923
+S1 done 924
+S1 done 925
+S1 done 926
+S1 done 927
+S1 done 928
+S1 done 929
+S1 done 930
+S1 done 931
+S1 done 932
+S1 done 933
+S1 done 934
+S1 done 935
+S1 done 936
+S1 done 937
+S1 done 938
+S1 done 939
+S1 done 940
+S1 done 941
+S1 done 942
+S1 done 943
+S1 done 944
+S1 done 945
+S1 done 946
+S1 done 947
+S1 done 948
+S1 done 949
+S1 done 950
+S1 done 951
+S1 done 952
+S1 done 953
+S1 done 954
+S1 done 955
+S1 done 956
+S1 done 957
+S1 done 958
+S1 done 959
+S1 done 960
+S1 done 961
+S1 done 962
+S1 done 963
+S1 done 964
+S1 done 965
+S1 done 966
+S1 done 967
+S1 done 968
+S1 done 969
+S1 done 970
+S1 done 971
+S1 done 972
+S1 done 973
+S1 done 974
+S1 done 975
+S1 done 976
+S1 done 977
+S1 done 978
+S1 done 979
+S1 done 980
+S1 done 981
+S1 done 982
+S1 done 983
+S1 done 984
+S1 done 985
+S1 done 986
+S1 done 987
+S1 done 988
+S1 done 989
+S1 done 990
+S1 done 991
+S1 done 992
+S1 done 993
+S1 done 994
+S1 done 995
+S1 done 996
+S1 done 997
+S1 done 998
+S1 done 999
+S2 statement done!
Index: tests/concurrent/pthread/.expect/pthread_demo_create_join.txt
===================================================================
--- tests/concurrent/pthread/.expect/pthread_demo_create_join.txt	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/.expect/pthread_demo_create_join.txt	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,1 @@
+final res is 190
Index: tests/concurrent/pthread/.expect/pthread_demo_lock.txt
===================================================================
--- tests/concurrent/pthread/.expect/pthread_demo_lock.txt	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/.expect/pthread_demo_lock.txt	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,6 @@
+lock res is 2000000000
+in trylocktest1 res1 is 0
+in trylocktest1 res2 is 0
+in trylocktest2 res1 is 16
+in trylocktest2 res2 is 16
+cnt_trylock is 200000000
Index: tests/concurrent/pthread/.expect/pthread_key_test.txt
===================================================================
--- tests/concurrent/pthread/.expect/pthread_key_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/.expect/pthread_key_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,6 @@
+Destructor function invoked
+Destructor function invoked
+Destructor function invoked
+Destructor function invoked
+Destructor function invoked
+total value is 207, total value by pthread_getspecific is 207
Index: tests/concurrent/pthread/.expect/pthread_once_test.txt
===================================================================
--- tests/concurrent/pthread/.expect/pthread_once_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/.expect/pthread_once_test.txt	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,1 @@
+in once_fn
Index: tests/concurrent/pthread/bounded_buffer.cfa
===================================================================
--- tests/concurrent/pthread/bounded_buffer.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/bounded_buffer.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,156 @@
+#include <stdlib.h>										// prototype: rand
+#include <fstream.hfa>
+#include <thread.hfa>
+#include <pthread.h>
+#include <errno.h>
+// tested pthread mutex related routines, pthread cond related routines
+// tested pthread_create/join
+
+enum { BufferSize = 50 };
+
+volatile int producer_val_total;
+volatile int consumer_val_total;
+
+pthread_mutex_t producer_cnt_lock, consumer_cnt_lock;
+
+
+forall( T ){
+    struct Buffer
+    {
+        int front, back, count;
+		T elements[BufferSize];
+        pthread_mutex_t _mutex;
+	    pthread_cond_t Full, Empty;							// waiting consumers & producers
+    };
+
+    void ?{}( Buffer(T) & buffer ) with( buffer ) {
+         [front, back, count] = 0; 
+         pthread_mutex_init(&_mutex, NULL);
+         pthread_cond_init(&Full, NULL);
+         pthread_cond_init(&Empty, NULL);
+    }
+
+    void ^?{}( Buffer(T) & buffer ) with( buffer ){
+        pthread_mutex_destroy(&_mutex);
+        pthread_cond_destroy(&Full);
+        pthread_cond_destroy(&Empty);
+    }
+
+    int query( Buffer(T) & buffer ) { return buffer.count; } // read-only, no mutual exclusion
+    
+    void insert( Buffer(T) & buffer, T elem ) with(buffer) {
+		pthread_mutex_lock(&_mutex);
+		while ( count == 20 ) pthread_cond_wait( &Empty, &_mutex ); // block producer
+		elements[back] = elem;
+		back = ( back + 1 ) % 20;
+		count += 1;
+		pthread_cond_signal( &Full );					// unblock consumer
+        pthread_mutex_unlock(&_mutex);
+	}
+
+    T remove(Buffer(T) & buffer) with(buffer) {
+		pthread_mutex_lock(&_mutex);
+		while ( count == 0 ) pthread_cond_wait( &Full, &_mutex ); // block consumer
+		T elem = elements[front];
+		front = ( front + 1 ) % 20;
+		count -= 1;
+		pthread_cond_signal( &Empty );					// unblock producer
+        pthread_mutex_unlock(&_mutex);
+		return elem;
+	}
+
+}
+
+void *producer( void *arg ) {
+	Buffer(int) &buf = *(Buffer(int)*)arg;
+	const int NoOfItems = rand() % 40;
+	int item;
+	for ( int i = 1; i <= NoOfItems; i += 1 ) {			// produce a bunch of items
+		item = rand() % 100 + 1;						// produce a random number
+		//sout | "Producer:" | pthread_self() | " value:" | item;
+		insert( buf,item );								// insert element into queue
+        pthread_mutex_lock(&producer_cnt_lock);
+        producer_val_total += item;
+        pthread_mutex_unlock(&producer_cnt_lock);
+	} // for
+	//sout | "Producer:" | pthread_self() | " is finished";
+	return NULL;
+} // producer
+
+void *consumer( void *arg ) {
+	Buffer(int) &buf = *(Buffer(int) *)arg;
+	int item;
+	for ( ;; ) {										// consume until a negative element appears
+		item = remove(buf);							// remove from front of queue
+		//sout | "Consumer:" | pthread_self() | " value:" | item;
+	  if ( item == -1 ) break;
+        pthread_mutex_lock(&consumer_cnt_lock);
+        consumer_val_total += item;
+        pthread_mutex_unlock(&consumer_cnt_lock);
+	} // for
+	//sout | "Consumer:" | pthread_self() | " is finished";
+	return NULL;
+} // consumer
+
+int main() {
+	const int NoOfCons = 20, NoOfProds = 30;
+	Buffer(int) buf;								// create a buffer monitor
+	pthread_t cons[NoOfCons];							// pointer to an array of consumers
+	pthread_t prods[NoOfProds];							// pointer to an array of producers
+    pthread_mutex_init(&producer_cnt_lock, NULL);
+    pthread_mutex_init(&consumer_cnt_lock, NULL);
+	// parallelism
+    srandom( 1003 );
+
+	processor p[5];
+    {
+        // create/join and mutex/condition test
+        //sout | "create/join and mutex/condition test";
+        for ( int i = 0; i < NoOfCons; i += 1 ) {			// create consumers
+            if ( pthread_create( &cons[i], NULL, consumer, (void*)&buf ) != 0 ) {
+                sout | "create thread failure, errno:" | errno;
+                exit( EXIT_FAILURE );
+            } // if
+        } // for
+        for ( int i = 0; i < NoOfProds; i += 1 ) {			// 	create producers
+            if ( pthread_create( &prods[i], NULL, producer, (void*)&buf ) != 0 ) {
+                sout | "create thread failure";
+                exit( EXIT_FAILURE );
+            } // if
+        } // for
+
+        void *result;
+        for ( int i = 0; i < NoOfProds; i += 1 ) {			// wait for producers to end
+            if ( pthread_join( prods[i], &result ) != 0 ) {
+                sout | " producers join thread failure";
+                exit( EXIT_FAILURE );
+            } // if
+            if ( (uint64_t)result != 0 ) {
+                sout | "producers" | prods[i] |" bad return value " | result;
+                exit( EXIT_FAILURE );
+            } // if
+            //sout | "join prods[" | i | "]:" | prods[i] | " result:" | result;
+        } // for
+
+        for ( int i = 0; i < NoOfCons; i += 1 ) {			// terminate each consumer
+            insert(buf, -1 );
+        } // for
+
+        for ( int i = 0; i < NoOfCons; i += 1 ) {			// wait for consumer to end
+            if ( pthread_join( cons[i], &result ) != 0 ) {
+                sout| "consumers join thread failure" ;
+                exit( EXIT_FAILURE );
+            } // if
+            if ( (uint64_t)result != 0 ) {
+                sout| "consumers bad return value" | result;
+                exit( EXIT_FAILURE );
+            } // if
+        } // for
+        sout | "producer total value is " | producer_val_total;
+        sout | "consumer total value is " | consumer_val_total;
+    }
+
+	
+
+	
+}
Index: tests/concurrent/pthread/pthread_attr_test.cfa
===================================================================
--- tests/concurrent/pthread/pthread_attr_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/pthread_attr_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,29 @@
+/* test attr init; set stack; get stack */
+
+#include <fstream.hfa>
+#include <thread.hfa>
+
+void* foo(void* _attr){
+    size_t size;
+    pthread_attr_t* attr = (pthread_attr_t*)_attr;
+    int status = pthread_attr_getstacksize(attr, &size);
+    if (status != 0){
+        sout | "error return code";
+        exit(1);
+    }
+    sout | "stack size is " | size;
+    return NULL;
+}
+
+int main(int argc, char const *argv[])
+{
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, 123456789);
+    pthread_t thr;
+    void* res;
+    pthread_create(&thr, &attr, foo, (void*)&attr);
+    pthread_join(thr, &res);
+    pthread_attr_destroy(&attr);
+    return 0;
+}
Index: tests/concurrent/pthread/pthread_cond_test.cfa
===================================================================
--- tests/concurrent/pthread/pthread_cond_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/pthread_cond_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,46 @@
+/* small test of pthread cond */
+
+#include <fstream.hfa>
+#include <thread.hfa>
+#include <pthread.h>
+
+int done_flag = 0;
+pthread_mutex_t _mutex;
+pthread_cond_t cond;
+
+extern "C"{
+    void* S1(void* arg){
+        pthread_mutex_lock(&_mutex);
+        for (int i = 0; i < 1000; i++) sout | "S1 done " | i;
+        done_flag = 1;
+        pthread_mutex_unlock(&_mutex);
+        pthread_cond_signal(&cond);
+        return NULL;
+    }
+
+    void* S2(void* arg){
+        pthread_mutex_lock(&_mutex);
+        if (!done_flag) pthread_cond_wait(&cond, &_mutex);
+        sout | "S2 statement done!";
+        pthread_mutex_unlock(&_mutex);
+        return NULL;
+    }
+}
+
+
+
+int main(int argc, char const *argv[])
+{
+    /* code */
+    pthread_mutex_init(&_mutex, NULL);
+    pthread_cond_init(&cond, NULL);
+    pthread_t s1,s2;
+    pthread_create(&s1, NULL, S1, NULL);
+    pthread_create(&s2, NULL, S2, NULL);
+    void* res = NULL;
+    pthread_join(s1, &res);
+    pthread_join(s2, &res);
+    pthread_mutex_destroy(&_mutex);
+    pthread_cond_destroy(&cond);
+    return 0;
+}
Index: tests/concurrent/pthread/pthread_demo_create_join.cfa
===================================================================
--- tests/concurrent/pthread/pthread_demo_create_join.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/pthread_demo_create_join.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,41 @@
+#include <fstream.hfa>
+#include <thread.hfa>
+/* test pthread create/join/exit */
+
+int arr[20];
+
+void* fetch(void* idx){
+    int res = arr[(uint64_t)idx];
+    pthread_exit((void*)res);
+    sout | "it should not be here";
+    exit(1);
+    //return (void*)res;
+}
+
+void arr_init(){
+    for (int i = 0; i < 20; i++){
+        arr[i] = i;
+    }
+}
+
+int main(int argc, char const *argv[])
+{
+    pthread_t threads[20];
+    arr_init();
+    int status;
+    for (int i = 0; i < 20; i++){
+        status = pthread_create(&threads[i], NULL, fetch, (void*)i);
+        if (status != 0) exit(1);
+    }
+    int res = 0;
+    for (int i = 0; i < 20; i++){
+        void* _res = NULL;
+        status = pthread_join(threads[i], &_res);
+        if (status != 0) exit(2);
+        if (((uint64_t)_res) != i) exit(3);
+        res += (uint64_t)_res;
+    }
+    sout | "final res is" | res;
+
+    return 0;
+}
Index: tests/concurrent/pthread/pthread_demo_lock.cfa
===================================================================
--- tests/concurrent/pthread/pthread_demo_lock.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/pthread_demo_lock.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,124 @@
+#include <fstream.hfa>
+#include <thread.hfa>
+/* 
+    test pthread_mutex to provide mutual exclusion
+    test pthread_mutex_trylock not block when lock is acquired by others; test pthread_mutex_trylock can acquire the lock
+*/
+volatile int cnt_nolock = 0;
+volatile int cnt_lock = 0;
+volatile int cnt_trylock = 0;
+extern "C"{
+    static pthread_mutex_t _mutex;
+}
+
+/* mutex pthread routine  */
+// unlocked increnment
+void* inc_unlock(void* cnt){
+    for (int i = 0; i < (uint64_t)cnt; i++){
+        cnt_nolock++;
+    }   // for
+    return NULL;
+}   
+// locked increment
+void* inc_lock(void* cnt){
+    pthread_mutex_lock(&_mutex);
+    for (int i = 0; i < (uint64_t)cnt; i++){
+        cnt_lock++;
+    }   // for
+    pthread_mutex_unlock(&_mutex);
+    return NULL;
+}
+
+/* test lock vs unlock */
+void test_unlock(){
+    pthread_t threads[20];
+    for (int i = 0; i < 20; i++){
+        pthread_create(&threads[i], NULL, inc_unlock, (void*)100000000);
+    }
+    for (int i = 0; i < 20; i++){
+        void * res = NULL;
+        pthread_join(threads[i], &res);
+    }
+    sout | "unlock res is" | cnt_nolock;
+    cnt_nolock = 0;
+}
+extern "C"{
+    void test_lock(){
+        pthread_mutex_init(&_mutex, NULL);
+        pthread_t threads[20];
+        for (int i = 0; i < 20; i++){
+            
+            pthread_create(&threads[i], NULL, inc_lock, (void*)100000000);
+        }
+        for (int i = 0; i < 20; i++){
+            void * res = NULL;
+            pthread_join(threads[i], &res);
+        }
+        sout | "lock res is" | cnt_lock;
+        pthread_mutex_destroy(&_mutex);
+        if (cnt_lock != 100000000 * 20) {
+            sout | "pthread mutex not working";
+            exit(1);
+        }
+        cnt_lock = 0;
+    }
+}
+
+
+/* mutex trylock pthread routine  */
+void* trylock_test2(void* arg){
+    int res = pthread_mutex_trylock(&_mutex);
+    sout | "in trylocktest2 res1 is" | res;
+    res = pthread_mutex_trylock(&_mutex);
+    sout | "in trylocktest2 res2 is" | res;
+    pthread_mutex_lock(&_mutex);
+    for (int i = 0; i < (uint64_t)arg; i++) cnt_trylock++;
+    pthread_mutex_unlock(&_mutex);
+    return NULL;
+}
+
+void* trylock_test1(void* arg){
+    int res = pthread_mutex_trylock(&_mutex);
+    sout | "in trylocktest1 res1 is" | res;
+    res = pthread_mutex_trylock(&_mutex);
+    sout | "in trylocktest1 res2 is" | res;
+    pthread_t task2;
+    pthread_create(&task2, NULL, trylock_test2, (void*)100000000);
+
+    // inc cnt then release the lock
+    for (int i = 0; i < (uint64_t)arg; i++) cnt_trylock++;
+    pthread_mutex_unlock(&_mutex);
+    pthread_mutex_unlock(&_mutex);
+    void * dummy = NULL;
+    pthread_join(task2, &dummy);
+    sout | "cnt_trylock is " | cnt_trylock;
+    return NULL;
+}
+
+// trylock test
+void test_trylock(){
+    pthread_mutex_init(&_mutex, NULL);
+    pthread_t task1;
+    pthread_create(&task1, NULL, trylock_test1, (void*)100000000);
+    void * dummy = NULL;
+    pthread_join(task1,&dummy);
+    pthread_mutex_destroy(&_mutex);
+    if (cnt_trylock != 100000000 * 2) {
+        sout | "pthread try mutex not working";
+        exit(1);
+    }
+    cnt_trylock = 0;
+}
+
+
+
+int main(int argc, char const *argv[])
+{
+    
+    // compare unlock vs lock
+    test_lock();
+    // test trylock
+    test_trylock();
+    
+    return 0;
+}
Index: tests/concurrent/pthread/pthread_key_test.cfa
===================================================================
--- tests/concurrent/pthread/pthread_key_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/pthread_key_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,126 @@
+
+/* test pthread_key_create/set_specific/get_specific
+    get specific == set specific
+    dtor is invoked (no mem leak)
+*/
+
+
+extern "C"{
+
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <errno.h>
+    #include <pthread.h>
+
+    #define THREADS 5
+    #define BUFFSZ  48
+    pthread_key_t   key;
+    volatile int total_value,total_value_getspec;
+    pthread_mutex_t value_mutex;
+
+    void            *threadfunc(void *parm)
+    {
+        int        status;
+        void      *value;
+        int        threadnum;
+        int       *tnum;
+        void      *getvalue;
+        char       Buffer[BUFFSZ];
+
+        tnum = (int*)parm;
+        threadnum = *tnum;
+
+        //printf("Thread %d executing\n", threadnum);
+        value = (void *)(rand()%100);
+        status = pthread_setspecific(key, (void *) value);
+        if ( status !=  0) {
+            printf("pthread_setspecific failed, thread %d, errno %d",
+                                                        threadnum, errno);
+            return (void*)12;
+        }
+        pthread_mutex_lock(&value_mutex);
+        total_value_getspec += (int)value;
+        total_value += (int)pthread_getspecific(key);
+        pthread_mutex_unlock(&value_mutex);
+
+
+        if (!(value = malloc(sizeof(Buffer))))
+            printf("Thread %d could not allocate storage, errno = %d\n",
+                                                        threadnum, errno);
+        status = pthread_setspecific(key, (void *) value);
+        if ( status !=  0) {
+            printf("pthread_setspecific failed, thread %d, errno %d",
+                                                        threadnum, errno);
+            return (void*)12;
+        }
+        //printf("Thread %d setspecific value: %d\n", threadnum, value);
+
+        getvalue = 0;
+        getvalue = pthread_getspecific(key);
+
+        if (getvalue != value) {
+        printf("getvalue not valid, getvalue=%d", (u_int64_t)getvalue);
+            return (void*)68;
+        }
+
+        pthread_exit((void *)0);
+    }
+
+    void  destr_fn(void *parm)
+    {
+
+        printf("Destructor function invoked\n");
+        free(parm);
+    }
+
+
+    int main() {
+        int          getvalue;
+        int          status;
+        int          i;
+        int          threadparm[THREADS];
+        pthread_t    threadid[THREADS];
+        void*          thread_stat[THREADS];
+
+        // rand seed for testing
+        srand(1003);
+        pthread_mutex_init(&value_mutex, NULL);
+
+        // testing getspec and setspec
+        total_value = 0;
+        total_value_getspec = 0;
+
+        if ((status = pthread_key_create(&key, destr_fn )) < 0) {
+            printf("pthread_key_create failed, errno=%d", errno);
+            exit(1);
+        }
+
+        // create 3 THREADS, pass each its number
+        for (i=0; i<THREADS; i++) {
+            threadparm[i] = i+1;
+            status = pthread_create( &threadid[i],
+                                    NULL,
+                                    threadfunc,
+                                    (void *)&threadparm[i]);
+            if ( status <  0) {
+            printf("pthread_create failed, errno=%d", errno);
+            exit(2);
+            }
+        }
+
+        for ( i=0; i<THREADS; i++) {
+            status = pthread_join( threadid[i], (void **)&thread_stat[i]);
+            if ( status <  0) {
+            printf("pthread_join failed, thread %d, errno=%d\n", i+1, errno);
+            }
+
+            if (thread_stat[i] != 0)   {
+                printf("bad thread status, thread %d, status=%d\n", i+1,
+                                                        (u_int64_t)thread_stat[i]);
+            }
+        }
+        printf("total value is %d, total value by pthread_getspecific is %d\n", total_value, total_value_getspec);
+        exit(0);
+    }   // main
+}
+
Index: tests/concurrent/pthread/pthread_once_test.cfa
===================================================================
--- tests/concurrent/pthread/pthread_once_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
+++ tests/concurrent/pthread/pthread_once_test.cfa	(revision 1a452638e119559b489523986faa60a438969248)
@@ -0,0 +1,96 @@
+// tested pthread once,create,join
+
+                                                          
+                                                                                
+                                                            
+#include <fstream.hfa>
+#include <thread.hfa>                                                                    
+#define THREADS 20                                                                                                                                                    
+
+extern "C"{
+    #include <pthread.h>
+    #include <stdio.h>
+    #include <errno.h> 
+    int             once_counter=0;                                                 
+    pthread_once_t  once_control = PTHREAD_ONCE_INIT;                               
+                                                                                    
+    void  once_fn(void)                                                             
+    {                                                                               
+    puts("in once_fn");                                                            
+    once_counter++;                                                                
+    }                                                                               
+                                                                                    
+    void            *threadfunc(void *parm)                                         
+    {                                                                               
+    int        status;                                                             
+    int        threadnum;                                                          
+    int        *tnum;                                                              
+                                                                                    
+    tnum = (int *)parm;                                                                   
+    threadnum = *tnum;                                                             
+                                                                                    
+    //printf("Thread %d executing\n", threadnum);                                    
+                                                                                    
+    status = pthread_once(&once_control, once_fn);                                 
+    if ( status <  0)                                                              
+        printf("pthread_once failed, thread %d, errno=%d\n", threadnum,             
+                                                                errno);             
+                                                                                    
+    //pthread_exit((void *)0);  
+    return NULL;                                                     
+    }  
+
+
+    void once_rtn(){
+        printf("in once init\n");
+    }
+    void test(){
+
+        processor p[10];
+        
+
+        int          status;                                                           
+        int          i;                                                                
+        int          threadparm[THREADS];                                              
+        pthread_t    threadid[THREADS];                                                
+        void*          thread_stat[THREADS];                                             
+                                                                                        
+        for (i=0; i<THREADS; i++) {                                                    
+            threadparm[i] = i+1;                                                        
+            status = pthread_create( &threadid[i],                                      
+                                    NULL,                                              
+                                    threadfunc,                                        
+                                    (void *)&threadparm[i]);                           
+            if ( status <  0) {                                                         
+            printf("pthread_create failed, errno=%d", errno);                        
+            exit(2);                                                                 
+            }                                                                           
+        }                                                                             
+                                                                                        
+        for ( i=0; i<THREADS; i++) {                                                   
+            status = pthread_join( threadid[i], (void **)&thread_stat[i]);               
+            if ( status <  0)                                                           
+            printf("pthread_join failed, thread %d, errno=%d\n", i+1, errno);        
+                                                                                        
+            if (thread_stat[i] != 0)                                                    
+                printf("bad thread status, thread %d, status=%d\n", i+1,                
+                                                        (int)thread_stat[i]);             
+        }                                                                             
+                                                                                        
+        if (once_counter != 1) {
+            printf("once_fn did not get control once, counter=%d",once_counter);         
+            exit(1);
+        }                                                        
+        
+        exit(0);
+        
+    }
+}
+
+
+
+int main(int argc, char const *argv[])
+{
+    test();
+    return 0;
+}
