1/*
2 * Copyright (c) 2021-2022 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#include "param_osadp.h"
16
17#include <errno.h>
18#include <fcntl.h>
19#include <pthread.h>
20#include <string.h>
21#ifdef __LITEOS_A__
22#include <sys/ipc.h>
23#include <sys/mman.h>
24#include <sys/shm.h>
25#else
26#include "los_task.h"
27#include "los_mux.h"
28#endif
29#include <sys/stat.h>
30#include <sys/time.h>
31#include <sys/types.h>
32#include <unistd.h>
33#include <signal.h>
34#include <time.h>
35
36#include "param_security.h"
37#include "securec.h"
38
39#define NSEC_PER_MSEC 1000000LL
40#define MSEC_PER_SEC 1000LL
41
42static void TimerHandle(union sigval v)
43{
44    ParamTimer *timer = (ParamTimer *)v.sival_ptr;
45    PARAM_CHECK(timer != NULL, return, "Invalid timer");
46    if (timer->timeProcessor != NULL) {
47        timer->timeProcessor(timer, timer->context);
48    }
49}
50
51static void SetTimeSpec(struct timespec *ts, int64_t msec)
52{
53    ts->tv_sec = msec / MSEC_PER_SEC; // 1000LL ms --> m
54    ts->tv_nsec = (msec - ts->tv_sec * MSEC_PER_SEC) * NSEC_PER_MSEC;
55}
56
57static int StartTimer(const ParamTimer *paramTimer, int64_t whenMsec, int64_t repeat)
58{
59    UNUSED(repeat);
60    struct itimerspec ts;
61    SetTimeSpec(&ts.it_value, whenMsec);
62    SetTimeSpec(&ts.it_interval, whenMsec);
63    int32_t ret = timer_settime(paramTimer->timerId, 0, &ts, NULL);
64    if (ret < 0) {
65        PARAM_LOGE("Failed to start timer");
66        return -1;
67    }
68    return 0;
69}
70
71int ParamTimerCreate(ParamTaskPtr *timer, ProcessTimer process, void *context)
72{
73    PARAM_CHECK(timer != NULL && process != NULL, return -1, "Invalid timer");
74    ParamTimer *paramTimer = malloc(sizeof(ParamTimer));
75    PARAM_CHECK(paramTimer != NULL, return -1, "Failed to create timer");
76    paramTimer->timeProcessor = process;
77    paramTimer->context = context;
78
79    struct sigevent evp;
80    (void)memset_s(&evp, sizeof(evp), 0, sizeof(evp));
81    evp.sigev_value.sival_ptr = paramTimer;
82    evp.sigev_notify = SIGEV_THREAD;
83    evp.sigev_notify_function = TimerHandle;
84    int32_t ret = timer_create(CLOCK_REALTIME, &evp, &paramTimer->timerId);
85    if (ret < 0) {
86        PARAM_LOGE("Failed to create timer");
87        free(paramTimer);
88        return -1;
89    }
90    *timer = paramTimer;
91    return 0;
92}
93
94int ParamTimerStart(const ParamTaskPtr timer, uint64_t timeout, uint64_t repeat)
95{
96    PARAM_CHECK(timer != NULL, return -1, "Invalid timer");
97    ParamTimer *paramTimer = (ParamTimer *)timer;
98    PARAM_LOGV("ParamTimerStart timeout %llu ", timeout);
99    int32_t ret = StartTimer(paramTimer, timeout, repeat);
100    PARAM_CHECK(ret >= 0, return -1, "Failed to start timer");
101    return 0;
102}
103
104void ParamTimerClose(ParamTaskPtr timer)
105{
106    PARAM_CHECK(timer != NULL, return, "Invalid timer");
107    ParamTimer *paramTimer = (ParamTimer *)timer;
108    timer_delete(paramTimer->timerId);
109    free(paramTimer);
110}
111
112#ifdef __LITEOS_A__
113INIT_LOCAL_API void *GetSharedMem(const char *fileName, MemHandle *handle, uint32_t spaceSize, int readOnly)
114{
115    PARAM_CHECK(fileName != NULL && handle != NULL, return NULL, "Invalid filename or handle");
116    int mode = readOnly ? O_RDONLY : O_CREAT | O_RDWR;
117    void *areaAddr = NULL;
118    if (!readOnly) {
119        int fd = open(fileName, mode, S_IRWXU | S_IRWXG | S_IROTH);
120        PARAM_CHECK(fd >= 0, return NULL, "Open file %s mode %x fail error %d", fileName, mode, errno);
121        close(fd);
122    }
123    key_t key = ftok(fileName, 0x03);  // 0x03 flags for shmget
124    PARAM_CHECK(key != -1, return NULL, "Invalid errno %d key for %s", errno, fileName);
125    handle->shmid = shmget(key, spaceSize, IPC_CREAT | IPC_EXCL | 0666);  // 0666
126    if (handle->shmid == -1) {
127        handle->shmid = shmget(key, spaceSize, 0);  // 0666
128    }
129    PARAM_CHECK(handle->shmid != -1, return NULL, "Invalid shmId errno %d for %s", errno, fileName);
130    areaAddr = (void *)shmat(handle->shmid, NULL, 0);
131    return areaAddr;
132}
133
134INIT_LOCAL_API void FreeSharedMem(const MemHandle *handle, void *mem, uint32_t dataSize)
135{
136    PARAM_CHECK(mem != NULL && handle != NULL, return, "Invalid mem or handle");
137    shmdt(mem);
138    shmctl(handle->shmid, IPC_RMID, NULL);
139}
140
141INIT_LOCAL_API void paramMutexEnvInit(void)
142{
143    return;
144}
145
146INIT_LOCAL_API int ParamRWMutexCreate(ParamRWMutex *lock)
147{
148    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
149    pthread_rwlockattr_t rwlockatt;
150    pthread_rwlockattr_init(&rwlockatt);
151    pthread_rwlockattr_setpshared(&rwlockatt, PTHREAD_PROCESS_SHARED);
152    pthread_rwlock_init(&lock->rwlock, &rwlockatt);
153    return 0;
154}
155
156INIT_LOCAL_API int ParamRWMutexWRLock(ParamRWMutex *lock)
157{
158    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
159    pthread_rwlock_wrlock(&lock->rwlock);
160    return 0;
161}
162INIT_LOCAL_API int ParamRWMutexRDLock(ParamRWMutex *lock)
163{
164    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
165    pthread_rwlock_rdlock(&lock->rwlock);
166    return 0;
167}
168INIT_LOCAL_API int ParamRWMutexUnlock(ParamRWMutex *lock)
169{
170    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
171    pthread_rwlock_unlock(&lock->rwlock);
172    return 0;
173}
174
175INIT_LOCAL_API int ParamRWMutexDelete(ParamRWMutex *lock)
176{
177    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
178    uint32_t ret = pthread_rwlock_destroy(&lock->rwlock);
179    PARAM_CHECK(ret == 0, return -1, "Failed to mutex lock ret %d", ret);
180    return 0;
181}
182
183INIT_LOCAL_API int ParamMutexCreate(ParamMutex *mutex)
184{
185    PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex");
186    pthread_mutexattr_t mutexattr;
187    pthread_mutexattr_init(&mutexattr);
188    pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
189    pthread_mutex_init(&mutex->mutex, &mutexattr);
190    return 0;
191}
192INIT_LOCAL_API int ParamMutexPend(ParamMutex *mutex)
193{
194    PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex");
195    if (pthread_mutex_lock(&mutex->mutex) != 0) {
196        PARAM_LOGE("Failed to batch begin to save param errno %d", errno);
197        return errno;
198    }
199    return 0;
200}
201INIT_LOCAL_API int ParamMutexPost(ParamMutex *mutex)
202{
203    PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex");
204    pthread_mutex_unlock(&mutex->mutex);
205    return 0;
206}
207
208INIT_LOCAL_API int ParamMutexDelete(ParamMutex *mutex)
209{
210    PARAM_CHECK(mutex != NULL, return -1, "Invalid lock");
211    uint32_t ret = pthread_mutex_destroy(&mutex->mutex);
212    PARAM_CHECK(ret == 0, return -1, "Failed to mutex lock ret %d", ret);
213    return 0;
214}
215#endif
216
217#ifdef __LITEOS_M__
218__attribute__((weak)) void* GetSysParamMem(uint32_t spaceSize)
219{
220    return malloc(spaceSize);
221}
222
223__attribute__((weak)) void FreeSysParamMem(void *mem)
224{
225    if (mem == NULL) {
226        return;
227    }
228    free(mem);
229}
230
231INIT_LOCAL_API void *GetSharedMem(const char *fileName, MemHandle *handle, uint32_t spaceSize, int readOnly)
232{
233    PARAM_CHECK(spaceSize <= PARAM_WORKSPACE_MAX, return NULL, "Invalid spaceSize %u", spaceSize);
234    UNUSED(fileName);
235    UNUSED(handle);
236    UNUSED(readOnly);
237    return GetSysParamMem(spaceSize);
238}
239
240INIT_LOCAL_API void FreeSharedMem(const MemHandle *handle, void *mem, uint32_t dataSize)
241{
242    PARAM_CHECK(mem != NULL && handle != NULL, return, "Invalid mem or handle");
243    UNUSED(handle);
244    UNUSED(dataSize);
245    FreeSysParamMem(mem);
246}
247
248INIT_LOCAL_API void paramMutexEnvInit(void)
249{
250    return;
251}
252
253INIT_LOCAL_API int ParamRWMutexCreate(ParamRWMutex *lock)
254{
255    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
256    uint32_t ret = LOS_MuxCreate(&lock->mutex);
257    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to init mutex ret %d", ret);
258    return 0;
259}
260
261INIT_LOCAL_API int ParamRWMutexWRLock(ParamRWMutex *lock)
262{
263    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
264    uint32_t ret = LOS_MuxPend(lock->mutex, LOS_WAIT_FOREVER);
265    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex);
266    return 0;
267}
268
269INIT_LOCAL_API int ParamRWMutexRDLock(ParamRWMutex *lock)
270{
271    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
272    uint32_t ret = LOS_MuxPend(lock->mutex, LOS_WAIT_FOREVER);
273    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex);
274    return 0;
275}
276
277INIT_LOCAL_API int ParamRWMutexUnlock(ParamRWMutex *lock)
278{
279    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
280    uint32_t ret = LOS_MuxPost(lock->mutex);
281    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex);
282    return 0;
283}
284
285INIT_LOCAL_API int ParamRWMutexDelete(ParamRWMutex *lock)
286{
287    PARAM_CHECK(lock != NULL, return -1, "Invalid lock");
288    uint32_t ret = LOS_MuxDelete(lock->mutex);
289    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex);
290    return 0;
291}
292
293INIT_LOCAL_API int ParamMutexCreate(ParamMutex *mutex)
294{
295    PARAM_CHECK(mutex != NULL, return -1, "Invalid lock");
296    uint32_t ret = LOS_MuxCreate(&mutex->mutex);
297    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to init mutex ret %d", ret);
298    return 0;
299}
300
301INIT_LOCAL_API int ParamMutexPend(ParamMutex *mutex)
302{
303    PARAM_CHECK(mutex != NULL, return -1, "Invalid lock");
304    uint32_t ret = LOS_MuxPend(mutex->mutex, LOS_WAIT_FOREVER);
305    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, mutex->mutex);
306    return 0;
307}
308
309INIT_LOCAL_API int ParamMutexPost(ParamMutex *mutex)
310{
311    PARAM_CHECK(mutex != NULL, return -1, "Invalid lock");
312    uint32_t ret = LOS_MuxPost(mutex->mutex);
313    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, mutex->mutex);
314    return 0;
315}
316
317INIT_LOCAL_API int ParamMutexDelete(ParamMutex *mutex)
318{
319    PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex");
320    uint32_t ret = LOS_MuxDelete(mutex->mutex);
321    PARAM_CHECK(ret == LOS_OK, return -1, "Failed to delete mutex lock ret %d %d", ret, mutex->mutex);
322    return 0;
323}
324#endif
325
326