diff --git a/lib/libc/posix/pthread.c b/lib/libc/posix/pthread.c index 532f6f0..cc9199c 100644 --- a/lib/libc/posix/pthread.c +++ b/lib/libc/posix/pthread.c @@ -301,40 +301,112 @@ pthread_mutex_unlock(pthread_mutex_t *mutex) * Condition Variables */ -struct pthread_cond { +struct pthread_condattr { + uint64_t _unused; }; -struct pthread_condattr { +struct pthread_cond { + CoreMutex mtx; + uint64_t enter; + uint64_t exit; }; int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { - return EINVAL; + struct pthread_cond *cnd = (struct pthread_cond *)malloc(sizeof(*cnd)); + + if (cnd == NULL) { + return ENOMEM; + } + + CoreMutex_Init(&cnd->mtx); + cnd->enter = 0; + cnd->exit = 0; + + *cond = cnd; + + return 0; } int pthread_cond_destroy(pthread_cond_t *cond) { + struct pthread_cond *cnd = *cond; + + *cond = NULL; + free(cnd); + return EINVAL; } int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { - return EINVAL; + struct pthread_cond *cnd; + uint64_t level; + + if (*cond == NULL) { + int status = pthread_cond_init(cond, NULL); + if (status != 0) + return status; + } + cnd = *cond; + + if (mutex) + pthread_mutex_unlock(mutex); + + CoreMutex_Lock(&cnd->mtx); + level = cnd->enter; + cnd->enter++; + CoreMutex_Unlock(&cnd->mtx); + + while (level >= cnd->exit) { + OSThreadSleep(0); + } + + if (mutex) + pthread_mutex_lock(mutex); + + return 0; } int pthread_cond_signal(pthread_cond_t *cond) { - return EINVAL; + struct pthread_cond *cnd; + + if (*cond == NULL) { + int status = pthread_cond_init(cond, NULL); + if (status != 0) + return status; + } + cnd = *cond; + + CoreMutex_Lock(&cnd->mtx); + cnd->exit++; + CoreMutex_Unlock(&cnd->mtx); + + return 0; } int pthread_cond_broadcast(pthread_cond_t *cond) { - return EINVAL; + struct pthread_cond *cnd; + + if (*cond == NULL) { + int status = pthread_cond_init(cond, NULL); + if (status != 0) + return status; + } + cnd = *cond; + + CoreMutex_Lock(&cnd->mtx); + cnd->exit = cnd->enter; + CoreMutex_Unlock(&cnd->mtx); + + return 0; }