* Copyright (c) 2021 Huawei Technologies Co.,Ltd.
*
* CM is licensed under 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.
* -------------------------------------------------------------------------
*
* cm_util.cpp
*
*
* IDENTIFICATION
* src/cm_common/cm_util.cpp
*
* -------------------------------------------------------------------------
*/
#include <sys/stat.h>
#include <securec.h>
#include "cm_misc_base.h"
#include "cm_util.h"
#ifndef THR_LOCAL
#ifndef WIN32
#define THR_LOCAL __thread
#else
#define THR_LOCAL __declspec(thread)
#endif
#endif
int CmMkdirP(char *path, unsigned int omode)
{
int retval = 0;
char *cur = path;
mode_t oldUmask = umask(0);
mode_t newUmask = oldUmask & ~(S_IWUSR | S_IXUSR);
(void)umask(newUmask);
if (cur[0] == '/') {
++cur;
}
for (int last = 0; !last; ++cur) {
if (cur[0] == '\0') {
last = 1;
} else if (cur[0] != '/') {
continue;
}
*cur = '\0';
if (!last && cur[1] == '\0') {
last = 1;
}
if (last) {
(void)umask(oldUmask);
}
struct stat sb = {0};
if (stat(path, &sb) == 0) {
if (!S_ISDIR(sb.st_mode)) {
errno = last ? EEXIST : ENOTDIR;
retval = -1;
break;
}
} else if (mkdir(path, last ? (mode_t)omode : (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
retval = -1;
break;
}
if (!last) {
*cur = '/';
}
}
(void)umask(oldUmask);
return retval;
}
char *gs_getenv_r(const char *name)
{
(void)pthread_mutex_lock(&g_cmEnvLock);
char *ret = getenv(name);
(void)pthread_mutex_unlock(&g_cmEnvLock);
return ret;
}
uint64 GetMonotonicTimeMs()
{
struct timespec ts;
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64)ts.tv_sec * CM_MS_COUNT_PER_SEC + (uint64)ts.tv_nsec / CM_NSEC_COUNT_PER_MS;
}
uint64 GetMonotonicTimeS()
{
struct timespec ts;
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64)ts.tv_sec;
}
void CMFairMutexInit(CMFairMutex &mutex)
{
(void)pthread_mutex_init(&mutex.lock, NULL);
(void)pthread_mutex_init(&mutex.innerLock, NULL);
(void)pthread_cond_init(&mutex.cond, NULL);
mutex.readerCount = 0;
mutex.writerCount = 0;
mutex.curType = CMFairMutexType::CM_MUTEX_NODE;
}
int CMFairMutexLock(CMFairMutex &mutex, CMFairMutexType type)
{
struct timespec ts;
uint32* count1 = NULL;
uint32* count2 = NULL;
const int LOCK_WAIT_TIME = 2;
if (type == CMFairMutexType::CM_MUTEX_READ) {
count1 = &mutex.readerCount;
count2 = &mutex.writerCount;
} else {
count1 = &mutex.writerCount;
count2 = &mutex.readerCount;
}
(void)pthread_mutex_lock(&mutex.innerLock);
(*count1)++;
while (true) {
if (type != mutex.curType || *count2 == 0) {
int ret = pthread_mutex_trylock(&mutex.lock);
if (ret == 0) {
mutex.curType = type;
(*count1)--;
break;
}
}
(void)clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += LOCK_WAIT_TIME;
(void)pthread_cond_timedwait(&mutex.cond, &mutex.innerLock, &ts);
}
(void)pthread_mutex_unlock(&mutex.innerLock);
return 0;
}
void CMFairMutexUnLock(CMFairMutex &mutex)
{
(void)pthread_mutex_lock(&mutex.innerLock);
(void)pthread_mutex_unlock(&mutex.lock);
(void)pthread_mutex_unlock(&mutex.innerLock);
(void)pthread_cond_broadcast(&mutex.cond);
}
char *GetDynamicMem(char *dynamicPtr, size_t *curSize, size_t memSize)
{
size_t tmpCurSize = (*curSize);
char *tmp = dynamicPtr + tmpCurSize;
(*curSize) = tmpCurSize + memSize;
return tmp;
}