1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef BASE_STARTUP_INIT_SYS_PARAM_H
17#define BASE_STARTUP_INIT_SYS_PARAM_H
18
19#include <stdint.h>
20#ifndef __LITEOS_M__
21#include <pthread.h>
22#endif
23
24#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
25#include <stdatomic.h>
26#endif
27
28#ifndef __LITEOS_A__
29#if defined FUTEX_WAIT || defined FUTEX_WAKE
30#include <linux/futex.h>
31#endif
32#endif
33
34#define MEMORY_ORDER_ACQUIRE 2
35
36#ifdef __cplusplus
37#if __cplusplus
38extern "C" {
39#endif
40#endif
41
42#ifdef __LITEOS_M__
43#define ATOMIC_UINT32 uint32_t
44#define ATOMIC_LLONG  long long
45#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) *(commitId)
46
47#else
48#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__))
49#define ATOMIC_UINT32 atomic_uint
50#define ATOMIC_LLONG atomic_llong
51#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), order)
52
53#else
54#ifndef STARTUP_INIT_TEST
55#define ATOMIC_UINT32 uint32_t
56#define ATOMIC_LLONG int64_t
57static inline ATOMIC_LLONG param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order)
58{
59    return *((volatile ATOMIC_LLONG *)ptr);
60}
61#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) param_atomic_uint64_load((commitId), order)
62#endif
63#endif
64#endif
65
66#ifdef __LITEOS_M__
67typedef struct {
68    uint32_t mutex;
69} ParamRWMutex;
70
71typedef struct {
72    uint32_t mutex;
73} ParamMutex;
74#endif
75
76// support mutex
77#ifndef STARTUP_INIT_TEST
78typedef struct {
79    pthread_rwlock_t rwlock;
80} ParamRWMutex;
81
82typedef struct {
83    pthread_mutex_t mutex;
84} ParamMutex;
85#endif
86
87#ifndef STARTUP_INIT_TEST
88typedef struct {
89    int shmid;
90} MemHandle;
91
92typedef struct {
93    ATOMIC_LLONG commitId;
94    ATOMIC_LLONG commitPersistId;
95    uint32_t trieNodeCount;
96    uint32_t paramNodeCount;
97    uint32_t securityNodeCount;
98    uint32_t currOffset;
99    uint32_t spaceSizeOffset;
100    uint32_t firstNode;
101    uint32_t dataSize;
102    char data[0];
103} ParamTrieHeader;
104
105typedef struct WorkSpace_ {
106    unsigned int flags;
107    MemHandle memHandle;
108    ParamTrieHeader *area;
109    ATOMIC_UINT32 rwSpaceLock;
110    uint32_t spaceSize;
111    uint32_t spaceIndex;
112    ParamRWMutex rwlock;
113    char fileName[0];
114} WorkSpace;
115
116typedef struct CachedParameter_ {
117    struct WorkSpace_ *workspace;
118    const char *(*cachedParameterCheck)(struct CachedParameter_ *param, int *changed);
119    long long spaceCommitId;
120    uint32_t dataCommitId;
121    uint32_t dataIndex;
122    uint32_t bufferLen;
123    uint32_t nameLen;
124    char *paramValue;
125    char data[0];
126} CachedParameter;
127
128typedef void *CachedHandle;
129#endif
130/**
131 * parameter client init
132 */
133void InitParameterClient(void);
134
135/**
136 * by name and default value,save parameter info in handle。
137 *
138 */
139CachedHandle CachedParameterCreate(const char *name, const char *defValue);
140
141/**
142 * destroy handle
143 *
144 */
145void CachedParameterDestroy(CachedHandle handle);
146
147/**
148 * if name exist,return value else return default value
149 *
150 */
151static inline const char *CachedParameterGet(CachedHandle handle)
152{
153    struct CachedParameter_ *param = (struct CachedParameter_ *)handle;
154    if (param == NULL) {
155        return NULL;
156    }
157
158    // no change, do not to find
159    long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&param->workspace->area->commitId, MEMORY_ORDER_ACQUIRE);
160    if (param->spaceCommitId == spaceCommitId) {
161        return param->paramValue;
162    }
163    param->spaceCommitId = spaceCommitId;
164    int changed = 0;
165    if (param->cachedParameterCheck == NULL) {
166        return param->paramValue;
167    }
168    return param->cachedParameterCheck(param, &changed);
169}
170
171static inline const char *CachedParameterGetChanged(CachedHandle handle, int *changed)
172{
173    struct CachedParameter_ *param = (struct CachedParameter_ *)handle;
174    if (param == NULL) {
175        return NULL;
176    }
177    // no change, do not to find
178    long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&param->workspace->area->commitId, MEMORY_ORDER_ACQUIRE);
179    if (param->spaceCommitId == spaceCommitId) {
180        return param->paramValue;
181    }
182    param->spaceCommitId = spaceCommitId;
183    if ((changed == NULL) || (param->cachedParameterCheck == NULL)) {
184        return param->paramValue;
185    }
186    return param->cachedParameterCheck(param, changed);
187}
188
189#ifdef __cplusplus
190#if __cplusplus
191}
192#endif
193#endif
194#endif