Files
E502_ADC_BF_PC_companion/x502api-1.1.34/lib/osspec/osspec.c

310 lines
9.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***************************************************************************//**
@file osspec.c
Файл содержит некоторые внутренние функции, которые скрывают вызовы ОС:
функции работы с объектами синхронизации, потоками и т.д.
@author Borisov Alexey <borisov@lcard.ru>
@date 28.05.2012
***************************************************************************/
#include "osspec.h"
#include <stdlib.h>
#ifndef _WIN32
#include <sys/time.h>
#include <errno.h>
static void f_get_abs_time(uint32_t timeout, struct timespec *timeToWait) {
#ifdef NO_CLOCKGETTIME
struct timeval tv;
gettimeofday(&tv, NULL);
timeToWait->tv_sec = tv.tv_sec;
timeToWait->tv_nsec = tv.tv_usec * 1000;
#else
clock_gettime(CLOCK_REALTIME, timeToWait);
#endif
timeToWait->tv_sec += timeout/1000;
timeToWait->tv_nsec += 1000000*(timeout%1000) + 1;
while (timeToWait->tv_nsec >= 1000000000) {
timeToWait->tv_sec++;
timeToWait->tv_nsec -=1000000000;
}
}
#endif
#ifdef OSSPEC_USE_MUTEX
/***************************************************************************
Вспомогательная функции для работы с мьютексами....
**************************************************************************/
//создание мьютекса
t_mutex osspec_mutex_create(void) {
t_mutex hnd;
#ifdef _WIN32
hnd = CreateMutex(NULL, FALSE, NULL);
#else
hnd = (t_mutex)malloc(sizeof(pthread_mutex_t));
if (hnd!=NULL) {
int err = pthread_mutex_init(hnd, NULL);
if (err) {
free(hnd);
hnd = OSSPEC_INVALID_MUTEX;
}
} else {
hnd = OSSPEC_INVALID_MUTEX;
}
#endif
return hnd;
}
//захват мьютекса
int32_t osspec_mutex_lock(t_mutex handle, uint32_t timeout) {
int32_t err = 0;
if (handle == OSSPEC_INVALID_MUTEX)
err = OSSPEC_ERR_MUTEX_INVALID_HANDLE;
#ifdef _WIN32
if (!err) {
err = WaitForSingleObject(handle, timeout)==WAIT_OBJECT_0 ? 0 : OSSPEC_ERR_MUTEX_LOCK_TOUT;
}
#else
if (!err) {
int wt_res;
#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK
if (timeout == OSSPEC_TIMEOUT_INFINITY) {
wt_res = pthread_mutex_lock(handle);
} else {
struct timespec timeToWait;
f_get_abs_time(timeout, &timeToWait);
wt_res = pthread_mutex_timedlock(handle, &timeToWait);
}
#else // HAVE_PTHREAD_MUTEX_TIMEDLOCK
(void)timeout;
wt_res = pthread_mutex_lock(handle);
#endif // HAVE_PTHREAD_MUTEX_TIMEDLOCK
if (wt_res == ETIMEDOUT) {
err = OSSPEC_ERR_MUTEX_LOCK_TOUT;
} else if (wt_res != 0) {
err = OSSPEC_ERR_MUTEX_INVALID_HANDLE;
}
}
#endif
return err;
}
//освобождение мьютекса
int32_t osspec_mutex_release(t_mutex handle) {
int32_t res = 0;
if (handle == OSSPEC_INVALID_MUTEX)
res = OSSPEC_ERR_MUTEX_INVALID_HANDLE;
#ifdef _WIN32
if (!res)
res = ReleaseMutex(handle) ? 0 : OSSPEC_ERR_MUTEX_RELEASE;
#else
if (!res && pthread_mutex_unlock(handle))
res = OSSPEC_ERR_MUTEX_RELEASE;
#endif
return res;
}
int32_t osspec_mutex_destroy(t_mutex handle) {
int32_t res = (handle != OSSPEC_INVALID_MUTEX) ?
0 : OSSPEC_ERR_MUTEX_INVALID_HANDLE;
#ifdef _WIN32
if (!res)
CloseHandle(handle);
#else
if (!res) {
pthread_mutex_destroy(handle);
free(handle);
}
#endif
return res;
}
#endif
#ifdef OSSPEC_USE_EVENTS
#ifdef _WIN32
#else
struct st_osspec_event {
pthread_cond_t cond;
pthread_mutex_t mutex;
int flags;
int val;
};
#endif
t_event osspec_event_create(int32_t flags) {
t_event evt;
#ifdef _WIN32
evt = CreateEvent(NULL, TRUE, FALSE, NULL);
#else
evt = malloc(sizeof(struct st_osspec_event));
if (evt!=NULL) {
if (pthread_mutex_init(&evt->mutex, NULL) != 0) {
free(evt);
evt = NULL;
} else {
if (pthread_cond_init(&evt->cond, NULL)!= 0) {
pthread_mutex_destroy(&evt->mutex);
free(evt);
evt = NULL;
} else {
evt->flags = flags;
evt->val = 0;
}
}
}
#endif
return evt;
}
int32_t osspec_event_destroy(t_event event) {
int32_t res = (event != OSSPEC_INVALID_EVENT) ?
0 : OSSPEC_ERR_EVENT_INVALID_HANDLE;
#ifdef _WIN32
if (!res)
CloseHandle(event);
#else
if (!res) {
pthread_mutex_destroy(&event->mutex);
pthread_cond_destroy(&event->cond);
free(event);
}
#endif
return res;
}
int32_t osspec_event_set(t_event event) {
int32_t res = (event != OSSPEC_INVALID_EVENT) ?
0 : OSSPEC_ERR_EVENT_INVALID_HANDLE;
if (res == 0) {
#ifdef _WIN32
if (!SetEvent(event))
res = OSSPEC_ERR_EVENT_INVALID_HANDLE;
#else
pthread_mutex_lock(&event->mutex);
if (!event->val) {
event->val = 1;
pthread_cond_signal(&event->cond);
}
pthread_mutex_unlock(&event->mutex);
#endif
}
return res;
}
int32_t osspec_event_clear(t_event event) {
int32_t res = (event != OSSPEC_INVALID_EVENT) ?
0 : OSSPEC_ERR_EVENT_INVALID_HANDLE;
if (res == 0) {
#ifdef _WIN32
if (!ResetEvent(event))
res = OSSPEC_ERR_EVENT_INVALID_HANDLE;
#else
pthread_mutex_lock(&event->mutex);
event->val = 0;
pthread_mutex_unlock(&event->mutex);
#endif
}
return res;
}
int32_t osspec_event_wait(t_event event, uint32_t timeout) {
int32_t err = (event != OSSPEC_INVALID_EVENT) ?
0 : OSSPEC_ERR_EVENT_INVALID_HANDLE;
if (err == 0) {
#ifdef _WIN32
err = WaitForSingleObject(event, timeout)==WAIT_OBJECT_0 ? 0 : OSSPEC_ERR_EVENT_WAIT_TOUT;
#else
struct timespec timeToWait;
int out = 0;
if (timeout != OSSPEC_TIMEOUT_INFINITY)
f_get_abs_time(timeout, &timeToWait);
while (!out && !err) {
pthread_mutex_lock(&event->mutex);
if (!event->val) {
int wait_res = timeout == OSSPEC_TIMEOUT_INFINITY ?
pthread_cond_wait(&event->cond,&event->mutex) :
pthread_cond_timedwait(&event->cond,&event->mutex, &timeToWait);
if (event->val) {
out = 1;
} else if (wait_res == ETIMEDOUT) {
err = OSSPEC_ERR_EVENT_WAIT_TOUT;
} else if (wait_res == EINVAL) {
err = OSSPEC_ERR_EVENT_INVALID_HANDLE;
}
} else {
out = 1;
}
pthread_mutex_unlock(&event->mutex);
}
#endif
}
return err;
}
#endif
#ifdef OSSPEC_USE_THREADS
t_thread osspec_thread_create(t_osspec_thread_func func, void *arg, uint32_t flags) {
t_thread thread;
#ifdef _WIN32
thread = CreateThread(NULL, 0, func, arg, 0, NULL);
#else
if (pthread_create(&thread, NULL, func, arg) != 0) {
thread = OSSPEC_INVALID_THREAD;
}
#endif
return thread;
}
int32_t osspec_thread_wait(t_thread thread, uint32_t timeout) {
int32_t err = (thread != OSSPEC_INVALID_THREAD) ?
0 : OSSPEC_ERR_THREAD_INVALID_HANDLE;
if (!err) {
#ifdef _WIN32
err = WaitForSingleObject(thread, timeout)==WAIT_OBJECT_0 ? 0 : OSSPEC_ERR_THREAD_WAIT_TOUT;
#else
int wt_res;
#ifndef OSSPEC_THREAD_NO_TIMEOUT
if (timeout != OSSPEC_TIMEOUT_INFINITY) {
struct timespec timeToWait;
f_get_abs_time(timeout, &timeToWait);
wt_res = pthread_timedjoin_np(thread, NULL, &timeToWait);
} else {
#endif
wt_res = pthread_join(thread, NULL);
#ifndef OSSPEC_THREAD_NO_TIMEOUT
}
#endif
if (wt_res == ETIMEDOUT) {
err = OSSPEC_ERR_THREAD_WAIT_TOUT;
} else if (wt_res != 0) {
err = OSSPEC_ERR_THREAD_INVALID_HANDLE;
}
#endif
}
return err;
}
#endif