From 2fdcc4b5574eae39d2ce78370d0361698f5bf63e Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Fri, 30 Jan 2015 18:40:25 -0800 Subject: [PATCH] pthread_mutex implementation --- include/errno.h | 1 + include/pthread.h | 11 ++++ lib/libc/posix/pthread.c | 115 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/include/errno.h b/include/errno.h index 3c6db71..4c2d3c3 100644 --- a/include/errno.h +++ b/include/errno.h @@ -12,6 +12,7 @@ #define ENAMETOOLONG 0xBAD8 #define ENOSYS 0xBAD9 #define EAGAIN 0xBADA +#define EBUSY 0xBADB #endif /* __ERRNO_H__ */ diff --git a/include/pthread.h b/include/pthread.h index 7433701..59e9825 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -2,12 +2,17 @@ #ifndef __PTHREAD_H__ #define __PTHREAD_H__ +#define PTHREAD_MUTEX_INITIALIZER NULL +#define PTHREAD_COND_INITIALIZER NULL + typedef struct pthread *pthread_t; typedef struct pthread_attr *pthread_attr_t; typedef struct pthread_barrier *pthread_barrier_t; typedef struct pthread_barrierattr *pthread_barrierattr_t; typedef struct pthread_mutex *pthread_mutex_t; typedef struct pthread_mutexattr *pthread_mutexattr_t; +typedef struct pthread_cond *pthread_cond_t; +typedef struct pthread_condattr *pthread_condattr_t; pthread_t pthread_self(void); int pthread_create(pthread_t *thread, const pthread_attr_t *attr, @@ -45,5 +50,11 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex); * Condition Variables */ +int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_broadcast(pthread_cond_t *cond); + #endif /* __PTHREAD_H__ */ diff --git a/lib/libc/posix/pthread.c b/lib/libc/posix/pthread.c index 8b89873..0631ad6 100644 --- a/lib/libc/posix/pthread.c +++ b/lib/libc/posix/pthread.c @@ -113,45 +113,123 @@ pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned count) { + return EINVAL; } int pthread_barrier_destroy(pthread_barrier_t *barrier) { + return EINVAL; } int pthread_barrier_wait(pthread_barrier_t *barrier) { + return EINVAL; } /* * Mutex */ +struct pthread_mutexattr { + uint64_t _unused; +}; + +struct pthread_mutex { + uint64_t lock; +}; + int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { + struct pthread_mutex *mtx = (struct pthread_mutex *)malloc(sizeof(*mtx)); + + if (mtx == NULL) { + return ENOMEM; + } + + mtx->lock = 0; + *mutex = mtx; + + return 0; } int pthread_mutex_destroy(pthread_mutex_t *mutex) { + struct pthread_mutex *mtx = *mutex; + + if (mtx == NULL) { + return EINVAL; + } else if (mtx->lock == 1) { + return EBUSY; + } else { + *mutex = NULL; + free(mtx); + return 0; + } } int pthread_mutex_lock(pthread_mutex_t *mutex) { + struct pthread_mutex *mtx; + + if (*mutex == NULL) { + int status = pthread_mutex_init(mutex, NULL); + if (status != 0) + return status; + } + + mtx = *mutex; + + // XXX: Should have the kernel wait kernel instead of yielding + while (__sync_lock_test_and_set(&mtx->lock, 1) == 1) { + OSThreadSleep(0); + } + + return 0; } int pthread_mutex_trylock(pthread_mutex_t *mutex) { + struct pthread_mutex *mtx; + + if (*mutex == NULL) { + int status = pthread_mutex_init(mutex, NULL); + if (status != 0) + return status; + } + + mtx = *mutex; + + if (__sync_lock_test_and_set(&mtx->lock, 1) == 1) { + return EBUSY; + } else { + // Lock acquired + return 0; + } } int pthread_mutex_unlock(pthread_mutex_t *mutex) { + struct pthread_mutex *mtx; + + if (*mutex == NULL) { + int status = pthread_mutex_init(mutex, NULL); + if (status != 0) + return status; + } + + mtx = *mutex; + + __sync_lock_release(&mtx->lock); + // XXX: Wakeup a sleeping thread + + return 0; } @@ -163,3 +241,40 @@ pthread_mutex_unlock(pthread_mutex_t *mutex) * Condition Variables */ +struct pthread_cond { +}; + +struct pthread_condattr { +}; + +int +pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) +{ + return EINVAL; +} + +int +pthread_cond_destroy(pthread_cond_t *cond) +{ + return EINVAL; +} + +int +pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + return EINVAL; +} + + +int +pthread_cond_signal(pthread_cond_t *cond) +{ + return EINVAL; +} + +int +pthread_cond_broadcast(pthread_cond_t *cond) +{ + return EINVAL; +} +