/* * 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 #include #include "hitls_build.h" #include "bsl_errno.h" #include "bsl_sal.h" #if defined(HITLS_BSL_SAL_LINUX) && defined(HITLS_BSL_SAL_LOCK) // Used for DEFAULT lock implementation 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) { // By default, gettid is not used to obtain the global tid corresponding to the thread // because other thread functions use the pthread library. // Use pthread_self to obtain the PID used by pthread_create in this process. // However, the pids of the parent and child processes may be the same. 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 // 1s = 1000000000ns #define SAL_SECS_IN_MS 1000 // 1s = 1000ms #define SAL_MS_IN_NS 1000000 // 1ms = 1000000ns 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; // nanosecond long int endSecs; // second 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