2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include <semaphore.h>
27 #include <native_service/cl_region.h>
28 #include <native_service/cl_monitor.h>
30 #define CL_MONITOR_SHM_NAME "/cl_monitor"
32 #define CL_MONITOR_ID_REAL_GENERIC_START (0)
33 #define CL_MONITOR_ID_REAL_GENERIC_END (1023)
34 #define CL_MONITOR_ID_REAL_RPC_START (49952)
35 #define CL_MONITOR_ID_REAL_RPC_END (59999)
37 #define CL_MONITOR_ID_FLAT_GENERIC_START (0)
38 #define CL_MONITOR_ID_FLAT_GENERIC_END \
39 (CL_MONITOR_ID_FLAT_GENERIC_START + (CL_MONITOR_ID_REAL_GENERIC_END - CL_MONITOR_ID_REAL_GENERIC_START))
40 #define CL_MONITOR_ID_FLAT_RPC_START (CL_MONITOR_ID_FLAT_GENERIC_END + 1)
41 #define CL_MONITOR_ID_FLAT_RPC_END \
42 (CL_MONITOR_ID_FLAT_RPC_START + (CL_MONITOR_ID_REAL_RPC_END - CL_MONITOR_ID_REAL_RPC_START))
43 #define CL_MONITOR_ENTRY_NUM (CL_MONITOR_ID_FLAT_RPC_END + 1)
45 #define CL_MONITOR_BITMAP_LENGTH ((CL_MONITOR_ENTRY_NUM + 63) / 64) // aligned
47 #define CL_ALIGN(x, a) (((x) + (a - 1)) / (a) * (a))
49 struct cl_monitor_header {
51 uint64_t bitmap[CL_MONITOR_BITMAP_LENGTH];
55 #define CL_MONITOR_OBJECT_SIZE \
56 CL_ALIGN((sizeof(struct cl_monitor_header) + (sizeof(CL_MonitorEntry_t) * CL_MONITOR_ENTRY_NUM)), 4096)
58 #define CL_MONITOR_SET_BIT(a, i) (a[i / 64] |= (1ULL << (i % 64)))
59 #define CL_MONITOR_CLEAR_BIT(a, i) (a[i / 64] &= ~(1ULL << (i % 64)))
61 static struct cl_monitor_header *cl_monitor_obj;
62 static CL_MonitorEntry_t *cl_monitor_entry_head;
64 int CL_MonitorInit(CL_MonitorInit_t init_type) {
69 if (init_type != CL_MONITOR_INIT_SYSTEM && init_type != CL_MONITOR_INIT_USER) {
74 if (cl_monitor_obj != NULL) {
78 if (init_type == CL_MONITOR_INIT_SYSTEM) {
79 oflag = O_RDWR | O_CREAT | O_EXCL;
86 if ((fd = shm_open(CL_MONITOR_SHM_NAME, oflag, mode)) == -1) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function shm_open
87 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
89 return -1;// LCOV_EXCL_LINE 5: fail safe for glibc function shm_open
92 if (init_type == CL_MONITOR_INIT_SYSTEM) {
93 if (ftruncate(fd, CL_MONITOR_OBJECT_SIZE) == -1) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function ftruncate
94 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
96 return -1; // LCOV_EXCL_LINE 5: fail safe for glibc function ftruncate
100 if (fstat(fd, &st_buf) == -1) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function fstat
101 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
103 return -1; // LCOV_EXCL_LINE 5: fail safe for glibc function fstat
106 if (st_buf.st_size != CL_MONITOR_OBJECT_SIZE) {
112 // LCOV_EXCL_BR_START 5: fail safe for glibc function mmap
113 if ((cl_monitor_obj = mmap(NULL, CL_MONITOR_OBJECT_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
115 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
117 return -1; // LCOV_EXCL_LINE 5: fail safe for glibc function mmap
120 if (init_type == CL_MONITOR_INIT_SYSTEM) { // LCOV_EXCL_BR_LINE 11: out branch
121 memcpy(cl_monitor_obj->signature, "CLAM", 4);
122 memset(cl_monitor_obj->bitmap, 0, sizeof(cl_monitor_obj->bitmap));
123 sem_init(&cl_monitor_obj->sem, 1, 1);
125 cl_monitor_entry_head = (CL_MonitorEntry_t *)(((char *)cl_monitor_obj) + sizeof(struct cl_monitor_header));
130 static inline int cl_monitor_check_type_id(CL_MonitorType_t type, uint32_t id, int *offset) {
131 if (type == CL_MONITOR_TYPE_GENERIC) {
132 if (id > CL_MONITOR_ID_REAL_GENERIC_END) {
136 *offset = (int)((id - CL_MONITOR_ID_REAL_GENERIC_START) + CL_MONITOR_ID_FLAT_GENERIC_START);
137 } else if (type == CL_MONITOR_TYPE_RPC) {
138 if (id < CL_MONITOR_ID_REAL_RPC_START || id > CL_MONITOR_ID_REAL_RPC_END) {
142 *offset = (int)((id - CL_MONITOR_ID_REAL_RPC_START) + CL_MONITOR_ID_FLAT_RPC_START);
151 static inline int cl_monitor_sem_wait(sem_t *sem) {
156 if (ret == -1) { // LCOV_EXCL_BR_LINE 5: fail safe for libc sem_wait
157 // LCOV_EXCL_START 5: fail safe for libc sem_wait
159 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
161 if (errno == EINTR) {
164 CL_PERROR("sem_wait");
171 static inline int cl_monitor_sem_post(sem_t *sem) {
174 if ((ret = sem_post(sem)) == -1) { // LCOV_EXCL_BR_LINE 5: fail safe for libc sem_post
175 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
177 CL_PERROR("sem_post"); // LCOV_EXCL_LINE 5: fail safe for libc sem_post
183 int CL_MonitorSetEntry(CL_MonitorType_t type, uint32_t id, CL_MonitorState_t state, uint32_t timeout,
184 uint32_t user_data) {
186 CL_MonitorEntry_t *e;
189 if (cl_monitor_obj == NULL) {
194 if (cl_monitor_check_type_id(type, id, &offset) == -1) {
198 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) { // LCOV_EXCL_BR_LINE 5: fail safe for libc clock_gettime
199 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
201 return -1; // LCOV_EXCL_LINE 5: fail safe for libc clock_gettime
204 e = cl_monitor_entry_head + offset;
205 cl_monitor_sem_wait(&cl_monitor_obj->sem);
207 if (state == CL_MONITOR_STATE_SLEEP) {
208 memset(e, 0, sizeof(CL_MonitorEntry_t));
209 CL_MONITOR_CLEAR_BIT(cl_monitor_obj->bitmap, offset);
211 e->pid = (uint16_t)getpid();
215 // e->timeout = (uint32_t)ts.tv_sec + timeout;
216 e->timeout = ts.tv_sec + timeout;
218 e->user_data = user_data;
219 CL_MONITOR_SET_BIT(cl_monitor_obj->bitmap, offset);
222 cl_monitor_sem_post(&cl_monitor_obj->sem);
227 int CL_MonitorGetEntry(CL_MonitorType_t type, uint32_t id, CL_MonitorEntry_t *entry) {
229 CL_MonitorEntry_t *e;
231 if (cl_monitor_obj == NULL) {
241 if (cl_monitor_check_type_id(type, id, &offset) == -1) {
245 e = cl_monitor_entry_head + offset;
246 cl_monitor_sem_wait(&cl_monitor_obj->sem);
248 memcpy(entry, e, sizeof(CL_MonitorEntry_t));
250 cl_monitor_sem_post(&cl_monitor_obj->sem);
255 int CL_MonitorSearchInit(CL_MonitorSearch_t *serch) {
261 serch->entry_list = NULL;
262 serch->entry_num = 0;
266 int CL_MonitorSearchDestroy(CL_MonitorSearch_t *serch) {
272 free(serch->entry_list);
273 serch->entry_num = 0;
277 static inline int cl_monitor_popcnt64(uint64_t x) {
280 n = (x >> 1) & 0x7777777777777777ULL;
282 n = (n >> 1) & 0x7777777777777777ULL;
284 n = (n >> 1) & 0x7777777777777777ULL;
286 x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
287 x = x * 0x0101010101010101ULL;
288 return (int)(x >> 56);
291 typedef struct cl_monitor_offset_s cl_monitor_offset_t;
292 struct cl_monitor_offset_s {
293 cl_monitor_offset_t *next;
297 int CL_MonitorSearchTimeout(CL_MonitorSearch_t *search) {
300 CL_MonitorEntry_t *e;
302 int timeout_entry_num = 0;
304 cl_monitor_offset_t *o, *head = NULL, *tail = NULL;
306 if (cl_monitor_obj == NULL) {
311 if (search == NULL) {
316 if ((r = CL_RegionCreate(CL_REGION_DEFAULT_SIZE)) == NULL) {
321 free(search->entry_list);
322 search->entry_list = NULL;
324 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {// LCOV_EXCL_BR_LINE 5: fail safe for libc clock_gettime
325 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
327 return -1;// LCOV_EXCL_LINE 5: fail safe for libc clock_gettime
330 cl_monitor_sem_wait(&cl_monitor_obj->sem);
332 for (i = 0; i < CL_MONITOR_BITMAP_LENGTH; i++) {
333 if (cl_monitor_obj->bitmap[i] != 0) {
334 uint64_t bits, mrb1; // most right bit 1
336 bits = cl_monitor_obj->bitmap[i];
338 mrb1 = bits & (-bits);
339 offset = i * 64 + cl_monitor_popcnt64(mrb1 - 1);
340 e = cl_monitor_entry_head + offset;
342 if (e->timeout <= ts.tv_sec) {
344 if ((o = CL_RegionAlloc(r, cl_monitor_offset_t, 1)) == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for mmap
345 // LCOV_EXCL_START 5: fail safe for libc mmap
346 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
348 timeout_entry_num = -1;
368 if (timeout_entry_num) {
369 CL_MonitorEntry_t *src, *dst;
370 dst = malloc(sizeof(CL_MonitorEntry_t) * (size_t)timeout_entry_num);
371 if (dst == NULL) { // LCOV_EXCL_LINE 5: fail safe for libc malloc
372 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
374 errno = ENOMEM; // LCOV_EXCL_LINE 5: fail safe for libc malloc
375 timeout_entry_num = -1; // LCOV_EXCL_LINE 5: fail safe for libc malloc
376 goto exit; // LCOV_EXCL_LINE 5: fail safe for libc malloc
379 search->entry_list = dst;
381 for (i = 0; i < timeout_entry_num; i++) {
382 src = cl_monitor_entry_head + o->offset;
383 memcpy(dst, src, sizeof(CL_MonitorEntry_t));
391 cl_monitor_sem_post(&cl_monitor_obj->sem);
394 search->entry_num = (timeout_entry_num == -1) ? 0 : timeout_entry_num; // LCOV_EXCL_BR_LINE 11: out branch
395 return timeout_entry_num;
398 int cl_monitor_cleanup(int pid) {
402 CL_MonitorEntry_t *e;
404 if (cl_monitor_obj == NULL) {
409 if (pid <= 0) { // LCOV_EXCL_LINE 5: fail safe for glibc function waitid
410 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
412 errno = EINVAL;// LCOV_EXCL_LINE 5: fail safe for glibc function waitid
413 return -1;// LCOV_EXCL_LINE 5: fail safe for glibc function waitid
416 cl_monitor_sem_wait(&cl_monitor_obj->sem);
418 for (i = 0; i < CL_MONITOR_BITMAP_LENGTH; i++) {
419 if (cl_monitor_obj->bitmap[i] != 0) {
420 uint64_t bits, mrb1; // most right bit 1
422 bits = cl_monitor_obj->bitmap[i];
424 mrb1 = bits & (-bits);
425 offset = i * 64 + cl_monitor_popcnt64(mrb1 - 1);
427 e = cl_monitor_entry_head + offset;
429 memset(e, 0, sizeof(CL_MonitorEntry_t));
430 CL_MONITOR_CLEAR_BIT(cl_monitor_obj->bitmap, offset);
439 cl_monitor_sem_post(&cl_monitor_obj->sem);