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.
18 // #include <stdlib.h>
26 #include <native_service/cl_lock.h>
27 #include <native_service/cl_lockid.h>
28 #include "cl_lock_internal.h"
31 static int shm_id = -1;
34 * Lock file is consists of slots(4KB)
36 * 0 ~ 4Byte : field of PID
37 * 4Byte ~ 28Byte : field of pthread_mutex_t
41 static int cl_LockfileInit(void *base) {
47 pthread_mutexattr_t attr;
49 if (pthread_mutexattr_init(&attr) != 0) { // LCOV_EXCL_BR_LINE 5:fail safe for libc pthread_mutexattr_init
50 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
52 return -1; // LCOV_EXCL_LINE 5:fail safe for libc pthread_mutexattr_init
54 if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) != 0) { // LCOV_EXCL_BR_LINE 5:fail safe for libc pthread_mutexattr_setpshared
55 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
57 return -1; // LCOV_EXCL_LINE 5:fail safe for libc pthread_mutexattr_setpshared
59 // if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP) != 0) {
62 if (pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST) != 0) {
66 for (i = 0; i < LID_NUM; i++) {
68 addr = SLOT_SIZE * 1 + base;
69 for (j = 0; j < 1024; j++) {
70 *(int*)(addr + j * sizeof(int)) = j;
73 addr = SLOT_SIZE * i + (char *)base + sizeof(int);
74 pthread_mutex_init((pthread_mutex_t *)addr, &attr);
77 if (pthread_mutexattr_destroy(&attr) != 0) { // LCOV_EXCL_BR_LINE 5:fail safe for libc pthread_mutexattr_destroy
78 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
80 return -1; // LCOV_EXCL_LINE 5:fail safe for libc pthread_mutexattr_destroy
86 * Initialize in the system
87 * This function will generate the Lock file, and initialize pthread_mutex_t for all slots
89 int CL_LockSystemInit(void) {
92 void *base = MAP_FAILED;
94 fd = shm_open(LOCKFILE_NAME, O_CREAT | O_EXCL | O_RDWR, (S_IRWXG | S_IRWXO | S_IRWXU));
99 if (ftruncate(fd, LOCKFILE_SIZE) != 0) { // LCOV_EXCL_BR_LINE 5:fail safe for libc ftruncate
100 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
102 ret = -1; // LCOV_EXCL_LINE 5:fail safe for libc ftruncate
103 goto exit; // LCOV_EXCL_LINE 5:fail safe for libc ftruncate
106 base = mmap(NULL, LOCKFILE_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
107 if (base == MAP_FAILED) { // LCOV_EXCL_BR_LINE 5:fail safe for libc mmap
108 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
110 ret = -1; // LCOV_EXCL_LINE 5:fail safe for libc mmap
111 goto exit; // LCOV_EXCL_LINE 5:fail safe for libc mmap
114 if (cl_LockfileInit(base) < 0) { // LCOV_EXCL_BR_LINE 11:out branch
115 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
117 ret = -1; // LCOV_EXCL_LINE 5:fail safe for libc
118 goto exit; // LCOV_EXCL_LINE 5:fail safe for libc
125 if (base != MAP_FAILED) {
126 munmap(base, LOCKFILE_SIZE);
131 void CL_LockSystemFin_debug(void) {
135 shm_unlink(LOCKFILE_NAME);
140 * Initialize in the process
143 int CL_LockProcessInit(void) {
145 shm_id = shm_open(LOCKFILE_NAME, O_RDWR, (S_IRWXG | S_IRWXO | S_IRWXU));
147 if (shm_id < 0) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function shm_open
148 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
150 return -1; // LCOV_EXCL_LINE 5: fail safe for glibc function shm_open
155 void *CL_LockMap(int lid) {
156 if ((lid < 0) || (lid >= LID_NUM)) {
160 return mmap(NULL, SLOT_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, shm_id, (off_t)(lid * SLOT_SIZE));
163 int CL_LockUnmap(void *addr) {
164 return munmap(addr, SLOT_SIZE);
167 int CL_LockGet(void *addr) {
170 if ((addr == NULL) || (addr == MAP_FAILED)) {
173 CL_DBG_PRINT("@@@@@ %s Start: pid = %d\n", __func__, *(int *)addr);
174 // LCOV_EXCL_BR_START 5:fail safe for libc pthread_mutex_lock
175 if ((ret = pthread_mutex_lock((pthread_mutex_t*)((char *)addr + sizeof(int)))) == 0) {
177 *(int *)addr = (int)getpid();
178 } else if (ret == EOWNERDEAD) {
179 if ((ret = pthread_mutex_consistent((pthread_mutex_t *)((char *)addr + sizeof(int)))) == 0) {
180 *(int *)addr = (int)getpid();
183 CL_DBG_PRINT("@@@@@ %s End: pid = %d\n", __func__, *(int *)addr);
188 int CL_LockNowait(void *addr) {
191 if ((addr == NULL) || (addr == MAP_FAILED)) {
194 CL_DBG_PRINT("@@@@@ %s Start: pid = %d\n", __func__, *(int *)addr);
195 if ((ret = pthread_mutex_trylock((pthread_mutex_t*)((char *)addr + sizeof(int)))) == 0) {
196 *(int *)addr = (int)getpid();
197 } else if (ret == EOWNERDEAD) {
198 if ((ret = pthread_mutex_consistent((pthread_mutex_t *)((char *)addr + sizeof(int)))) == 0) {
199 *(int *)addr = (int)getpid();
202 CL_DBG_PRINT("@@@@@ %s End: pid = %d\n", __func__, *(int *)addr);
208 int CL_LockRelease(void *addr) {
210 if ((addr == NULL) || (addr == MAP_FAILED)) {
213 CL_DBG_PRINT("@@@@@ %s : pid = %d\n", __func__, *(int *)addr);
214 *(int *)addr = (int)0;
215 ret = pthread_mutex_unlock((pthread_mutex_t*)((char *)addr + sizeof(int)));