* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <pthread.h>
#include <unistd.h>
#include "hitls_build.h"
#include "bsl_errno.h"
#include "bsl_sal.h"
#if defined(HITLS_BSL_SAL_LINUX) && defined(HITLS_BSL_SAL_LOCK)
typedef struct {
pthread_rwlock_t rwlock;
} BslOsalRWLock;
int32_t SAL_RwLockNew(BSL_SAL_ThreadLockHandle *lock)
{
if (lock == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
BslOsalRWLock *newLock = (BslOsalRWLock *)BSL_SAL_Calloc(1, sizeof(BslOsalRWLock));
if (newLock == NULL) {
return BSL_MALLOC_FAIL;
}
if (pthread_rwlock_init(&newLock->rwlock, (const pthread_rwlockattr_t *)NULL) != 0) {
BSL_SAL_FREE(newLock);
return BSL_SAL_ERR_UNKNOWN;
}
*lock = newLock;
return BSL_SUCCESS;
}
int32_t SAL_RwReadLock(BSL_SAL_ThreadLockHandle rwLock)
{
BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
if (lock == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
if (pthread_rwlock_rdlock(&lock->rwlock) != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
int32_t SAL_RwWriteLock(BSL_SAL_ThreadLockHandle rwLock)
{
BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
if (lock == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
if (pthread_rwlock_wrlock(&lock->rwlock) != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
int32_t SAL_RwUnlock(BSL_SAL_ThreadLockHandle rwLock)
{
BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
if (lock == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
if (pthread_rwlock_unlock(&lock->rwlock) != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
void SAL_RwLockFree(BSL_SAL_ThreadLockHandle rwLock)
{
BslOsalRWLock *lock = (BslOsalRWLock *)rwLock;
if (lock != NULL) {
(void)pthread_rwlock_destroy(&(lock->rwlock));
BSL_SAL_FREE(lock);
}
}
#endif
#if defined(HITLS_BSL_SAL_LINUX) && defined(HITLS_BSL_SAL_THREAD)
uint64_t SAL_GetPid(void)
{
return (uint64_t)pthread_self();
}
int32_t SAL_PthreadRunOnce(uint32_t *onceControl, BSL_SAL_ThreadInitRoutine initFunc)
{
if (onceControl == NULL || initFunc == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
pthread_once_t *tmpOnce = (pthread_once_t *)onceControl;
if (pthread_once(tmpOnce, initFunc) != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
int32_t BSL_SAL_ThreadCreate(BSL_SAL_ThreadId *thread, void *(*startFunc)(void *), void *arg)
{
if (thread == NULL || startFunc == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
int32_t ret = pthread_create((pthread_t *)thread, NULL, startFunc, arg);
if (ret != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
void BSL_SAL_ThreadClose(BSL_SAL_ThreadId thread)
{
if (thread == NULL) {
return;
}
(void)pthread_join((pthread_t)(uintptr_t)thread, NULL);
}
int32_t BSL_SAL_CreateCondVar(BSL_SAL_CondVar *condVar)
{
if (condVar == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
pthread_cond_t *cond = (pthread_cond_t *)BSL_SAL_Malloc(sizeof(pthread_cond_t));
if (cond == NULL) {
return BSL_MALLOC_FAIL;
}
if (pthread_cond_init(cond, NULL) != 0) {
BSL_SAL_FREE(cond);
return BSL_SAL_ERR_UNKNOWN;
}
*condVar = cond;
return BSL_SUCCESS;
}
int32_t BSL_SAL_CondSignal(BSL_SAL_CondVar condVar)
{
if (condVar == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
if (pthread_cond_signal(condVar) != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
#define SAL_SECS_IN_NS 1000000000
#define SAL_SECS_IN_MS 1000
#define SAL_MS_IN_NS 1000000
int32_t BSL_SAL_CondTimedwaitMs(BSL_SAL_Mutex condMutex, BSL_SAL_CondVar condVar, int32_t timeout)
{
struct timespec stm = {0};
struct timespec etm = {0};
long int endNs;
long int endSecs;
if (condMutex == NULL || condVar == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
pthread_mutex_lock(condMutex);
clock_gettime(CLOCK_REALTIME, &stm);
endSecs = stm.tv_sec + timeout / SAL_SECS_IN_MS;
endNs = stm.tv_nsec + (timeout % SAL_SECS_IN_MS) * SAL_MS_IN_NS;
endSecs += endNs / SAL_SECS_IN_NS;
endNs %= SAL_SECS_IN_NS;
etm.tv_sec = endSecs;
etm.tv_nsec = endNs;
int32_t ret = pthread_cond_timedwait(condVar, condMutex, &etm);
pthread_mutex_unlock(condMutex);
if (ret != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
int32_t BSL_SAL_DeleteCondVar(BSL_SAL_CondVar condVar)
{
if (condVar == NULL) {
return BSL_SAL_ERR_BAD_PARAM;
}
int32_t ret = pthread_cond_destroy((pthread_cond_t *)condVar);
BSL_SAL_FREE(condVar);
if (ret != 0) {
return BSL_SAL_ERR_UNKNOWN;
}
return BSL_SUCCESS;
}
#endif