#include "Internal.h" #include "Timespec.h" #include "Codemap.h" #include #if (_POSIX_SEMAPHORES >= 200112L) CgeSemaphore *CgeSemaphoreNew(int value, int *result) { CgeSemaphore *semaphore; int code = CGE_THREAD_EOK; semaphore = malloc(sizeof(CgeSemaphore)); if (semaphore && sem_init(&semaphore->handle, 0, value)) { code = errorToErrorCode(errno); free(semaphore); semaphore = NULL; } else if (!semaphore) { code = CGE_THREAD_EOOM; } if (result) *result = code; return semaphore; } void CgeSemaphoreFree(CgeSemaphore *semaphore) { if (!semaphore) return; sem_destroy(&semaphore->handle); free(semaphore); } int CgeSemaphorePost(CgeSemaphore *semaphore, int *result) { int code = CGE_THREAD_EOK; if (sem_post(&semaphore->handle)) code = errorToErrorCode(errno); if (result) *result = code; return code == CGE_THREAD_EOK; } int CgeSemaphoreWait(CgeSemaphore *semaphore, int *result) { int code = CGE_THREAD_EOK; if (sem_wait(&semaphore->handle)) code = errorToErrorCode(errno); if (result) *result = code; return code == CGE_THREAD_EOK; } int CgeSemaphoreTryWait(CgeSemaphore *semaphore, int *result) { int code = CGE_THREAD_EOK; if (sem_trywait(&semaphore->handle)) code = errorToErrorCode(errno); if (result) *result = code; return code == CGE_THREAD_EOK; } int CgeSemaphoreWaitFor(CgeSemaphore *semaphore, uint32_t timeout, int *result) { struct timespec ts; int code = CGE_THREAD_EOK; if (!convertToTimespec(&ts, timeout)) { if (result) *result = CGE_THREAD_EINVAL; return 0; } if (sem_timedwait(&semaphore->handle, &ts)) code = errorToErrorCode(errno); if (result) *result = code; return code == CGE_THREAD_EOK; } #else CgeSemaphore *CgeSemaphoreNew(int value, int *result) { CgeSemaphore *semaphore; int code = CGE_THREAD_EOOM; if (semaphore = malloc(sizeof(*semaphore))) { semaphore->count = value; semaphore->waiters = 0; if ((code = errorToErrorCode(pthread_mutex_init(&semaphore->mutex, NULL)))) { free(semaphore); if (result) *result = code; return NULL; } if ((code = errorToErrorCode(pthread_cond_init(&semaphore->condition, NULL)))) { pthread_mutex_destroy(&semaphore->mutex); free(semaphore); if (result) *result = code; return NULL; } } if (result) *result = code; return semaphore; } void CgeSemaphoreFree(CgeSemaphore *semaphore) { if (!semaphore) return; pthread_cond_destroy(&semaphore->condition); pthread_mutex_destroy(&semaphore->mutex); free(semaphore); } int CgeSemaphorePost(CgeSemaphore *semaphore, int *result) { int code; if ((code = errorToErrorCode(pthread_mutex_lock(&semaphore->mutex)))) { if (result) *result = code; return 0; } semaphore->count++; if (semaphore->waiters && (code = errorToErrorCode(pthread_cond_signal(&semaphore->condition)))) { if (result) *result = code; } pthread_mutex_unlock(&semaphore->mutex); return code == CGE_THREAD_EOK; } int CgeSemaphoreWait(CgeSemaphore *semaphore, int *result) { int code; if ((code = pthread_mutex_lock(&semaphore->mutex))) { if (result) *result = code; return 0; } semaphore->waiters++; while (!semaphore->count) { if ((code = errorToErrorCode(pthread_cond_wait(&semaphore->condition, &semaphore->mutex)))) break; } semaphore->waiters--; semaphore->count--; pthread_mutex_unlock(&semaphore->mutex); return code == CGE_THREAD_EOK; } int CgeSemaphoreTryWait(CgeSemaphore *semaphore, int *result) { int code; if ((code = errorToErrorCode(pthread_mutex_lock(&semaphore->mutex)))) { if (result) *result = code; return 0; } if (!semaphore->count) code = CGE_THREAD_EBUSY; else semaphore->count--; pthread_mutex_unlock(&semaphore->mutex); return code == CGE_THREAD_EOK; } int CgeSemaphoreWaitFor(CgeSemaphore *semaphore, uint32_t timeout, int *result) { struct timespec ts; int code; if (!convertToTimespec(&ts, timeout)) { if (result) *result = CGE_THREAD_EINVAL; return 0; } if ((code = errorToErrorCode(pthread_mutex_lock(&semaphore->mutex)))) { if (result) *result = code; return 0; } semaphore->waiters++; while (!semaphore->count && code == CGE_THREAD_EOK) { code = errorToErrorCode(pthread_cond_timedwait(&semaphore->condition, &semaphore->mutex, &ts)); } semaphore->waiters--; if (code == CGE_THREAD_EOK) semaphore->count--; pthread_mutex_unlock(&semaphore->mutex); if (result) *result = code; return code == CGE_THREAD_EOK; } #endif