manually merged with ARM version

This commit is contained in:
2025-11-13 17:43:55 +03:00
parent f978759ae0
commit 04015fb4cb
463 changed files with 119514 additions and 45 deletions

View File

@ -0,0 +1,25 @@
#ifndef OS_SPEC_CFG_H_
#define OS_SPEC_CFG_H_
//#define OSSPEC_USE_MUTEX
//#define OSSPEC_USE_EVENTS
//#define OSSPEC_USE_THREADS
#define OSSPEC_ERR_MUTEX_INVALID_HANDLE -1
#define OSSPEC_ERR_MUTEX_LOCK_TOUT -2
#define OSSPEC_ERR_MUTEX_RELEASE -3
#define OSSPEC_ERR_EVENT_INVALID_HANDLE OSSPEC_ERR_MUTEX_INVALID_HANDLE
#define OSSPEC_ERR_EVENT_WAIT_TOUT OSSPEC_ERR_MUTEX_LOCK_TOUT
#define OSSPEC_ERR_THREAD_INVALID_HANDLE OSSPEC_ERR_MUTEX_INVALID_HANDLE
#define OSSPEC_ERR_THREAD_WAIT_TOUT OSSPEC_ERR_MUTEX_LOCK_TOUT
#endif

View File

@ -0,0 +1,309 @@
/***************************************************************************//**
@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

View File

@ -0,0 +1,59 @@
# Файл для включения в проект на CMAKE.
# Перед включением необходимо определить переменные
# OSSPEC_DIR - путь к директории, где находится osspec.cmake
# OSSPEC_USE_EVENTS - использовать события
# OSSPEC_USE_THREADS - использовать потоки
# OSSPEC_USE_MUTEX - использовать мьютексы
# После включения будут установлены следующие перменные:
# OSSPEC_HEADERS - используемые заголовочные файлы
# OSSPEC_SOURCES - используемые файлы исходных кодов
# OSSPEC_DEFINITIONS - используемые определения компилятора
cmake_policy(PUSH)
cmake_minimum_required(VERSION 2.8.12)
if(OSSPEC_USE_EVENTS OR OSSPEC_USE_THREADS OR OSSPEC_USE_MUTEX)
find_package(Threads)
# set(OSSPEC_LIBS ${CMAKE_THREAD_LIBS_INIT})
unset(OSSPEC_LIBS)
unset(OSSPEC_DEFINITIONS)
set(OSSPEC_HEADERS ${OSSPEC_DIR}/osspec.h)
set(OSSPEC_SOURCES ${OSSPEC_DIR}/osspec.c)
if(CMAKE_USE_PTHREADS_INIT)
include(CheckLibraryExists)
if(OSSPEC_USE_MUTEX)
set(OSSPEC_DEFINITIONS ${OSSPEC_DEFINITIONS} OSSPEC_USE_MUTEX)
check_library_exists(pthread pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK)
if(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
set(OSSPEC_DEFINITIONS ${OSSPEC_DEFINITIONS} HAVE_PTHREAD_MUTEX_TIMEDLOCK)
#заглушки для _timedlock функций отстутсвуют в libc, поэтому в любом случае включаем pthread
set(OSSPEC_LIBS ${OSSPEC_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
endif(OSSPEC_USE_MUTEX)
if(OSSPEC_USE_THREADS)
set(OSSPEC_DEFINITIONS ${OSSPEC_DEFINITIONS} OSSPEC_USE_THREADS)
if (NOT OSSPEC_LIBS)
set(OSSPEC_LIBS ${CMAKE_THREAD_LIBS_INIT})
endif (NOT OSSPEC_LIBS)
check_library_exists(pthread pthread_timedjoin_np "" HAVE_PTHREAD_TIMEDJOIN_NP)
if(HAVE_PTHREAD_TIMEDJOIN_NP)
set(OSSPEC_DEFINITIONS ${OSSPEC_DEFINITIONS} HAVE_PTHREAD_TIMEDJOIN_NP)
endif(HAVE_PTHREAD_TIMEDJOIN_NP)
endif(OSSPEC_USE_THREADS)
else(CMAKE_USE_PTHREADS_INIT)
if(OSSPEC_USE_MUTEX)
set(OSSPEC_DEFINITIONS ${OSSPEC_DEFINITIONS} OSSPEC_USE_MUTEX)
endif(OSSPEC_USE_MUTEX)
if(OSSPEC_USE_THREADS)
set(OSSPEC_DEFINITIONS ${OSSPEC_DEFINITIONS} OSSPEC_USE_THREADS)
endif(OSSPEC_USE_THREADS)
endif(CMAKE_USE_PTHREADS_INIT)
if(OSSPEC_USE_EVENTS)
set(OSSPEC_DEFINITIONS ${OSSPEC_DEFINITIONS} OSSPEC_USE_EVENTS)
endif(OSSPEC_USE_EVENTS)
endif(OSSPEC_USE_EVENTS OR OSSPEC_USE_THREADS OR OSSPEC_USE_MUTEX)
cmake_policy(POP)

View File

@ -0,0 +1,93 @@
/***************************************************************************//**
@file osspec.h
Файл содержит объявления функций, которые скрывают вызовы ОС:
функции работы с объектами синхронизации, потоками и т.д.
@author Borisov Alexey <borisov@lcard.ru>
@date 28.05.2012
***************************************************************************/
#ifndef OSSPEC_H_
#define OSSPEC_H_
#ifdef __cplusplus
extern "C" {
#endif
#if !defined _WIN32 && !defined _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "osspec_cfg.h"
#ifdef _WIN32
#include <Windows.h>
#define OSSPEC_TIMEOUT_INFINITY INFINITE
#else
#include <pthread.h>
#define OSSPEC_TIMEOUT_INFINITY ((uint32_t)-1)
#endif
#ifndef NO_OSSPEC_USE_MUTEX
#ifdef _WIN32
typedef HANDLE t_mutex;
#else
typedef pthread_mutex_t* t_mutex;
#endif
#define OSSPEC_INVALID_MUTEX NULL
t_mutex osspec_mutex_create(void);
int32_t osspec_mutex_lock(t_mutex handle, uint32_t tout);
int32_t osspec_mutex_release(t_mutex handle);
int32_t osspec_mutex_destroy(t_mutex handle);
#endif
#ifndef NO_OSSPEC_USE_EVENTS
#ifdef _WIN32
typedef HANDLE t_event;
#else
struct st_osspec_event;
typedef struct st_osspec_event *t_event;
#endif
#define OSSPEC_INVALID_EVENT NULL
t_event osspec_event_create(int32_t flags);
int32_t osspec_event_destroy(t_event event);
int32_t osspec_event_set(t_event event);
int32_t osspec_event_clear(t_event event);
int32_t osspec_event_wait(t_event event, uint32_t timeout);
#endif
#ifndef NO_OSSPEC_USE_THREADS
#ifdef _WIN32
typedef HANDLE t_thread;
#define OSSPEC_INVALID_THREAD NULL
#define OSSPEC_THREAD_FUNC_RET DWORD
#define OSSPEC_THREAD_FUNC_CALL WINAPI
#else
typedef pthread_t t_thread;
#define OSSPEC_INVALID_THREAD ((pthread_t)-1)
#define OSSPEC_THREAD_FUNC_RET void*
#define OSSPEC_THREAD_FUNC_CALL
#endif
typedef OSSPEC_THREAD_FUNC_RET (OSSPEC_THREAD_FUNC_CALL *t_osspec_thread_func)(void *arg);
t_thread osspec_thread_create(t_osspec_thread_func func, void *arg, uint32_t flags);
int32_t osspec_thread_wait(t_thread thread, uint32_t timeout);
#endif
#ifdef __cplusplus
}
#endif
#endif