forked from Bananymous/banan-os
				
			LibC: Implement pthread_barrier
This is not fully working but should be fine for most cases
This commit is contained in:
		
							parent
							
								
									60cb392e97
								
							
						
					
					
						commit
						2a5921b9c9
					
				|  | @ -28,8 +28,8 @@ typedef pthread_t pthread_spinlock_t; | ||||||
| typedef struct { int type; int shared; } pthread_mutexattr_t; | typedef struct { int type; int shared; } pthread_mutexattr_t; | ||||||
| typedef struct { pthread_mutexattr_t attr; pthread_t locker; unsigned lock_depth; } pthread_mutex_t; | typedef struct { pthread_mutexattr_t attr; pthread_t locker; unsigned lock_depth; } pthread_mutex_t; | ||||||
| 
 | 
 | ||||||
| typedef int pthread_barrierattr_t; | typedef struct { int shared; } pthread_barrierattr_t; | ||||||
| typedef int pthread_barrier_t; | typedef struct { pthread_barrierattr_t attr; unsigned target; unsigned waiting; } pthread_barrier_t; | ||||||
| 
 | 
 | ||||||
| typedef struct { int clock; int shared; } pthread_condattr_t; | typedef struct { int clock; int shared; } pthread_condattr_t; | ||||||
| struct _pthread_cond_block { struct _pthread_cond_block* next; int signaled; }; | struct _pthread_cond_block { struct _pthread_cond_block* next; int signaled; }; | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ struct uthread | ||||||
| 	uintptr_t dtv[]; | 	uintptr_t dtv[]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define PTHREAD_BARRIER_SERIAL_THREAD	1 |  | ||||||
| #define PTHREAD_CANCEL_ASYNCHRONOUS		2 | #define PTHREAD_CANCEL_ASYNCHRONOUS		2 | ||||||
| #define PTHREAD_CANCEL_ENABLE			3 | #define PTHREAD_CANCEL_ENABLE			3 | ||||||
| #define PTHREAD_CANCEL_DEFERRED			4 | #define PTHREAD_CANCEL_DEFERRED			4 | ||||||
|  | @ -40,6 +39,8 @@ struct uthread | ||||||
| #define PTHREAD_SCOPE_PROCESS			23 | #define PTHREAD_SCOPE_PROCESS			23 | ||||||
| #define PTHREAD_SCOPE_SYSTEM			24 | #define PTHREAD_SCOPE_SYSTEM			24 | ||||||
| 
 | 
 | ||||||
|  | #define PTHREAD_BARRIER_SERIAL_THREAD	1 | ||||||
|  | 
 | ||||||
| #define PTHREAD_ONCE_INIT				0 | #define PTHREAD_ONCE_INIT				0 | ||||||
| 
 | 
 | ||||||
| #define PTHREAD_PROCESS_SHARED			0 | #define PTHREAD_PROCESS_SHARED			0 | ||||||
|  |  | ||||||
|  | @ -818,6 +818,82 @@ int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __r | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) | ||||||
|  | { | ||||||
|  | 	(void)attr; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pthread_barrierattr_init(pthread_barrierattr_t* attr) | ||||||
|  | { | ||||||
|  | 	*attr = { | ||||||
|  | 		.shared = false, | ||||||
|  | 	}; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pthread_barrierattr_getpshared(const pthread_barrierattr_t* __restrict attr, int* __restrict pshared) | ||||||
|  | { | ||||||
|  | 	*pshared = attr->shared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) | ||||||
|  | { | ||||||
|  | 	switch (pshared) | ||||||
|  | 	{ | ||||||
|  | 		case PTHREAD_PROCESS_PRIVATE: | ||||||
|  | 			attr->shared = false; | ||||||
|  | 			return 0; | ||||||
|  | 		case PTHREAD_PROCESS_SHARED: | ||||||
|  | 			attr->shared = true; | ||||||
|  | 			return 0; | ||||||
|  | 	} | ||||||
|  | 	return EINVAL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pthread_barrier_destroy(pthread_barrier_t* barrier) | ||||||
|  | { | ||||||
|  | 	(void)barrier; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pthread_barrier_init(pthread_barrier_t* __restrict barrier, const pthread_barrierattr_t* __restrict attr, unsigned count) | ||||||
|  | { | ||||||
|  | 	if (count == 0) | ||||||
|  | 		return EINVAL; | ||||||
|  | 	const pthread_barrierattr_t default_attr = { | ||||||
|  | 		.shared = false, | ||||||
|  | 	}; | ||||||
|  | 	if (attr == nullptr) | ||||||
|  | 		attr = &default_attr; | ||||||
|  | 	*barrier = { | ||||||
|  | 		.attr = *attr, | ||||||
|  | 		.target = count, | ||||||
|  | 		.waiting = 0, | ||||||
|  | 	}; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pthread_barrier_wait(pthread_barrier_t* barrier) | ||||||
|  | { | ||||||
|  | 	const unsigned index = BAN::atomic_add_fetch(barrier->waiting, 1); | ||||||
|  | 
 | ||||||
|  | 	// FIXME: this case should be handled, but should be relatively uncommon
 | ||||||
|  | 	//        so i'll just roll with the easy implementation
 | ||||||
|  | 	ASSERT(index <= barrier->target); | ||||||
|  | 
 | ||||||
|  | 	if (index == barrier->target) | ||||||
|  | 	{ | ||||||
|  | 		BAN::atomic_store(barrier->waiting, 0); | ||||||
|  | 		return PTHREAD_BARRIER_SERIAL_THREAD; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	while (BAN::atomic_load(barrier->waiting)) | ||||||
|  | 		sched_yield(); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #if not __disable_thread_local_storage | #if not __disable_thread_local_storage | ||||||
| struct tls_index | struct tls_index | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue