224 lines
5.0 KiB
C
224 lines
5.0 KiB
C
#include "Internal.h"
|
|
#include "Timespec.h"
|
|
#include "Codemap.h"
|
|
#include <stdlib.h>
|
|
|
|
#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
|