提交 311e01df 编写于 作者: C cheng_jinsong

benchmark test for param

Signed-off-by: Ncheng_jinsong <chengjinsong2@huawei.com>
上级 ba71a874
......@@ -27,6 +27,8 @@ config("exported_header_files") {
"//base/startup/init/interfaces/innerkits/include/syspara",
"//base/startup/init/interfaces/innerkits/include/token",
"//base/startup/init/services/include",
"//base/startup/init/services/include/param",
"//base/startup/init/services/param/include",
]
}
......
......@@ -178,9 +178,6 @@ if (defined(ohos_lite)) {
]
}
if (startup_init_test_performance) {
defines += [ "PARAM_TEST_PERFORMANCE" ]
}
install_images = [ "system" ]
install_enable = true
......
......@@ -20,7 +20,6 @@
#ifdef PARAM_SUPPORT_TRIGGER
#include "cJSON.h"
#endif
#include "sys_param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
......@@ -65,6 +64,8 @@ typedef enum {
#define LOAD_PARAM_NORMAL 0x00
#define LOAD_PARAM_ONLY_ADD 0x01
typedef uint32_t ParamHandle;
/**
* Init 接口
* 初始化参数服务
......@@ -155,6 +156,37 @@ void SystemDumpTriggers(int verbose, int (*dump)(const char *fmt, ...));
*/
int SystemSetParameter(const char *name, const char *value);
/**
* Init 接口
* 查询参数。
*
*/
int SystemReadParam(const char *name, char *value, uint32_t *len);
/**
* 对外接口
* 查询参数,主要用于其他进程使用,找到对应属性的handle。
*
*/
int SystemFindParameter(const char *name, ParamHandle *handle);
/**
* 对外接口
* 根据handle获取对应数据的修改标识。
* commitId 获取计数变化
*
*/
int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId);
/**
* 外部接口
* 获取参数值。
*
*/
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len);
long long GetSystemCommitId(void);
/**
* 对外接口
* 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。
......
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
......@@ -15,87 +15,72 @@
#ifndef BASE_STARTUP_INIT_SYS_PARAM_H
#define BASE_STARTUP_INIT_SYS_PARAM_H
#include <stdarg.h>
#include <stdint.h>
#include <unistd.h>
#include "param_common.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef uint32_t ParamHandle;
typedef void *CachedHandle;
typedef struct {
uint8_t updaterMode;
void (*logFunc)(int logLevel, uint32_t domain, const char *tag, const char *fmt, va_list vargs);
int (*setfilecon)(const char *name, const char *content);
int (*getServiceGroupIdByPid)(pid_t pid, gid_t *gids, uint32_t gidSize);
} PARAM_WORKSPACE_OPS;
/**
* parameter service初始化接口 仅供init调用
*/
int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *ops);
/**
* Init 接口
* 查询参数。
*
*/
int SystemReadParam(const char *name, char *value, uint32_t *len);
/**
* parameter client初始化接口 供服务调用
* parameter client init
*/
void InitParameterClient(void);
/**
* 对外接口
* 查询参数,主要用于其他进程使用,找到对应属性的handle。
*
*/
int SystemFindParameter(const char *name, ParamHandle *handle);
/**
* 对外接口
* 根据handle获取对应数据的修改标识。
* commitId 获取计数变化
* by name and default value,save parameter info in handle。
*
*/
int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId);
CachedHandle CachedParameterCreate(const char *name, const char *defValue);
/**
* 外部接口
* 获取参数值。
* destroy handle
*
*/
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len);
long long GetSystemCommitId(void);
void CachedParameterDestroy(CachedHandle handle);
/**
* 外部接口
* 保存相关的parameter信息,包括workspace,和各层的commit。
* if name exist,return value else return default value
*
*/
CachedHandle CachedParameterCreate(const char *name, const char *defValue);
static inline const char *CachedParameterGet(CachedHandle handle)
{
struct CachedParameter_ *param = (struct CachedParameter_ *)handle;
if (param == NULL) {
return NULL;
}
/**
* 外部接口
* 如果获取到value,返回对应的 paramValue的指针,否则返回上面定义的defValue
*
*/
const char *CachedParameterGet(CachedHandle handle);
const char *CachedParameterGetChanged(CachedHandle handle, int *changed);
// no change, do not to find
long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&param->workspace->area->commitId, MEMORY_ORDER_ACQUIRE);
if (param->spaceCommitId == spaceCommitId) {
return param->paramValue;
}
param->spaceCommitId = spaceCommitId;
int changed = 0;
if (param->cachedParameterCheck == NULL) {
return param->paramValue;
}
return param->cachedParameterCheck(param, &changed);
}
/**
* 外部接口
* 释放handle内存
*
*/
void CachedParameterDestroy(CachedHandle handle);
static inline const char *CachedParameterGetChanged(CachedHandle handle, int *changed)
{
struct CachedParameter_ *param = (struct CachedParameter_ *)handle;
if (param == NULL) {
return NULL;
}
// no change, do not to find
long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&param->workspace->area->commitId, MEMORY_ORDER_ACQUIRE);
if (param->spaceCommitId == spaceCommitId) {
return param->paramValue;
}
param->spaceCommitId = spaceCommitId;
if ((changed == NULL) || (param->cachedParameterCheck == NULL)) {
return param->paramValue;
}
return param->cachedParameterCheck(param, changed);
}
#ifdef __cplusplus
#if __cplusplus
......
......@@ -31,7 +31,6 @@
#include "init_utils.h"
#include "securec.h"
#include "service_control.h"
#include "sys_param.h"
#ifdef ASAN_DETECTOR
#include "init_param.h"
#endif
......
......@@ -20,7 +20,7 @@
#ifdef WITH_SECCOMP_DEBUG
#include "init_utils.h"
#include "sys_param.h"
#include "init_param.h"
#endif
#include <dlfcn.h>
......
......@@ -198,7 +198,7 @@ static int DacGetParamSecurityLabel(const char *path)
if (strcmp(tmp, ".para.dac") != 0) {
continue;
}
int ret = ParamSprintf(fileName, MAX_BUF_SIZE, "%s/%s", path, dp->d_name);
int ret = PARAM_SPRINTF(fileName, MAX_BUF_SIZE, "%s/%s", path, dp->d_name);
if (ret <= 0) {
PARAM_LOGE("Failed to get file name for %s", dp->d_name);
continue;
......@@ -225,7 +225,7 @@ INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
{
PARAM_CHECK(ops != NULL, return -1, "Invalid param");
PARAM_LOGV("RegisterSecurityDacOps %d", isInit);
int ret = ParamStrCpy(ops->name, sizeof(ops->name), "dac");
int ret = PARAM_STRCPY(ops->name, sizeof(ops->name), "dac");
ops->securityInitLabel = InitLocalSecurityLabel;
ops->securityCheckFilePermission = CheckFilePermission;
#ifdef STARTUP_INIT_TEST
......@@ -251,7 +251,7 @@ static void AddGroupUser(const char *userName, gid_t gid)
return;
}
char buffer[USER_BUFFER_LEN] = {0};
int ret = ParamSprintf(buffer, sizeof(buffer), GROUP_FORMAT, gid, uid);
int ret = PARAM_SPRINTF(buffer, sizeof(buffer), GROUP_FORMAT, gid, uid);
PARAM_CHECK(ret >= 0, return, "Failed to format name for %d.%d", gid, uid);
(void)AddParamEntry(WORKSPACE_INDEX_BASE, PARAM_TYPE_STRING, buffer, "1");
}
......
......@@ -120,7 +120,7 @@ static void SetSelinuxFileCon(const char *name, const char *context)
PARAM_CHECK(GetParamWorkSpace() != NULL && GetParamWorkSpace()->ops.setfilecon != NULL,
return, "Invalid workspace or setfilecon");
static char buffer[FILENAME_LEN_MAX] = {0};
int len = ParamSprintf(buffer, sizeof(buffer), "%s/%s", PARAM_STORAGE_PATH, context);
int len = PARAM_SPRINTF(buffer, sizeof(buffer), "%s/%s", PARAM_STORAGE_PATH, context);
if (len > 0) {
buffer[len] = '\0';
PARAM_LOGV("setfilecon name %s path: %s %s ", name, context, buffer);
......@@ -137,7 +137,8 @@ static uint32_t GetWorkSpaceSize(const char *content)
}
char name[PARAM_NAME_LEN_MAX] = {0};
int index = 6; // 6 strlen for const.
(void)ParamMemcpy(name, sizeof(name), "const.", index);
int ret = PARAM_MEMCPY(name, sizeof(name), "const.", index);
PARAM_CHECK(ret == 0, return PARAM_WORKSPACE_MIN, "Invalid name");
size_t len = strlen(content);
for (size_t i = strlen("u:object_r:"); i < len; i++) {
if (*(content + i) == ':') {
......@@ -160,7 +161,7 @@ static uint32_t GetWorkSpaceSize(const char *content)
return PARAM_WORKSPACE_MIN;
#endif
}
int ret = ParamMemcpy(name, sizeof(name) - 1, node->data + node->keyLength + 1, node->valueLength);
ret = PARAM_MEMCPY(name, sizeof(name) - 1, node->data + node->keyLength + 1, node->valueLength);
if (ret == 0) {
name[node->valueLength] = '\0';
errno = 0;
......@@ -294,7 +295,7 @@ INIT_LOCAL_API int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
{
PARAM_CHECK(GetParamWorkSpace() != NULL, return -1, "Invalid workspace");
PARAM_CHECK(ops != NULL, return -1, "Invalid param");
int ret = ParamStrCpy(ops->name, sizeof(ops->name), "selinux");
int ret = PARAM_STRCPY(ops->name, sizeof(ops->name), "selinux");
ops->securityGetLabel = NULL;
ops->securityInitLabel = InitLocalSecurityLabel;
ops->securityCheckFilePermission = CheckFilePermission;
......
......@@ -21,6 +21,8 @@ config("exported_header_files") {
"//base/startup/init/services/include",
"//base/startup/init/services/loopevent/include",
"//base/startup/init/services/log",
"//base/startup/init/services/param/include",
"//base/startup/init/services/param/base",
]
}
......@@ -36,6 +38,7 @@ base_include_dirs = [
"//base/startup/init/services/param/adapter",
"//base/startup/init/services/param/linux",
"//base/startup/init/services/param/base",
"//base/startup/init/services/loopevent/include",
"//third_party/bounds_checking_function/include",
]
......
此差异已折叠。
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
......@@ -15,9 +15,10 @@
#ifndef BASE_STARTUP_PARAM_BASE_H
#define BASE_STARTUP_PARAM_BASE_H
#include "sys_param.h"
#include "param_osadp.h"
#include "beget_ext.h"
#include "param_trie.h"
#ifndef PARAM_BASE
#include "securec.h"
#endif
......@@ -28,24 +29,41 @@ extern "C" {
#endif
#endif
INIT_LOCAL_API void CloseParamWorkSpace(void);
INIT_LOCAL_API int ParamSprintf(char *buffer, size_t buffSize, const char *format, ...);
INIT_LOCAL_API int ParamMemcpy(void *dest, size_t destMax, const void *src, size_t count);
INIT_LOCAL_API int ParamStrCpy(char *strDest, size_t destMax, const char *strSrc);
typedef struct CachedParameter_ {
struct WorkSpace_ *workspace;
long long spaceCommitId;
uint32_t dataCommitId;
uint32_t dataIndex;
uint32_t bufferLen;
uint32_t nameLen;
char *paramValue;
char data[0];
} CachedParameter;
#ifdef PARAM_TEST_PERFORMANCE
void TestParameterReaderPerformance(void);
#ifndef PARAM_BASE
#define PARAM_SPRINTF(buffer, buffSize, format, ...) \
snprintf_s((buffer), (buffSize), (buffSize) - 1, (format), ##__VA_ARGS__)
#define PARAM_MEMCPY(dest, destMax, src, count) memcpy_s((dest), (destMax), (src), (count))
#define PARAM_STRCPY(strDest, destMax, strSrc) strcpy_s((strDest), (destMax), (strSrc))
#else
#define PARAM_SPRINTF(buffer, buffSize, format, ...) snprintf((buffer), (buffSize), (format), ##__VA_ARGS__)
#define PARAM_MEMCPY(dest, destMax, src, count) (memcpy((dest), (src), (count)) != NULL) ? 0 : 1
#define PARAM_STRCPY(strDest, destMax, strSrc) (strcpy((strDest), (strSrc)) != NULL) ? 0 : 1
#endif
static inline uint32_t ReadCommitId(ParamNode *entry)
{
uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE);
while (commitId & PARAM_FLAGS_MODIFY) {
futex_wait(&entry->commitId, commitId);
commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE);
}
return commitId & PARAM_FLAGS_COMMITID;
}
static inline int ReadParamValue_(ParamNode *entry, uint32_t *commitId, char *value, uint32_t *length)
{
uint32_t id = *commitId;
do {
*commitId = id;
int ret = PARAM_MEMCPY(value, *length, entry->data + entry->keyLength + 1, entry->valueLength);
PARAM_CHECK(ret == 0, return -1, "Failed to copy value");
value[entry->valueLength] = '\0';
*length = entry->valueLength;
id = ReadCommitId(entry);
} while (*commitId != id); // if change,must read
return 0;
}
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -19,15 +19,21 @@
#include "param_trie.h"
#include "param_base.h"
INIT_LOCAL_API uint32_t GetWorkSpaceIndex(const char *name)
INIT_LOCAL_API WorkSpace *GetWorkSpaceByName(const char *name)
{
#ifdef PARAM_SUPPORT_SELINUX
ParamWorkSpace *paramSpace = GetParamWorkSpace();
PARAM_CHECK(paramSpace != NULL, return (uint32_t)-1, "Invalid paramSpace");
return (paramSpace->selinuxSpace.getParamLabelIndex != NULL) ?
paramSpace->selinuxSpace.getParamLabelIndex(name) + WORKSPACE_INDEX_BASE : (uint32_t)-1;
PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace");
#ifdef PARAM_SUPPORT_SELINUX
if (paramSpace->selinuxSpace.getParamLabelIndex == NULL) {
return NULL;
}
uint32_t labelIndex = (uint32_t)paramSpace->selinuxSpace.getParamLabelIndex(name) + WORKSPACE_INDEX_BASE;
if (labelIndex < paramSpace->maxLabelIndex) {
return paramSpace->workSpace[labelIndex];
}
return NULL;
#else
return 0;
return paramSpace->workSpace[WORKSPACE_INDEX_DAC];
#endif
}
......@@ -48,7 +54,7 @@ INIT_LOCAL_API WorkSpace *GetWorkSpace(uint32_t labelIndex)
if (workSpace == NULL) {
return NULL;
}
uint32_t rwSpaceLock = ATOMIC_LOAD_EXPLICIT(&workSpace->rwSpaceLock, memory_order_acquire);
uint32_t rwSpaceLock = ATOMIC_LOAD_EXPLICIT(&workSpace->rwSpaceLock, MEMORY_ORDER_ACQUIRE);
if (rwSpaceLock == 1) {
return NULL;
}
......@@ -142,49 +148,3 @@ INIT_LOCAL_API int SplitParamString(char *line, const char *exclude[], uint32_t
}
return result(context, name, value);
}
INIT_LOCAL_API int ParamSprintf(char *buffer, size_t buffSize, const char *format, ...)
{
int len = -1;
va_list vargs;
va_start(vargs, format);
#ifdef PARAM_BASE
len = vsnprintf(buffer, buffSize - 1, format, vargs);
#else
len = vsnprintf_s(buffer, buffSize, buffSize - 1, format, vargs);
#endif
va_end(vargs);
return len;
}
INIT_LOCAL_API int ParamMemcpy(void *dest, size_t destMax, const void *src, size_t count)
{
int ret = 0;
#ifdef PARAM_BASE
memcpy(dest, src, count);
#else
ret = memcpy_s(dest, destMax, src, count);
#endif
return ret;
}
INIT_LOCAL_API int ParamStrCpy(char *strDest, size_t destMax, const char *strSrc)
{
int ret = 0;
#ifdef PARAM_BASE
if (strlen(strSrc) >= destMax) {
return -1;
}
size_t i = 0;
while ((i < destMax) && *strSrc != '\0') {
*strDest = *strSrc;
strDest++;
strSrc++;
i++;
}
*strDest = '\0';
#else
ret = strcpy_s(strDest, destMax, strSrc);
#endif
return ret;
}
......@@ -27,7 +27,7 @@ static uint32_t AllocateParamTrieNode(WorkSpace *workSpace, const char *key, uin
static int GetRealFileName(WorkSpace *workSpace, char *buffer, uint32_t size)
{
int ret = ParamSprintf(buffer, size, "%s/%s", PARAM_STORAGE_PATH, workSpace->fileName);
int ret = PARAM_SPRINTF(buffer, size, "%s/%s", PARAM_STORAGE_PATH, workSpace->fileName);
PARAM_CHECK(ret > 0, return -1, "Failed to copy file name %s", workSpace->fileName);
buffer[ret] = '\0';
return 0;
......@@ -46,8 +46,8 @@ static int InitWorkSpace_(WorkSpace *workSpace, uint32_t spaceSize, int readOnly
PARAM_ONLY_CHECK(areaAddr != NULL, return PARAM_CODE_ERROR_MAP_FILE);
if (!readOnly) {
workSpace->area = (ParamTrieHeader *)areaAddr;
ATOMIC_INIT(&workSpace->area->commitId, 0);
ATOMIC_INIT(&workSpace->area->commitPersistId, 0);
ATOMIC_UINT64_INIT(&workSpace->area->commitId, 0);
ATOMIC_UINT64_INIT(&workSpace->area->commitPersistId, 0);
workSpace->area->trieNodeCount = 0;
workSpace->area->paramNodeCount = 0;
workSpace->area->securityNodeCount = 0;
......@@ -72,7 +72,7 @@ static uint32_t AllocateParamTrieNode(WorkSpace *workSpace, const char *key, uin
workSpace->area->currOffset, workSpace->area->dataSize, workSpace->fileName);
ParamTrieNode *node = (ParamTrieNode *)(workSpace->area->data + workSpace->area->currOffset);
node->length = keyLen;
int ret = ParamMemcpy(node->key, keyLen, key, keyLen);
int ret = PARAM_MEMCPY(node->key, keyLen, key, keyLen);
PARAM_CHECK(ret == 0, return 0, "Failed to copy key");
node->key[keyLen] = '\0';
node->left = 0;
......@@ -281,7 +281,7 @@ INIT_LOCAL_API uint32_t AddParamNode(WorkSpace *workSpace, uint8_t type,
node->type = type;
node->keyLength = keyLen;
node->valueLength = valueLen;
int ret = ParamSprintf(node->data, realLen, "%s=%s", key, value);
int ret = PARAM_SPRINTF(node->data, realLen, "%s=%s", key, value);
PARAM_CHECK(ret > 0, return 0, "Failed to sprint key and value");
uint32_t offset = workSpace->area->currOffset;
workSpace->area->currOffset += realLen;
......
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BASE_STARTUP_PARAM_ATOMIC_H
#define BASE_STARTUP_PARAM_ATOMIC_H
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
#include <pthread.h>
#include <stdatomic.h>
#endif
#if defined FUTEX_WAIT || defined FUTEX_WAKE
#include <linux/futex.h>
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#ifdef __LITEOS_M__
#define ATOMIC_UINT32 uint32_t
#define ATOMIC_LLONG long long
#define ATOMIC_INIT(commitId, value) *(commitId) = (value)
#define ATOMIC_LOAD_EXPLICIT(commitId, order) *(commitId)
#define ATOMIC_STORE_EXPLICIT(commitId, value, order) *(commitId) = (value)
#define ATOMIC_UINT64_INIT(commitId, value) *(commitId) = (value)
#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) *(commitId)
#define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) *(commitId) = (value)
#define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) *(commitId)
#define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) *(commitId)
#define futex_wake(ftx, count) (void)(ftx)
#define futex_wait(ftx, value) (void)(ftx)
#else
// support futex
#ifndef __NR_futex
#define PARAM_NR_FUTEX 202 /* syscall number */
#else
#define PARAM_NR_FUTEX __NR_futex
#endif
#if !(defined FUTEX_WAIT || defined FUTEX_WAKE)
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define PARAM_FUTEX(ftx, op, value, timeout, bitset) \
do { \
struct timespec d_timeout = { 0, 1000 * 1000 * (timeout) }; \
syscall(PARAM_NR_FUTEX, ftx, op, value, &d_timeout, NULL, bitset); \
} while (0)
#define futex_wake(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE, count, 0, 0)
#define futex_wait(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT, value, 100, 0)
#endif
#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
#define MEMORY_ORDER_RELAXED memory_order_relaxed
#define MEMORY_ORDER_CONSUME memory_order_consume
#define MEMORY_ORDER_ACQUIRE memory_order_acquire
#define MEMORY_ORDER_RELEASE memory_order_release
#define ATOMIC_UINT32 atomic_uint
#define ATOMIC_LLONG atomic_llong
#define ATOMIC_INIT(commitId, value) atomic_init((commitId), (value))
#define ATOMIC_UINT64_INIT(commitId, value) atomic_init((commitId), (value))
#define ATOMIC_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), (order))
#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), order)
#define ATOMIC_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order))
#define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order))
#define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) atomic_fetch_or_explicit((commitId), (value), (order))
#define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) atomic_fetch_add_explicit((commitId), (value), (order))
#else
#define MEMORY_ORDER_RELAXED 0
#define MEMORY_ORDER_CONSUME 1
#define MEMORY_ORDER_ACQUIRE 2
#define MEMORY_ORDER_RELEASE 3
#define ATOMIC_UINT32 uint32_t
#define ATOMIC_LLONG int64_t
static inline void param_atomic_store(ATOMIC_UINT32 *ptr, uint32_t value, int order)
{
__sync_lock_test_and_set(ptr, value);
if (order == MEMORY_ORDER_RELEASE) {
__sync_synchronize();
}
}
static inline void param_atomic_uint64_store(ATOMIC_LLONG *ptr, int64_t value, int order)
{
__sync_lock_test_and_set(ptr, value);
if (order == MEMORY_ORDER_RELEASE) {
__sync_synchronize();
}
}
static inline void param_atomic_init(ATOMIC_UINT32 *ptr, uint32_t value)
{
*ptr = 0;
__sync_fetch_and_add(ptr, value, 0);
}
static inline void param_atomic_uint64_init(ATOMIC_LLONG *ptr, int64_t value)
{
*ptr = 0;
__sync_fetch_and_add(ptr, value, 0);
}
static inline ATOMIC_UINT32 param_atomic_load(ATOMIC_UINT32 *ptr, int order)
{
return *((volatile ATOMIC_UINT32 *)ptr);
}
static inline ATOMIC_LLONG param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order)
{
return *((volatile ATOMIC_LLONG *)ptr);
}
#define ATOMIC_INIT(commitId, value) param_atomic_init((commitId), (value))
#define ATOMIC_UINT64_INIT(commitId, value) param_atomic_uint64_init((commitId), (value))
#define ATOMIC_LOAD_EXPLICIT(commitId, order) param_atomic_load((commitId), order)
#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) param_atomic_uint64_load((commitId), order)
#define ATOMIC_STORE_EXPLICIT(commitId, value, order) param_atomic_store((commitId), (value), (order))
#define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) param_atomic_uint64_store((commitId), (value), (order))
#define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) __sync_or_and_fetch((commitId), (value))
#define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) __sync_add_and_fetch((commitId), (value))
#endif
#endif // __LITEOS_M__
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_PARAM_ATOMIC_H
\ No newline at end of file
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BASE_STARTUP_PARAM_COMMON_H
#define BASE_STARTUP_PARAM_COMMON_H
#include <stdio.h>
#include <stdint.h>
#ifndef __LITEOS_M__
#include <pthread.h>
#endif
#include "param_atomic.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
// support mutex
#ifndef __LITEOS_M__
typedef struct {
pthread_rwlock_t rwlock;
} ParamRWMutex;
typedef struct {
pthread_mutex_t mutex;
} ParamMutex;
#else
typedef struct {
uint32_t mutex;
} ParamRWMutex;
typedef struct {
uint32_t mutex;
} ParamMutex;
#endif
typedef struct {
int shmid;
} MemHandle;
typedef struct {
uint32_t left;
uint32_t right;
uint32_t child;
uint32_t labelIndex;
uint32_t dataIndex;
uint16_t selinuxLabel;
uint16_t length;
char key[0];
} ParamTrieNode;
#define PARAM_FLAGS_MODIFY 0x80000000
#define PARAM_FLAGS_TRIGGED 0x40000000
#define PARAM_FLAGS_WAITED 0x20000000
#define PARAM_FLAGS_COMMITID 0x0000ffff
#define PARAM_TYPE_MASK 0x0f
#define PARAM_TYPE_STRING 0x00
#define PARAM_TYPE_INT 0x01
#define PARAM_TYPE_BOOL 0x02
typedef struct {
ATOMIC_UINT32 commitId;
uint8_t type;
uint8_t keyLength;
uint16_t valueLength;
char data[0];
} ParamNode;
typedef struct {
uid_t uid;
gid_t gid;
uint32_t selinuxIndex;
uint16_t mode;
uint8_t type;
uint8_t length;
} ParamSecurityNode;
typedef struct {
ATOMIC_LLONG commitId;
ATOMIC_LLONG commitPersistId;
uint32_t trieNodeCount;
uint32_t paramNodeCount;
uint32_t securityNodeCount;
uint32_t currOffset;
uint32_t firstNode;
uint32_t dataSize;
char data[0];
} ParamTrieHeader;
typedef struct WorkSpace_ {
unsigned int flags;
MemHandle memHandle;
ParamTrieHeader *area;
ATOMIC_UINT32 rwSpaceLock;
uint32_t spaceSize;
uint32_t spaceIndex;
ParamRWMutex rwlock;
char fileName[0];
} WorkSpace;
typedef struct {
uint8_t updaterMode;
void (*logFunc)(int logLevel, uint32_t domain, const char *tag, const char *fmt, va_list vargs);
int (*setfilecon)(const char *name, const char *content);
int (*getServiceGroupIdByPid)(pid_t pid, gid_t *gids, uint32_t gidSize);
} PARAM_WORKSPACE_OPS;
typedef struct CachedParameter_ {
struct WorkSpace_ *workspace;
const char *(*cachedParameterCheck)(struct CachedParameter_ *param, int *changed);
long long spaceCommitId;
uint32_t dataCommitId;
uint32_t dataIndex;
uint32_t bufferLen;
uint32_t nameLen;
char *paramValue;
char data[0];
} CachedParameter;
typedef void *CachedHandle;
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_PARAM_COMMON_H
\ No newline at end of file
......@@ -21,7 +21,7 @@
#include "init_param.h"
#include "list.h"
#include "param_base.h"
#include "param_osadp.h"
#include "param_persist.h"
#include "param_security.h"
......@@ -118,7 +118,7 @@ INIT_LOCAL_API int OpenWorkSpace(uint32_t index, int readOnly);
INIT_LOCAL_API WorkSpace *GetNextWorkSpace(WorkSpace *curr);
INIT_LOCAL_API WorkSpace *GetWorkSpace(uint32_t labelIndex);
INIT_LOCAL_API uint32_t GetWorkSpaceIndex(const char *name);
INIT_LOCAL_API WorkSpace *GetWorkSpaceByName(const char *name);
INIT_LOCAL_API int CheckParamValue(const ParamTrieNode *node, const char *name, const char *value, uint8_t paramType);
INIT_LOCAL_API int CheckParamName(const char *name, int paramInfo);
......@@ -148,6 +148,8 @@ INIT_INNER_API ParamWorkSpace *GetParamWorkSpace(void);
INIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData);
INIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo);
INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *ops);
INIT_LOCAL_API void CloseParamWorkSpace(void);
#ifdef STARTUP_INIT_TEST
ParamService *GetParamService();
#endif
......
......@@ -29,15 +29,9 @@
#ifndef __LITEOS_M__
#include <pthread.h>
#include <stdatomic.h>
#endif
#if defined FUTEX_WAIT || defined FUTEX_WAKE
#include <linux/futex.h>
#endif
#include "param_utils.h"
#include "param_common.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
......@@ -48,7 +42,7 @@ extern "C" {
#ifdef STARTUP_INIT_TEST
#define STATIC_INLINE
#else
#define STATIC_INLINE static __attribute__((always_inline))
#define STATIC_INLINE static inline
#endif
#endif
......@@ -61,6 +55,9 @@ extern "C" {
24 * (count(.) + 1) + strlen(xxxx.xxxx.xxxx.xxxx)
data size
strlen(xxxx.xxxx.xxxx.xxxx) + 96
dac size
24 * (count(.) + 1) + sizeof(ParamSecurityNode)
*/
#define DAC_DEFAULT_GROUP 0
#define DAC_DEFAULT_USER 0
......@@ -88,7 +85,11 @@ extern "C" {
#define PARAM_WORKSPACE_DEF PARAM_WORKSPACE_MAX
#else // __LITEOS_A__
#define DAC_DEFAULT_MODE 0774
#ifdef PARAM_TEST_PERFORMANCE
#define PARAM_WORKSPACE_MAX (1024 * 1024 * 10)
#else
#define PARAM_WORKSPACE_MAX (80 * 1024)
#endif
#define PARAM_WORKSPACE_SMALL (1024 * 10)
#define PARAM_WORKSPACE_DEF (1024 * 30)
#define PARAM_WORKSPACE_DAC (1024 * 20)
......@@ -100,32 +101,6 @@ extern "C" {
#define PARAM_WORKSPACE_DAC PARAM_WORKSPACE_SMALL
#endif
// support futex
#ifndef __NR_futex
#define PARAM_NR_FUTEX 202 /* syscall number */
#else
#define PARAM_NR_FUTEX __NR_futex
#endif
#if !(defined FUTEX_WAIT || defined FUTEX_WAKE)
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#ifndef __LITEOS_M__
#define PARAM_FUTEX(ftx, op, value, timeout, bitset) \
do { \
struct timespec d_timeout = { 0, 1000 * 1000 * (timeout) }; \
syscall(PARAM_NR_FUTEX, ftx, op, value, &d_timeout, NULL, bitset); \
} while (0)
#define futex_wake(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE, count, 0, 0)
#define futex_wait(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT, value, 100, 0)
#else
#define futex_wake(ftx, count) (void)(ftx)
#define futex_wait(ftx, value) (void)(ftx)
#endif
#endif
// support timer
#if defined __LITEOS_A__ || defined __LITEOS_M__
struct ParamTimer_;
......@@ -147,25 +122,6 @@ int ParamTimerCreate(ParamTaskPtr *timer, ProcessTimer process, void *context);
int ParamTimerStart(const ParamTaskPtr timer, uint64_t timeout, uint64_t repeat);
void ParamTimerClose(ParamTaskPtr timer);
// support mutex
#ifndef __LITEOS_M__
typedef struct {
pthread_rwlock_t rwlock;
} ParamRWMutex;
typedef struct {
pthread_mutex_t mutex;
} ParamMutex;
#else
typedef struct {
uint32_t mutex;
} ParamRWMutex;
typedef struct {
uint32_t mutex;
} ParamMutex;
#endif
INIT_LOCAL_API void paramMutexEnvInit(void);
INIT_LOCAL_API int ParamRWMutexCreate(ParamRWMutex *lock);
INIT_LOCAL_API int ParamRWMutexWRLock(ParamRWMutex *lock);
......@@ -190,31 +146,13 @@ INIT_LOCAL_API int ParamMutexDelete(ParamMutex *mutex);
#define PARAMSPACE_AREA_RW_UNLOCK(rwlock) (void)(rwlock)
#endif
typedef struct {
int shmid;
} MemHandle;
INIT_LOCAL_API void *GetSharedMem(const char *fileName, MemHandle *handle, uint32_t spaceSize, int readOnly);
INIT_LOCAL_API void FreeSharedMem(const MemHandle *handle, void *mem, uint32_t dataSize);
// for atomic
#ifdef __LITEOS_M__
#define ATOMIC_UINT32 uint32_t
#define ATOMIC_LLONG long long
#define ATOMIC_INIT(commitId, value) *(commitId) = (value)
#define ATOMIC_LOAD_EXPLICIT(commitId, order) *(commitId)
#define ATOMIC_STORE_EXPLICIT(commitId, value, order) *(commitId) = (value)
#else
#define ATOMIC_UINT32 atomic_uint
#define ATOMIC_LLONG atomic_llong
#define ATOMIC_INIT(commitId, value) atomic_init((commitId), (value))
#define ATOMIC_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), (order))
#define ATOMIC_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order))
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_PARAM_MESSAGE_H
\ No newline at end of file
#endif // BASE_STARTUP_PARAM_OS_ADAPTER_H
\ No newline at end of file
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
......@@ -20,6 +20,7 @@
#include "init_hashmap.h"
#include "init_param.h"
#include "list.h"
#include "param_common.h"
#include "param_osadp.h"
#include "param_security.h"
......@@ -29,66 +30,6 @@ extern "C" {
#endif
#endif
typedef struct {
uint32_t left;
uint32_t right;
uint32_t child;
uint32_t labelIndex;
uint32_t dataIndex;
uint16_t length;
char key[0];
} ParamTrieNode;
#define PARAM_FLAGS_MODIFY 0x80000000
#define PARAM_FLAGS_TRIGGED 0x40000000
#define PARAM_FLAGS_WAITED 0x20000000
#define PARAM_FLAGS_COMMITID 0x0000ffff
#define PARAM_TYPE_MASK 0x0f
#define PARAM_TYPE_STRING 0x00
#define PARAM_TYPE_INT 0x01
#define PARAM_TYPE_BOOL 0x02
typedef struct {
ATOMIC_UINT32 commitId;
uint8_t type;
uint8_t keyLength;
uint16_t valueLength;
char data[0];
} ParamNode;
typedef struct {
uid_t uid;
gid_t gid;
uint32_t selinuxIndex;
uint16_t mode;
uint8_t type;
uint8_t length;
} ParamSecurityNode;
typedef struct {
ATOMIC_LLONG commitId;
ATOMIC_LLONG commitPersistId;
uint32_t trieNodeCount;
uint32_t paramNodeCount;
uint32_t securityNodeCount;
uint32_t currOffset;
uint32_t firstNode;
uint32_t dataSize;
char data[0];
} ParamTrieHeader;
typedef struct WorkSpace_ {
unsigned int flags;
MemHandle memHandle;
ParamTrieHeader *area;
ParamRWMutex rwlock;
ATOMIC_UINT32 rwSpaceLock;
uint32_t spaceSize;
uint32_t spaceIndex;
char fileName[0];
} WorkSpace;
INIT_LOCAL_API int InitWorkSpace(WorkSpace *workSpace, int onlyRead, uint32_t spaceSize);
INIT_LOCAL_API void CloseWorkSpace(WorkSpace *workSpace);
......
......@@ -15,7 +15,6 @@
#include "init_param.h"
#include <errno.h>
#include <stdatomic.h>
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
......@@ -23,21 +22,22 @@
#include "init_log.h"
#include "init_utils.h"
#include "param_base.h"
#include "param_atomic.h"
#include "param_manager.h"
#include "param_message.h"
#include "param_security.h"
#define INVALID_SOCKET (-1)
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
static atomic_uint g_requestId;
static ATOMIC_UINT32 g_requestId;
static int g_clientFd = INVALID_SOCKET;
static pthread_mutex_t g_clientMutex = PTHREAD_MUTEX_INITIALIZER;
__attribute__((constructor)) static void ParameterInit(void)
{
ATOMIC_INIT(&g_requestId, 1);
EnableInitLog(INIT_WARN);
EnableInitLog(INIT_INFO);
PARAM_WORKSPACE_OPS ops = {0};
ops.updaterMode = 0;
ops.logFunc = InitLog;
......@@ -173,7 +173,7 @@ static int SystemSetParameter_(const char *name, const char *value, int timeout)
PARAM_CHECK(ret == 0, free(request);
return -1, "Failed to fill value");
request->msgSize = offset + sizeof(ParamMessage);
request->id.msgId = atomic_fetch_add(&g_requestId, 1);
request->id.msgId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED);
PARAM_LOGI("SystemSetParameter name %s msgid:%d ", name, request->id.msgId);
pthread_mutex_lock(&g_clientMutex);
......@@ -246,7 +246,7 @@ int SystemWaitParameter(const char *name, const char *value, int32_t timeout)
offset += sizeof(ParamMsgContent) + sizeof(uint32_t);
request->msgSize = offset + sizeof(ParamMessage);
request->id.waitId = atomic_fetch_add(&g_requestId, 1);
request->id.waitId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED);
#ifdef STARTUP_INIT_TEST
timeout = 1;
#endif
......
......@@ -22,7 +22,6 @@
#include "init_param.h"
#include "init_utils.h"
#include "loop_event.h"
#include "param_base.h"
#include "param_manager.h"
#include "param_message.h"
#include "trigger_manager.h"
......@@ -60,26 +59,24 @@ static void TimerCallback(const ParamTaskPtr timer, void *context)
static void CheckAndSendTrigger(uint32_t dataIndex, const char *name, const char *value)
{
ParamNode *entry = (ParamNode *)GetTrieNode(GetWorkSpace(GetWorkSpaceIndex(name)), dataIndex);
ParamNode *entry = (ParamNode *)GetTrieNode(GetWorkSpaceByName(name), dataIndex);
PARAM_CHECK(entry != NULL, return, "Failed to get data %s ", name);
uint32_t trigger = 1;
if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, memory_order_relaxed) & PARAM_FLAGS_TRIGGED) != PARAM_FLAGS_TRIGGED) {
if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED) & PARAM_FLAGS_TRIGGED) != PARAM_FLAGS_TRIGGED) {
trigger = (CheckAndMarkTrigger(TRIGGER_PARAM, name) != 0) ? 1 : 0;
}
if (trigger) {
ATOMIC_STORE_EXPLICIT(&entry->commitId,
ATOMIC_LOAD_EXPLICIT(&entry->commitId, memory_order_relaxed) | PARAM_FLAGS_TRIGGED, memory_order_release);
ATOMIC_SYNC_OR_AND_FETCH(&entry->commitId, PARAM_FLAGS_TRIGGED, MEMORY_ORDER_RELEASE);
// notify event to process trigger
PostParamTrigger(EVENT_TRIGGER_PARAM, name, value);
}
int wait = 1;
if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, memory_order_relaxed) & PARAM_FLAGS_WAITED) != PARAM_FLAGS_WAITED) {
if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED) & PARAM_FLAGS_WAITED) != PARAM_FLAGS_WAITED) {
wait = (CheckAndMarkTrigger(TRIGGER_PARAM_WAIT, name) != 0) ? 1 : 0;
}
if (wait) {
ATOMIC_STORE_EXPLICIT(&entry->commitId,
ATOMIC_LOAD_EXPLICIT(&entry->commitId, memory_order_relaxed) | PARAM_FLAGS_WAITED, memory_order_release);
ATOMIC_SYNC_OR_AND_FETCH(&entry->commitId, PARAM_FLAGS_WAITED, MEMORY_ORDER_RELEASE);
PostParamTrigger(EVENT_TRIGGER_PARAM_WAIT, name, value);
}
PostParamTrigger(EVENT_TRIGGER_PARAM_WATCH, name, value);
......
......@@ -16,10 +16,12 @@
#include "param_manager.h"
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include "init_cmds.h"
#include "init_hook.h"
#include "param_base.h"
#include "param_trie.h"
#include "param_utils.h"
#include "securec.h"
......@@ -33,7 +35,7 @@ ParamNode *SystemCheckMatchParamWait(const char *name, const char *value)
PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace");
PARAM_WORKSPACE_CHECK(paramSpace, return NULL, "Invalid space");
WorkSpace *workspace = GetWorkSpace(GetWorkSpaceIndex(name));
WorkSpace *workspace = GetWorkSpaceByName(name);
PARAM_CHECK(workspace != NULL, return NULL, "Failed to get workspace %s", name);
PARAM_LOGV("SystemCheckMatchParamWait name %s", name);
uint32_t nameLength = strlen(name);
......@@ -48,8 +50,7 @@ ParamNode *SystemCheckMatchParamWait(const char *name, const char *value)
if ((param->keyLength != nameLength) || (strncmp(param->data, name, nameLength) != 0)) { // compare name
return NULL;
}
ATOMIC_STORE_EXPLICIT(&param->commitId,
ATOMIC_LOAD_EXPLICIT(&param->commitId, memory_order_relaxed) | PARAM_FLAGS_WAITED, memory_order_release);
ATOMIC_SYNC_OR_AND_FETCH(&param->commitId, PARAM_FLAGS_WAITED, MEMORY_ORDER_RELEASE);
if ((strncmp(value, "*", 1) == 0) || (strcmp(param->data + nameLength + 1, value) == 0)) { // compare value
return param;
}
......@@ -136,8 +137,8 @@ static int DumpTrieDataNodeTraversal(const WorkSpace *workSpace, const ParamTrie
if (current->dataIndex != 0) {
ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex);
if (entry != NULL) {
PARAM_DUMP("\tparameter length info [%u, %u] \n\t param: %s \n",
entry->keyLength, entry->valueLength, entry->data);
PARAM_DUMP("\tparameter length info [%d] [%u, %u] \n\t param: %s \n",
entry->commitId, entry->keyLength, entry->valueLength, entry->data);
}
}
if (current->labelIndex != 0 && verbose) {
......@@ -160,6 +161,10 @@ static void HashNodeTraverseForDump(WorkSpace *workSpace, int verbose)
PARAM_DUMP(" total node: %u \n", workSpace->area->trieNodeCount);
PARAM_DUMP(" total param node: %u \n", workSpace->area->paramNodeCount);
PARAM_DUMP(" total security node: %u\n", workSpace->area->securityNodeCount);
if (verbose) {
PARAM_DUMP(" commitId : %" PRId64 "\n", workSpace->area->commitId);
PARAM_DUMP(" commitPersistId : %" PRId64 "\n", workSpace->area->commitPersistId);
}
}
PARAM_DUMP(" node info: \n");
PARAMSPACE_AREA_RD_LOCK(workSpace);
......@@ -398,13 +403,11 @@ static int AddParam(WorkSpace *workSpace, uint8_t type, const char *name, const
PARAM_CHECK(offset > 0, return PARAM_CODE_REACHED_MAX,
"Failed to allocate name %s space %s", name, workSpace->fileName);
SaveIndex(&node->dataIndex, offset);
long long globalCommitId = ATOMIC_LOAD_EXPLICIT(&workSpace->area->commitId, memory_order_relaxed);
ATOMIC_STORE_EXPLICIT(&workSpace->area->commitId, ++globalCommitId, memory_order_release);
ATOMIC_SYNC_ADD_AND_FETCH(&workSpace->area->commitId, 1, MEMORY_ORDER_RELEASE);
#ifdef PARAM_SUPPORT_SELINUX
WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC);
if (space != NULL && space != workSpace) { // dac commit is global commit
globalCommitId = ATOMIC_LOAD_EXPLICIT(&space->area->commitId, memory_order_relaxed);
ATOMIC_STORE_EXPLICIT(&space->area->commitId, ++globalCommitId, memory_order_release);
ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitId, 1, MEMORY_ORDER_RELEASE);
}
#endif
}
......@@ -422,22 +425,20 @@ static int UpdateParam(const WorkSpace *workSpace, uint32_t *dataIndex, const ch
PARAM_CHECK(entry->keyLength == strlen(name), return PARAM_CODE_INVALID_NAME, "Failed to check name len %s", name);
uint32_t valueLen = strlen(value);
uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, memory_order_relaxed);
ATOMIC_STORE_EXPLICIT(&entry->commitId, commitId | PARAM_FLAGS_MODIFY, memory_order_relaxed);
long long globalCommitId = ATOMIC_LOAD_EXPLICIT(&workSpace->area->commitId, memory_order_relaxed);
uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED);
ATOMIC_STORE_EXPLICIT(&entry->commitId, commitId | PARAM_FLAGS_MODIFY, MEMORY_ORDER_RELAXED);
if (entry->valueLength < PARAM_VALUE_LEN_MAX && valueLen < PARAM_VALUE_LEN_MAX) {
int ret = ParamMemcpy(entry->data + entry->keyLength + 1, PARAM_VALUE_LEN_MAX, value, valueLen + 1);
int ret = PARAM_MEMCPY(entry->data + entry->keyLength + 1, PARAM_VALUE_LEN_MAX, value, valueLen + 1);
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_VALUE, "Failed to copy value");
entry->valueLength = valueLen;
}
uint32_t flags = commitId & ~PARAM_FLAGS_COMMITID;
ATOMIC_STORE_EXPLICIT(&entry->commitId, (++commitId) | flags, memory_order_release);
ATOMIC_STORE_EXPLICIT(&workSpace->area->commitId, ++globalCommitId, memory_order_release);
ATOMIC_STORE_EXPLICIT(&entry->commitId, (++commitId) | flags, MEMORY_ORDER_RELEASE);
ATOMIC_SYNC_ADD_AND_FETCH(&workSpace->area->commitId, 1, MEMORY_ORDER_RELEASE);
#ifdef PARAM_SUPPORT_SELINUX
WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC);
if (space != NULL && space != workSpace) { // dac commit is global commit
globalCommitId = ATOMIC_LOAD_EXPLICIT(&space->area->commitId, memory_order_relaxed);
ATOMIC_STORE_EXPLICIT(&space->area->commitId, ++globalCommitId, memory_order_release);
ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitId, 1, MEMORY_ORDER_RELEASE);
}
#endif
PARAM_LOGV("UpdateParam name %s value: %s", name, value);
......@@ -452,7 +453,7 @@ INIT_LOCAL_API int WriteParam(const char *name, const char *value, uint32_t *dat
PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid name or value");
WorkSpace *workSpace = GetWorkSpace(GetWorkSpaceIndex(name));
WorkSpace *workSpace = GetWorkSpaceByName(name);
PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace");
ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL);
int ret = 0;
......@@ -483,36 +484,6 @@ INIT_LOCAL_API int WriteParam(const char *name, const char *value, uint32_t *dat
return ret;
}
INIT_LOCAL_API int CheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
{
PARAM_CHECK(srcLabel != NULL, return DAC_RESULT_FORBIDED, "The srcLabel is null");
ParamWorkSpace *paramSpace = GetParamWorkSpace();
PARAM_CHECK(paramSpace != NULL, return DAC_RESULT_FORBIDED, "Invalid param workspace");
WorkSpace *dacSpace = GetWorkSpace(WORKSPACE_INDEX_DAC);
PARAM_WORKSPACE_CHECK(paramSpace, return DAC_RESULT_FORBIDED, "Invalid workspace");
PARAM_CHECK(paramSpace->checkParamPermission != NULL, return DAC_RESULT_FORBIDED, "Invalid check permission");
ParamLabelIndex labelIndex = {0};
// search node from dac space, and get selinux label index
(void)FindTrieNode(dacSpace, name, strlen(name), &labelIndex.dacLabelIndex);
ParamSecurityNode *securityNode = (ParamSecurityNode *)GetTrieNode(dacSpace, labelIndex.dacLabelIndex);
if ((securityNode == NULL) || (securityNode->selinuxIndex == 0) ||
(securityNode->selinuxIndex == INVALID_SELINUX_INDEX)) {
labelIndex.selinuxLabelIndex = GetWorkSpaceIndex(name);
} else {
labelIndex.selinuxLabelIndex = securityNode->selinuxIndex;
}
if (labelIndex.selinuxLabelIndex < paramSpace->maxLabelIndex) {
labelIndex.workspace = paramSpace->workSpace[labelIndex.selinuxLabelIndex];
}
PARAM_CHECK(labelIndex.workspace != NULL, return PARAM_CODE_INVALID_PARAM,
"Invalid workSpace for %s %u", name, labelIndex.selinuxLabelIndex);
int ret = paramSpace->checkParamPermission(&labelIndex, srcLabel, name, mode);
if (ret != 0) {
PARAM_LOGW("Forbid to access %s label %u %u", name, labelIndex.dacLabelIndex, labelIndex.selinuxLabelIndex);
}
return ret;
}
INIT_LOCAL_API WorkSpace *GetNextWorkSpace(WorkSpace *curr)
{
ParamWorkSpace *paramSpace = GetParamWorkSpace();
......@@ -610,7 +581,7 @@ static int ReadParamName(ParamHandle handle, char *name, uint32_t length)
return PARAM_CODE_NOT_FOUND;
}
PARAM_CHECK(length > entry->keyLength, return -1, "Invalid param size %u %u", entry->keyLength, length);
int ret = ParamMemcpy(name, length, entry->data, entry->keyLength);
int ret = PARAM_MEMCPY(name, length, entry->data, entry->keyLength);
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_PARAM, "Failed to copy name");
name[entry->keyLength] = '\0';
return 0;
......@@ -662,4 +633,134 @@ void ResetParamSecurityLabel(void)
paramSpace->securityLabel.cred.gid = getegid();
paramSpace->flags |= WORKSPACE_FLAGS_NEED_ACCESS;
#endif
}
static int CheckParamPermission_(WorkSpace **workspace, ParamTrieNode **node,
const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
{
ParamWorkSpace *paramSpace = GetParamWorkSpace();
PARAM_CHECK(srcLabel != NULL, return DAC_RESULT_FORBIDED, "The srcLabel is null");
WorkSpace *dacSpace = GetWorkSpace(WORKSPACE_INDEX_DAC);
PARAM_CHECK(paramSpace->checkParamPermission != NULL, return DAC_RESULT_FORBIDED, "Invalid check permission");
ParamLabelIndex labelIndex = {0};
// search node from dac space, and get selinux label index
*node = FindTrieNode(dacSpace, name, strlen(name), &labelIndex.dacLabelIndex);
labelIndex.workspace = GetWorkSpaceByName(name);
PARAM_CHECK(labelIndex.workspace != NULL, return DAC_RESULT_FORBIDED, "Invalid workSpace for %s", name);
labelIndex.selinuxLabelIndex = labelIndex.workspace->spaceIndex;
int ret = paramSpace->checkParamPermission(&labelIndex, srcLabel, name, mode);
PARAM_CHECK(ret == 0, return ret,
"Forbid to access %s label %u %u", name, labelIndex.dacLabelIndex, labelIndex.selinuxLabelIndex);
*workspace = labelIndex.workspace;
return ret;
}
INIT_LOCAL_API int CheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
{
ParamTrieNode *entry = NULL;
WorkSpace *workspace = NULL;
return CheckParamPermission_(&workspace, &entry, srcLabel, name, mode);
}
STATIC_INLINE ParamTrieNode *GetTrieNodeByHandle(ParamHandle handle)
{
PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return NULL);
uint32_t labelIndex = 0;
uint32_t index = 0;
PARAM_GET_HANDLE_INFO(handle, labelIndex, index);
WorkSpace *workSpace = GetWorkSpace(labelIndex);
PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workSpace for handle %x", handle);
if (PARAM_IS_ALIGNED(index)) {
return (ParamTrieNode *)GetTrieNode(workSpace, index);
}
return NULL;
}
STATIC_INLINE int ReadParamValue(ParamNode *entry, char *value, uint32_t *length)
{
if (entry == NULL) {
return PARAM_CODE_NOT_FOUND;
}
if (value == NULL) {
*length = entry->valueLength + 1;
return 0;
}
PARAM_CHECK(*length > entry->valueLength, return PARAM_CODE_INVALID_PARAM,
"Invalid value len %u %u", *length, entry->valueLength);
uint32_t commitId = ReadCommitId(entry);
return ReadParamValue_(entry, &commitId, value, length);
}
int SystemReadParam(const char *name, char *value, uint32_t *len)
{
PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init.");
PARAM_CHECK(name != NULL && len != NULL, return -1, "The name or value is null");
ParamTrieNode *node = NULL;
WorkSpace *workspace = NULL;
int ret = CheckParamPermission_(&workspace, &node, GetParamSecurityLabel(), name, DAC_READ);
if (ret != 0) {
return ret;
}
#ifdef PARAM_SUPPORT_SELINUX
// search from real workspace
node = FindTrieNode(workspace, name, strlen(name), NULL);
#endif
if (node == NULL) {
return PARAM_CODE_NOT_FOUND;
}
return ReadParamValue((ParamNode *)GetTrieNode(workspace, node->dataIndex), value, len);
}
int SystemFindParameter(const char *name, ParamHandle *handle)
{
PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init.");
PARAM_CHECK(name != NULL && handle != NULL, return -1, "The name or handle is null");
*handle = -1;
ParamTrieNode *entry = NULL;
WorkSpace *workspace = NULL;
int ret = CheckParamPermission_(&workspace, &entry, GetParamSecurityLabel(), name, DAC_READ);
PARAM_CHECK(ret == 0, return ret, "Forbid to access parameter %s", name);
#ifdef PARAM_SUPPORT_SELINUX
// search from real workspace
entry = FindTrieNode(workspace, name, strlen(name), NULL);
#endif
if (entry != NULL && entry->dataIndex != 0) {
*handle = PARAM_HANDLE(workspace, entry->dataIndex);
return 0;
} else if (entry != NULL) {
return PARAM_CODE_NODE_EXIST;
}
return PARAM_CODE_NOT_FOUND;
}
int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId)
{
PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init.");
PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND);
PARAM_CHECK(handle != 0 && commitId != NULL, return -1, "The handle is null");
ParamNode *entry = (ParamNode *)GetTrieNodeByHandle(handle);
if (entry == NULL) {
return PARAM_CODE_NOT_FOUND;
}
*commitId = ReadCommitId(entry);
return 0;
}
long long GetSystemCommitId(void)
{
PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init.");
WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC);
if (space == NULL) {
return 0;
}
return ATOMIC_UINT64_LOAD_EXPLICIT(&space->area->commitId, MEMORY_ORDER_ACQUIRE);
}
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len)
{
PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init.");
PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND);
PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null");
return ReadParamValue((ParamNode *)GetTrieNodeByHandle(handle), value, len);
}
\ No newline at end of file
......@@ -43,7 +43,7 @@ static long long GetPersistCommitId(void)
return 0;
}
PARAMSPACE_AREA_RD_LOCK(space);
long long globalCommitId = ATOMIC_LOAD_EXPLICIT(&space->area->commitPersistId, memory_order_acquire);
long long globalCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&space->area->commitPersistId, MEMORY_ORDER_ACQUIRE);
PARAMSPACE_AREA_RW_UNLOCK(space);
return globalCommitId;
}
......@@ -58,8 +58,7 @@ static void UpdatePersistCommitId(void)
return;
}
PARAMSPACE_AREA_RW_LOCK(space);
long long globalCommitId = ATOMIC_LOAD_EXPLICIT(&space->area->commitPersistId, memory_order_relaxed);
ATOMIC_STORE_EXPLICIT(&space->area->commitPersistId, ++globalCommitId, memory_order_release);
ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitPersistId, 1, MEMORY_ORDER_RELEASE);
PARAMSPACE_AREA_RW_UNLOCK(space);
}
......
......@@ -21,6 +21,7 @@
#ifdef SUPPORT_PARAM_LOAD_HOOK
#include "init_module_engine.h"
#endif
#include "securec.h"
/**
* Loading system parameter from /proc/cmdline by the following rules:
......@@ -167,7 +168,8 @@ static void CmdlineIterator(const NAME_VALUE_PAIR *nv, void *context)
CommonDealFun(nv->name, nv->value);
}
static void GenerateSnByDefault() {
static void GenerateSnByDefault(void)
{
const char *snFileList [] = {
"/sys/block/mmcblk0/device/cid",
"/proc/bootdevice/cid"
......
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
common_include_dirs = [
".",
"//third_party/bounds_checking_function/include",
]
ohos_executable("BMStartupTest") {
sources = [
"benchmark_fwk.cpp",
"parameter_benchmark.cpp",
]
defines = [ "_GNU_SOURCE" ]
include_dirs = common_include_dirs
deps = [
"../../interfaces/innerkits:libbegetutil",
"//third_party/benchmark:benchmark",
]
install_images = [ "system" ]
install_enable = true
part_name = "init"
subsystem_name = "startup"
}
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <benchmark/benchmark.h>
#include <err.h>
#include <getopt.h>
#include <cinttypes>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "benchmark_fwk.h"
using namespace std;
using namespace init_benchmark_test;
namespace {
constexpr auto K = 1024;
using args_vector = std::vector<std::vector<int64_t>>;
static const std::vector<int> commonArgs {
8,
16,
32,
64,
512,
1 * K,
8 * K,
16 * K,
32 * K,
64 * K,
128 * K,
};
static const std::vector<int> limitSizes {
1,
2,
3,
4,
5,
6,
7,
};
}
namespace init_benchmark_test {
std::map<std::string, std::pair<benchmark_func, std::string>> g_allBenchmarks;
std::mutex g_benchmarkLock;
static struct option g_benchmarkLongOptions[] = {
{"init_cpu", required_argument, nullptr, 'c'},
{"init_iterations", required_argument, nullptr, 'i'},
{"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0},
};
}
static void PrintUsageAndExit()
{
printf("Usage:\n");
printf("init_benchmarks [--init_cpu=<cpu_to_isolate>]\n");
printf(" [--init_iterations=<num_iter>]\n");
printf(" [<original benchmark flags>]\n");
printf("benchmark flags:\n");
int argc = 2;
char argv0[] = "init_benchmark";
char argv1[] = "--help";
char *argv[3] = { argv0, argv1, nullptr };
benchmark::Initialize(&argc, argv);
exit(1);
}
static void ShiftOptions(int argc, char **argv, std::vector<char *> *argvAfterShift)
{
(*argvAfterShift)[0] = argv[0];
for (int i = 1; i < argc; ++i) {
char *optarg = argv[i];
size_t index = 0;
// Find if musl defined this arg.
while (g_benchmarkLongOptions[index].name && strncmp(g_benchmarkLongOptions[index].name, optarg + 2, // 2 arg
strlen(g_benchmarkLongOptions[index].name))) {
++index;
}
// Not defined.
if (!g_benchmarkLongOptions[index].name) {
argvAfterShift->push_back(optarg);
} else if ((g_benchmarkLongOptions[index].has_arg == required_argument) && !strchr(optarg, '=')) {
i++;
}
}
argvAfterShift->push_back(nullptr);
}
static bench_opts_t ParseOptions(int argc, char **argv)
{
bench_opts_t opts;
int opt;
char *errorCheck = nullptr;
opterr = 0; // Don't show unrecognized option error.
while ((opt = getopt_long(argc, argv, "c:i:a:h", g_benchmarkLongOptions, nullptr)) != -1) {
switch (opt) {
case 'c':
if (!(*optarg)) {
printf("ERROR: no argument specified for init_cpu.\n");
PrintUsageAndExit();
break;
}
opts.cpuNum = strtol(optarg, &errorCheck, 10); // 10 base
if (*errorCheck) {
errx(1, "ERROR: Args %s is not a valid integer.", optarg);
}
break;
case 'i':
if (!(*optarg)) {
printf("ERROR: no argument specified for init_iterations.\n");
PrintUsageAndExit();
break;
}
opts.iterNum = strtol(optarg, &errorCheck, 10); // 10 base
if (*errorCheck != '\0' || opts.iterNum < 0) {
errx(1, "ERROR: Args %s is not a valid number of iterations.", optarg);
}
break;
case 'h':
PrintUsageAndExit();
break;
case '?':
break;
default:
exit(1);
}
}
return opts;
}
static void LockAndRun(benchmark::State &state, benchmark_func func, int cpuNum)
{
if (cpuNum >= 0) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpuNum, &cpuset);
if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
printf("lock CPU failed, ERROR:%s\n", strerror(errno));
}
}
reinterpret_cast<void (*)(benchmark::State &)>(func)(state);
}
static args_vector *ResolveArgs(args_vector *argsVector, std::string args,
std::map<std::string, args_vector> &presetArgs)
{
// Get it from preset args.
if (presetArgs.count(args)) {
return &presetArgs[args];
}
// Convert string to int.
argsVector->push_back(std::vector<int64_t>());
std::stringstream sstream(args);
std::string arg;
while (sstream >> arg) {
char *errorCheck;
int converted = static_cast<int>(strtol(arg.c_str(), &errorCheck, 10)); // 10 base
if (*errorCheck) {
errx(1, "ERROR: Args str %s contains an invalid macro or int.", args.c_str());
}
(*argsVector)[0].push_back(converted);
}
return argsVector;
}
static args_vector GetArgs(const std::vector<int> &sizes)
{
args_vector args;
for (int size : sizes) {
args.push_back( {size} );
}
return args;
}
static args_vector GetArgs(const std::vector<int> &sizes, int value)
{
args_vector args;
for (int size : sizes) {
args.push_back( {size, value} );
}
return args;
}
static args_vector GetArgs(const std::vector<int> &sizes, int value1, int value2)
{
args_vector args;
for (int size : sizes) {
args.push_back( {size, value1, value2} );
}
return args;
}
static args_vector GetArgs(const std::vector<int> &sizes, const std::vector<int> &limits, int value)
{
args_vector args;
for (int size : sizes) {
for (int limit : limits) {
args.push_back( {size, limit, value} );
}
}
return args;
}
static std::map<std::string, args_vector> GetPresetArgs()
{
std::map<std::string, args_vector> presetArgs {
{"COMMON_ARGS", GetArgs(commonArgs)},
{"ALIGNED_ONEBUF", GetArgs(commonArgs, 0)},
{"ALIGNED_TWOBUF", GetArgs(commonArgs, 0, 0)},
{"STRING_LIMIT", GetArgs(commonArgs, limitSizes, 0)},
{"MATH_COMMON", args_vector{{0}, {1}, {2}, {3}, {4}, {5}}},
{"BENCHMARK_VARIABLE", args_vector{{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}},
{"REALPATH_VARIABLE", args_vector{{0}, {1}, {2}, {3}, {4}}},
{"MMAP_SIZE", args_vector{{8}, {16}, {32}, {64}, {128}, {512}}},
};
return presetArgs;
}
static void RegisterSingleBenchmark(bench_opts_t opts, const std::string &funcName, args_vector *runArgs)
{
if (g_allBenchmarks.find(funcName) == g_allBenchmarks.end()) {
errx(1, "ERROR: No benchmark for function %s", funcName.c_str());
}
benchmark_func func = g_allBenchmarks.at(funcName).first;
for (const std::vector<int64_t> &args : (*runArgs)) {
// It will call LockAndRun(func, opts.cpuNum).
auto registration = benchmark::RegisterBenchmark(funcName.c_str(), LockAndRun, func, opts.cpuNum)->Args(args);
printf("opts.iterNum %ld \n", opts.iterNum);
if (opts.iterNum > 0) {
registration->Iterations(opts.iterNum);
}
}
}
static void RegisterAllBenchmarks(const bench_opts_t &opts, std::map<std::string, args_vector> &presetArgs)
{
for (auto &entry : g_allBenchmarks) {
auto &funcInfo = entry.second;
args_vector arg_vector;
args_vector *runArgs = ResolveArgs(&arg_vector, funcInfo.second, presetArgs);
RegisterSingleBenchmark(opts, entry.first, runArgs);
}
}
int main(int argc, char **argv)
{
std::map<std::string, args_vector> presetArgs = GetPresetArgs();
bench_opts_t opts = ParseOptions(argc, argv);
std::vector<char *> argvAfterShift(argc);
ShiftOptions(argc, argv, &argvAfterShift);
RegisterAllBenchmarks(opts, presetArgs);
if (setpriority(PRIO_PROCESS, 0, -20)) { // 20 max
perror("Set priority of process failed.\n");
}
CreateLocalParameterTest(512); // test max 512
int argcAfterShift = argvAfterShift.size();
benchmark::Initialize(&argcAfterShift, argvAfterShift.data());
benchmark::RunSpecifiedBenchmarks();
}
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef STARTUP_INIT_BENCHMARK_FWK_H
#define STARTUP_INIT_BENCHMARK_FWK_H
#include <map>
#include <mutex>
#include <string>
#include <utility>
#include <vector>
namespace init_benchmark_test {
using benchmark_func = void (*) (void);
extern std::mutex g_benchmarkLock;
extern std::map<std::string, std::pair<benchmark_func, std::string>> g_allBenchmarks;
static int __attribute__((unused)) AddBenchmark(const std::string &funcName,
benchmark_func funcPtr, const std::string &arg = "")
{
g_benchmarkLock.lock();
g_allBenchmarks.emplace(std::string(funcName), std::make_pair(funcPtr, arg));
g_benchmarkLock.unlock();
return 0;
}
#define INIT_BENCHMARK(n) \
int _init_benchmark_##n __attribute__((unused)) = AddBenchmark(std::string(#n), \
reinterpret_cast<benchmark_func>(n))
#define INIT_BENCHMARK_WITH_ARG(n, arg) \
int _init_benchmark_##n __attribute__((unused)) = AddBenchmark(std::string(#n), \
reinterpret_cast<benchmark_func>(n), arg)
}
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef struct bench_opts_t {
int cpuNum = -1;
long iterNum = 0;
} BENCH_OPTS_T;
void CreateLocalParameterTest(int max);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // STARTUP_INIT_BENCHMARK_FWK_H
\ No newline at end of file
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <benchmark/benchmark.h>
#include "benchmark_fwk.h"
#include "init_param.h"
#include "parameter.h"
#include "sys_param.h"
using namespace std;
using namespace init_benchmark_test;
namespace {
static int g_maxCount = 512;
}
static inline int TestRandom(void)
{
return random();
}
namespace init_benchmark_param {
struct LocalParameterTestState {
explicit LocalParameterTestState(int nprops) noexcept : nprops(nprops), valid(false)
{
static const char paramNameChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
if (g_maxCount < nprops) {
fprintf(stderr, "Invalid nprops %d\n", nprops);
return;
}
names = new char *[nprops];
nameLens = new int[nprops];
values = new char *[nprops];
valueLens = new int[nprops];
srandom(nprops);
int count = 0;
for (int i = 0; i < nprops; i++) {
// Make sure the name has at least 10 characters to make
// it very unlikely to generate the same TestRandom name.
nameLens[i] = (TestRandom() % (PARAM_NAME_LEN_MAX - 10)) + 10; // 10 name len
names[i] = new char[PARAM_NAME_LEN_MAX + 1];
size_t paramNameLen = sizeof(paramNameChars) - 1;
for (int j = 0; j < nameLens[i]; j++) {
if (j == 0 || names[i][j - 1] == '.' || j == nameLens[i] - 1) {
// Certain values are not allowed:
// - Don't start name with '.'
// - Don't allow '.' to appear twice in a row
// - Don't allow the name to end with '.'
// This assumes that '.' is the last character in the
// array so that decrementing the length by one removes
// the value from the possible values.
paramNameLen--;
}
names[i][j] = paramNameChars[TestRandom() % paramNameLen];
}
names[i][nameLens[i]] = 0;
// Make sure the value contains at least 1 character.
valueLens[i] = (TestRandom() % (PARAM_VALUE_LEN_MAX - 1)) + 1;
values[i] = new char[PARAM_VALUE_LEN_MAX];
for (int j = 0; j < valueLens[i]; j++) {
values[i][j] = paramNameChars[TestRandom() % (sizeof(paramNameChars) - 1)];
}
if (SystemSetParameter(names[i], values[i]) != 0) {
count++;
}
}
if (count > 0) {
fprintf(stderr, "Failed to add a property, count %d\n", count);
}
valid = true;
}
~LocalParameterTestState() noexcept
{
for (int i = 0; i < nprops; i++) {
delete names[i];
delete values[i];
}
delete[] names;
delete[] nameLens;
delete[] values;
delete[] valueLens;
}
public:
const int nprops;
char **names;
int *nameLens;
char **values;
int *valueLens;
bool valid;
};
}
static init_benchmark_param::LocalParameterTestState *g_localParamTester = nullptr;
void CreateLocalParameterTest(int max)
{
g_maxCount = max > 0 ? max : g_maxCount;
g_localParamTester = new init_benchmark_param::LocalParameterTestState(g_maxCount);
if (g_localParamTester == nullptr) {
exit(0);
}
}
/**
* @brief for parameter get
*
* @param state
*/
static void BMCachedParameterGet(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
CachedHandle handle = CachedParameterCreate(g_localParamTester->names[TestRandom() % g_maxCount], "4444444");
for (auto _ : state) {
benchmark::DoNotOptimize(CachedParameterGet(handle));
}
state.SetItemsProcessed(state.iterations());
}
/**
* @brief for parameter get, static handle
*
* @param state
*/
static void BMCachedParameterGetChangedStatic(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
for (auto _ : state) {
static CachedHandle handle = CachedParameterCreate(
g_localParamTester->names[TestRandom() % g_maxCount], "xxxxxx");
int changed = 0;
benchmark::DoNotOptimize(CachedParameterGetChanged(handle, &changed));
}
state.SetItemsProcessed(state.iterations());
}
/**
* @brief for parameter get, global handle
*
* @param state
*/
static void BMCachedParameterGetChangedGlobal(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
CachedHandle handle = CachedParameterCreate(g_localParamTester->names[TestRandom() % g_maxCount], "xxxxxxxxx");
for (auto _ : state) {
int changed = 0;
benchmark::DoNotOptimize(CachedParameterGetChanged(handle, &changed));
}
state.SetItemsProcessed(state.iterations());
}
/**
* @brief for parameter get, global handle
*
* @param state
*/
static void BMCachedParameterGetChangedGlobal2(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
CachedHandle handle = nullptr;
for (auto _ : state) {
if (handle == nullptr) {
handle = CachedParameterCreate(g_localParamTester->names[TestRandom() % g_maxCount], "xxxxxxxxx");
}
int changed = 0;
benchmark::DoNotOptimize(CachedParameterGetChanged(handle, &changed));
}
state.SetItemsProcessed(state.iterations());
}
/**
* @brief for get
* data exist
*
* @param state
*/
static void BMSystemReadParam(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
{
char value[PARAM_VALUE_LEN_MAX] = {0};
uint32_t len = PARAM_VALUE_LEN_MAX;
SystemReadParam(g_localParamTester->names[TestRandom() % g_maxCount], value, &len);
}
for (auto _ : state) {
char value[PARAM_VALUE_LEN_MAX] = {0};
uint32_t len = PARAM_VALUE_LEN_MAX;
SystemReadParam(g_localParamTester->names[TestRandom() % g_maxCount], value, &len);
}
state.SetItemsProcessed(state.iterations());
}
/**
* @brief for get
* data not exist
*
* @param state
*/
static void BMSystemReadParam_none(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
{
char value[PARAM_VALUE_LEN_MAX] = {0};
uint32_t len = PARAM_VALUE_LEN_MAX;
SystemReadParam("test.aaa.aaa.aaa", value, &len);
}
for (auto _ : state) {
char value[PARAM_VALUE_LEN_MAX] = {0};
uint32_t len = PARAM_VALUE_LEN_MAX;
SystemReadParam("test.aaa.aaa.aaa", value, &len);
}
state.SetItemsProcessed(state.iterations());
}
/**
* @brief for find
*
* @param state
*/
static void BMSystemFindParameter(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
for (auto _ : state) {
ParamHandle handle = 0;
SystemFindParameter(g_localParamTester->names[TestRandom() % g_maxCount], &handle);
}
state.SetItemsProcessed(state.iterations());
}
/**
* @brief for find, and read value
*
* @param state
*/
static void BMSystemGetParameterValue(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
ParamHandle *handle = new ParamHandle[g_maxCount];
for (int i = 0; i < g_maxCount; ++i) {
SystemFindParameter(g_localParamTester->names[TestRandom() % g_maxCount], &handle[i]);
}
int i = 0;
char value[PARAM_VALUE_LEN_MAX];
for (auto _ : state) {
uint32_t len = PARAM_VALUE_LEN_MAX;
SystemGetParameterValue(handle[i], value, &len);
i = (i + 1) % g_maxCount;
}
state.SetItemsProcessed(state.iterations());
delete[] handle;
}
/**
* @brief for find, and read commit id
*
* @param state
*/
static void BMSystemGetParameterCommitId(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
ParamHandle *handle = new ParamHandle[g_maxCount];
for (int i = 0; i < g_maxCount; ++i) {
SystemFindParameter(g_localParamTester->names[TestRandom() % g_maxCount], &handle[i]);
}
int i = 0;
for (auto _ : state) {
uint32_t commitId = 0;
SystemGetParameterCommitId(handle[i], &commitId);
i = (i + 1) % g_maxCount;
}
state.SetItemsProcessed(state.iterations());
delete[] handle;
}
static void BMTestRandom(benchmark::State &state)
{
if (g_localParamTester == nullptr || !g_localParamTester->valid) {
fprintf(stderr, "Invalid nprops %d \n", g_maxCount);
return;
}
for (auto _ : state) {
benchmark::DoNotOptimize(TestRandom());
}
state.SetItemsProcessed(state.iterations());
}
INIT_BENCHMARK(BMCachedParameterGet);
INIT_BENCHMARK(BMCachedParameterGetChangedStatic);
INIT_BENCHMARK(BMCachedParameterGetChangedGlobal);
INIT_BENCHMARK(BMCachedParameterGetChangedGlobal2);
INIT_BENCHMARK(BMSystemReadParam);
INIT_BENCHMARK(BMSystemReadParam_none);
INIT_BENCHMARK(BMSystemFindParameter);
INIT_BENCHMARK(BMSystemGetParameterValue);
INIT_BENCHMARK(BMSystemGetParameterCommitId);
INIT_BENCHMARK(BMTestRandom);
......@@ -66,6 +66,7 @@ ohos_moduletest("InitModuleTest") {
"//base/startup/init/interfaces/innerkits/include/syspara",
"//base/startup/init/interfaces/innerkits/syspara",
"//base/startup/init/services/include/param",
"//base/startup/init/services/param/include",
"//base/startup/init/device_info",
".",
]
......
......@@ -63,13 +63,7 @@ static void *CmdReader(void *args)
static int32_t BShellParamCmdRead(BShellHandle shell, int32_t argc, char *argv[])
{
PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter");
if (argc == 1) {
#ifdef PARAM_TEST_PERFORMANCE
TestParameterReaderPerformance();
#endif
return 0;
}
PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter");
static pthread_t thread = 0;
PLUGIN_LOGV("BShellParamCmdWatch %s, threadId %d", argv[1], thread);
if (strcmp(argv[1], "start") == 0) {
......
......@@ -23,6 +23,7 @@
#include "param_comm.h"
#include "init_param.h"
#include "sysparam_errno.h"
#include "sys_param.h"
using namespace std;
using namespace testing::ext;
......
......@@ -404,5 +404,8 @@ ohos_unittest("init_unittest") {
"//base/startup/init/test/unittest/modules/context_unittest.cpp",
]
# test atomic operation
sources += [ "//base/startup/init/test/unittest/param/atomic_unittest.cpp" ]
cflags_cc = [ "-fexceptions" ]
}
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <climits>
#include <thread>
#include <cstdint>
#include <gtest/gtest.h>
#include "param_atomic.h"
#include "param_common.h"
#include "param_utils.h"
using namespace testing::ext;
const int THREAD_NUM = 5;
const int MAX_NUM = 10;
namespace init_ut {
class AtomicUnitTest : public testing::Test {
public:
static void SetUpTestCase(void) {};
static void TearDownTestCase(void) {};
void SetUp(void) {};
void TearDown(void) {};
};
/**
* 测试方法:
* 1,create 线程,执行全局变量写操作
* store with dirty
* sleep
* store clear dirty
* store commit ++
* 2,read 现成,执行全局变量读参数
*
*/
using AtomicTestData = struct {
ATOMIC_UINT32 commitId;
uint32_t data;
};
static AtomicTestData g_testData = { 0, 0 };
static void *TestSetData(void *args)
{
while (g_testData.data < MAX_NUM) {
uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&g_testData.commitId, MEMORY_ORDER_RELAXED);
ATOMIC_STORE_EXPLICIT(&g_testData.commitId, commitId | PARAM_FLAGS_MODIFY, MEMORY_ORDER_RELAXED);
g_testData.data++;
usleep(200 * 1000); // 200 * 1000 wait
printf("TestSetData data: %d commit: %d \n", g_testData.data, g_testData.commitId & PARAM_FLAGS_COMMITID);
uint32_t flags = commitId & ~PARAM_FLAGS_COMMITID;
ATOMIC_STORE_EXPLICIT(&g_testData.commitId, (++commitId) | flags, MEMORY_ORDER_RELEASE);
futex_wake(&g_testData.commitId, INT_MAX);
usleep(100); // 100 wait
}
return nullptr;
}
static inline uint32_t TestReadCommitId(AtomicTestData *entry)
{
uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE);
while (commitId & PARAM_FLAGS_MODIFY) {
futex_wait(&entry->commitId, commitId);
commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE);
}
return commitId & PARAM_FLAGS_COMMITID;
}
static inline int TestReadParamValue(AtomicTestData *entry, uint32_t *commitId)
{
uint32_t data;
uint32_t id = *commitId;
do {
*commitId = id;
data = entry->data;
id = TestReadCommitId(entry);
} while (*commitId != id); // if change, must read
return data;
}
static void *TestReadData(void *args)
{
uint32_t data = 0;
while (data < MAX_NUM) {
uint32_t commitId = TestReadCommitId(&g_testData);
data = TestReadParamValue(&g_testData, &commitId);
printf("[ %d] TestReadData data: %d commit: %d \n", gettid(), data, commitId);
usleep(10); // 10 wait
}
return nullptr;
}
HWTEST_F(AtomicUnitTest, AtomicUnitTest_001, TestSize.Level0)
{
printf("AtomicUnitTest_001 \n");
pthread_t writeThread = 0;
pthread_t readThread[THREAD_NUM] = { 0 };
pthread_create(&writeThread, nullptr, TestSetData, nullptr);
for (size_t i = 0; i < THREAD_NUM; i++) {
pthread_create(&readThread[i], nullptr, TestReadData, nullptr);
}
pthread_join(writeThread, nullptr);
printf("AtomicUnitTest_001 end \n");
}
}
\ No newline at end of file
......@@ -15,12 +15,14 @@
#include <gtest/gtest.h>
#include "init_param.h"
#include "param_base.h"
#include "param_message.h"
#include "param_stub.h"
#include "trigger_manager.h"
#include "param_utils.h"
#include "param_osadp.h"
#include "param_manager.h"
#include "sys_param.h"
using namespace testing::ext;
using namespace std;
......@@ -301,6 +303,18 @@ public:
SystemDumpParameters(1, -1, NULL);
return 0;
}
uint32_t GetWorkSpaceIndex(const char *name)
{
#ifdef PARAM_SUPPORT_SELINUX
ParamWorkSpace *paramSpace = GetParamWorkSpace();
PARAM_CHECK(paramSpace != NULL, return (uint32_t)-1, "Invalid paramSpace");
return (paramSpace->selinuxSpace.getParamLabelIndex != NULL) ?
paramSpace->selinuxSpace.getParamLabelIndex(name) + WORKSPACE_INDEX_BASE : (uint32_t)-1;
#else
return 0;
#endif
}
};
HWTEST_F(ParamUnitTest, TestPersistParam, TestSize.Level0)
......@@ -431,7 +445,7 @@ HWTEST_F(ParamUnitTest, TestWorkSpace2, TestSize.Level0)
}
workSpace->flags = 0;
workSpace->area = NULL;
int ret = ParamStrCpy(workSpace->fileName, size, spaceName);
int ret = PARAM_STRCPY(workSpace->fileName, size, spaceName);
EXPECT_EQ(ret, 0);
CloseWorkSpace(workSpace);
free(workSpace);
......@@ -506,7 +520,7 @@ HWTEST_F(ParamUnitTest, TestFindTrieNode, TestSize.Level0)
{
int ret = AddWorkSpace("test.workspace.1", GetWorkSpaceIndex("test.workspace.1"), 0, PARAM_WORKSPACE_DEF);
EXPECT_EQ(ret, 0);
WorkSpace *space = GetWorkSpace(GetWorkSpaceIndex("test.workspace.1"));
WorkSpace *space = GetWorkSpaceByName("test.workspace.1");
ASSERT_NE(space, nullptr);
ParamTrieNode *node = FindTrieNode(nullptr, nullptr, 0, nullptr);
ASSERT_EQ(node, nullptr);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册