common_library: gettid is multiple declaration in cl_error
[staging/basesystem.git] / video_in_hal / vehicleservice / positioning_base_library / library / src / _pbSem.cpp
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * @file
19  *    _pbSem.cpp
20   */
21
22 #include <vehicle_service/positioning_base_library.h>
23 #include "_pbInternalProc.h"
24 #include "WPF_STD_private.h"
25 #include "tchar.h"
26
27 /*
28  Constants and structure definitions
29 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
30 #define MAX_PB_SEMAPHORES                        256
31 #define MAX_SEMAPHORE_NAME_LEN                    32
32 #define MAX_PB_SEMAPHORES_INPROC                16
33
34 /* Name storage table */
35 typedef struct {
36     TCHAR             semaphore_name[MAX_SEMAPHORE_NAME_LEN + 1];    /* Semaphore name(Specified name of the user APP) */
37     DWORD             ref_counter;                                    /* Reference Counter (Currently unused, always 1) */
38 } PB_SEMAPHORE;
39
40 /* Control information storage table */
41 typedef struct {
42     HANDLE           h_heap;          /* Handle of the heap area allocated for expanding the self TBL (control-information-storage TBL)  */
43     PB_SEMAPHORE*    p_sys_semaphore;  /* Address where the self name in the name storage table is stored (Top address of self name)    */
44     DWORD            index;          /* Semaphore ID that is equal to the index of self TBL (control information strage TBL:p_handle_table) + 1   */
45     HANDLE           h_semaphore;     /* Semaphore handle (Semaphore or Mutex according to the above DEBUG defines)     */
46     HANDLE           h_mutex;        /* Mutex handle for locking when updating the self TBL (control information storage TBL)  */
47 } PB_SEMAPHORE_OPEN_HANDLE;
48
49 /* Semaphore information management table */
50 typedef struct {
51     PB_SEMAPHORE_OPEN_HANDLE* p_handle_table[MAX_PB_SEMAPHORES];    /* Pointer to control information storage table      */
52     HANDLE                    h_shared_memory;        /* Handle of shared memory allocated for name storage table to expand  */
53     HANDLE                    h_mutex;                /* Mutex handle to lock when updating the name storage table */
54     PB_SEMAPHORE*             p_semaphore_table;   /* Pointer to the name storage table (Allocate as many areas as the maximum number of registrations in shared memory)*/
55 } PB_SEMAPHORE_INSTANCE;
56
57 typedef struct      /* In-process semaphore management table */ {
58     char                 semaphore_name[MAX_SEMAPHORE_NAME_LEN];        /* Semaphore name (Specified name of the user APP)   */
59     HANDLE               h_heap;                           /* Heap handle of critical section structure area */
60     CRITICAL_SECTION    *p_cs;                           /* Critical section pointer(Semaphore ID)    */
61 } PB_SEM_INPROC;
62
63 /*
64  Internal function prototype declarations
65 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
66 static DWORD    FindSemaphoreTable(PB_SEMAPHORE* p_semaphore_table, TCHAR* name, HANDLE h_mutex);
67 static DWORD    AllocNewSemaphoreTable(PB_SEMAPHORE* p_semaphore_table, TCHAR* name, HANDLE h_mutex);
68 static void     FreeSemaphoreTable(PB_SEMAPHORE* p_semaphore_table, int index, HANDLE h_mutex);
69
70 /*
71  Global variable definitions
72 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
73 static PB_SEMAPHORE_INSTANCE    g_instance;    // NOLINT(readability/nolint)  global class instance
74 /* CS for exclusive control of in-process semaphore management table */
75 CRITICAL_SECTION                g_sem_in_proc_tbl_mng_cs;
76 /* Pointer to the in-process semaphore management table */
77 PB_SEM_INPROC                   *g_p_sem_in_proc_mng = NULL;
78
79 /*
80  *    Inline functions.
81  */
82 inline void
83 MakeSemaphoreName(TCHAR* name, DWORD index) {
84     wsprintf(name, __TEXT("POS_BASE_SEMAPHORE_SEM%05d"), static_cast<int32>(index));
85 }
86 inline void
87 MakeMutexName(TCHAR* name, DWORD index) {
88     wsprintf(name, __TEXT("POS_BASE_SEMAPHORE_MUTEX%05d"), static_cast<int32>(index));
89 }
90
91 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
92  * MODULE    : SemaphoreInit
93  * ABSTRACT  : Semaphore initialization processing
94  * NOTE      : This function is called when _CWORD64_api.dll is ATTACH from processes
95  *           : and initializes the process.
96  * ARGUMENT  : None
97  * RETURN    : RET_API    RET_NORMAL        Normal completion
98  *                        RET_ERRINIT        ABEND
99  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
100 RET_API
101 SemaphoreInit(void) {
102     RET_API                    ret_api = RET_NORMAL;
103     PB_SEMAPHORE_INSTANCE *p_inst = &g_instance;
104     TCHAR                    name[32] = {0};
105     DWORD                    semaphore_table_size = 0;
106     int32                     n = 0;
107     PB_SEMAPHORE           *p_semaphore_table = NULL;
108     BOOL                    b_create = FALSE;
109
110     /* Initialize the semaphore information management table */
111     for (n = 0; n < MAX_PB_SEMAPHORES; n++) {
112         p_inst->p_handle_table[n] = NULL;            /* NULL initialize the control data storage table */
113     }
114
115     /* Initialize the semaphore name storage table */
116     _tcscpy(name, __TEXT("POS_BASE_SEMAPHORE_TABLE"));
117     semaphore_table_size = sizeof(PB_SEMAPHORE) * MAX_PB_SEMAPHORES;
118     /* Open shared memory with the name _CWORD64__SEMAPHORE_TABLE */
119     p_inst->h_shared_memory = OpenSharedMemory(name, semaphore_table_size);
120     if (p_inst->h_shared_memory == NULL)              /* If shared memory does not exist */ {
121         /* Create a shared memory with the name _CWORD64__SEMAPHORE_TABLE */
122         p_inst->h_shared_memory = CreateSharedMemory(name, semaphore_table_size);
123         if (p_inst->h_shared_memory == NULL)          /* If shared memory creation fails */ {
124             ret_api = RET_ERRINIT;                /* Ends in error */
125         } else {
126             b_create = TRUE;                        /* Create shared memory */
127
128             /* Allocate the created shared memory to the semaphore name storage table and initialize it. */
129             // LCOV_EXCL_BR_START 200: cannot be null
130             p_semaphore_table = reinterpret_cast<PB_SEMAPHORE*>(GetSharedMemoryPtr(p_inst->h_shared_memory));
131             // LCOV_EXCL_BR_STOP
132             if (p_semaphore_table == NULL) {    // LCOV_EXCL_BR_LINE 200: cannot be null
133                 // LCOV_EXCL_START 200: cannot be null
134                 AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
135                 CloseSharedMemory(p_inst->h_shared_memory);
136                 DeleteSharedMemory(name);
137                 ret_api = RET_ERRINIT;            /* Ends in error */
138                 // LCOV_EXCL_STOP
139             } else {
140                 for (n = 0; n < MAX_PB_SEMAPHORES; n++) {
141                     p_semaphore_table[n].semaphore_name[0] = __TEXT('\0');    /* Initialize name */
142                     p_semaphore_table[n].ref_counter = 0;                /* Initialize reference counter */
143                 }
144             }
145         }
146     }
147
148     if (ret_api == RET_NORMAL) {
149         /* Save the address of the shared memory to the name storage table pointer of the semaphore information management table. */
150         // LCOV_EXCL_BR_START 200: cannot be null
151         p_inst->p_semaphore_table = reinterpret_cast<PB_SEMAPHORE*>(GetSharedMemoryPtr(p_inst->h_shared_memory));
152         // LCOV_EXCL_BR_STOP
153         if (p_inst->p_semaphore_table == NULL) {  // LCOV_EXCL_BR_LINE 200: cannot be null
154             // LCOV_EXCL_START 200: cannot be null
155             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
156             CloseSharedMemory(p_inst->h_shared_memory);
157             if (b_create != FALSE) {
158                 DeleteSharedMemory(name);
159             }
160             ret_api = RET_ERRINIT;            /* Ends in error */
161             // LCOV_EXCL_STOP
162         } else {
163             /* Mutex creation process for semaphore-information-management table */
164             _tcscpy(name, __TEXT("POS_BASE_SEMAPHORE_MUTEX"));
165             /* Save the handle of the created Mutex in the Mutex handles for semaphore-information-management-table */
166             p_inst->h_mutex = _pb_CreateMutex(NULL, FALSE, name);  // LCOV_EXCL_BR_LINE 200: can not be null
167             if (p_inst->h_mutex == NULL) {  /* Failed to create a Mutex. */  // LCOV_EXCL_BR_LINE 200: can not be null
168                 // LCOV_EXCL_START 200: can not be null
169                 AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
170                 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "_CWORD64_api.dll:%s:LINE %d\r\n CreateMutex ERROR " \
171                     "In SemaphoreInit\r\n", LTEXT(__FILE__), __LINE__);
172                 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Mutex_Name : %s\r\n", name);
173                 _pb_Exit();
174                 // LCOV_EXCL_STOP
175             }
176         }
177     }
178
179     return ret_api;
180 }
181
182 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
183  * MODULE    : SemaphoreTerm
184  * ABSTRACT  : Semaphore function termination processing
185  * NOTE      : Called when the process ATTACH to _CWORD64_api.dll terminates, and then terminated.
186  * ARGUMENT  : None
187  * RETURN    : RET_API    RET_NORMAL        Always this value
188  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
189 RET_API
190 SemaphoreTerm(void) {  // LCOV_EXCL_START 8:dead code
191     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
192     PB_SEMAPHORE_INSTANCE *p_inst = &g_instance;
193
194     if (p_inst->h_mutex != NULL) {
195         PbDeleteMutex(p_inst->h_mutex);
196         p_inst->h_mutex = NULL;
197     }
198
199     if (p_inst->h_shared_memory != NULL) {
200         CloseSharedMemory(p_inst->h_shared_memory);
201         p_inst->h_shared_memory = NULL;
202     }
203
204     return RET_NORMAL;
205 }
206 // LCOV_EXCL_STOP
207
208 /**
209  * @brief
210  *   Create Semaphore
211  *
212  *   Create a semaphore and return a semaphore ID.<br>
213  *   For a semaphore that has already been created, return the same value of the semaphore ID when it has been created.
214  *
215  * @param[in]    *sem_name    Pointer to the semaphore name string to be created (NULL termination)
216  *
217  * @return Semaphore ID created other than 0<br>
218  *              0       ABEND to create semaphore
219  */
220 #ifdef _CWORD64_API_DOES_NOT_USE_UNICODE
221 SemID _pb_CreateSemaphore(char* sem_name)    // NOLINT(readability/nolint) WPF_SYSAPI.h API
222 #else
223 SemID _pb_CreateSemaphore(TCHAR* sem_name)   // NOLINT(readability/nolint) WPF_SYSAPI.h API
224 #endif  // _CWORD64_API_DOES_NOT_USE_UNICODE
225 {
226     SemID                   ret_sem_id = 0;
227     TCHAR                   *p_semaphore_name = NULL;
228     PB_SEMAPHORE_INSTANCE   *p_inst = &g_instance;
229     TCHAR                    name[MAX_SEMAPHORE_NAME_LEN + 1] = {0};
230     PB_SEMAPHORE_OPEN_HANDLE *p_semaphore_open = NULL;
231     DWORD                    index = 0;
232
233     /* Check if the semaphore name is NULL */
234     if (sem_name == NULL) {
235     } else {
236         p_semaphore_name = sem_name;
237
238         /* Check if the semaphore name is specified */
239         if (p_semaphore_name[0] == __TEXT('\0')) {
240         } else if (_tcslen(p_semaphore_name) > MAX_SEMAPHORE_NAME_LEN) {
241             /* Check whether the semaphore name is less than or equal to the maximum number of characters */
242         } else {
243             /* Allocate Heap control information storage table area to create a semaphore */
244             p_semaphore_open = reinterpret_cast<PB_SEMAPHORE_OPEN_HANDLE *>(PbProcessHeapAlloc(0, \
245                 sizeof(PB_SEMAPHORE_OPEN_HANDLE)));  // LCOV_EXCL_BR_LINE 200: no branch
246         }
247
248         if (p_semaphore_open != NULL) {
249             PbMutexLock(p_inst->h_mutex, INFINITE);  /* Mutex Lock from here */  // LCOV_EXCL_BR_LINE 200: no branch  // NOLINT(whitespace/line_length)
250
251             /* Retrieve the name storage table expanded in the shared memory with the user-specified name. */
252             index = FindSemaphoreTable(p_inst->p_semaphore_table, p_semaphore_name, p_inst->h_mutex);
253             if (index != ((DWORD) - 1)) {
254                 /* The semaphore name specified for the user already exists. */
255                 /* Check if the control information storage table exists */
256                 if (p_inst->p_handle_table[index] != NULL) {
257                     /* If the control information storage TBL exists,(If it has already been created by this process) */
258                     /* release the previously allocated Heap because it is not needed. */
259                     PbProcessHeapFree(0, p_semaphore_open);  // LCOV_EXCL_BR_LINE 200: no branch
260                      /* Retrieve the pointer to the TBL storing the existing control information. */
261                     p_semaphore_open = p_inst->p_handle_table[index];
262                     PbMutexUnlock(p_inst->h_mutex);  /* Mutex release */  // LCOV_EXCL_BR_LINE 200: no branch
263                     /* Convert from an index of array to a semaphore ID and return (If it has already been created in this process) */
264                     ret_sem_id = static_cast<SemID>(index + 1);
265                 } else {
266                     // LCOV_EXCL_START 200: p_handle_table can not be NULL
267                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
268                     /* If a semaphore with the established name exists but the control information table does not exist, link to it  or create it in the following processing. */
269                     /* (A semaphore was created by another process or the created process was terminated.) */
270                     /* Store the assigned semaphore ID in the control information storage table. */
271                     p_semaphore_open->index = index;
272                     /* Store the start address of the name storage table */
273                     p_semaphore_open->p_sys_semaphore = &p_inst->p_semaphore_table[index];
274                     /* Store the address of the control information TBL (Heap) into the semaphore information management TBL. */
275                     p_inst->p_handle_table[index] = p_semaphore_open;
276
277                     /* Create the object name of the semaphore from the position (index of array) of the control information storage TBL. */
278                     /* "_CWORD64__SEMAPHORE_SEMAPHORExxxxx" : xxxxx is expanded with five-digit array index */
279                     MakeSemaphoreName(name, index);
280
281                     /* Create a semaphore object using Mutex and store its handle into the control information storage TBL. */
282                     p_semaphore_open->h_semaphore = _pb_CreateMutex(NULL, FALSE, name);
283                     if (p_semaphore_open->h_semaphore == NULL) {
284                         /* If the semaphore object creation failed, */
285                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "_CWORD64_api.dll:%s:LINE %d\r\n CreateMutex ERROR " \
286                             "In _pb_CreateSemaphore\r\n", LTEXT(__FILE__), __LINE__);
287                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Mutex_Name : %s\r\n", name);
288                         _pb_Exit();                                /* Make reset */
289                     }
290
291                     /* Create a Mutex name for locking the control information storage TBL from the position (index of array) of the control information storage TBL */
292                     /* "_CWORD64__SEMAPHORE_MUTEXxxxxx" : xxxxx is expanded with five-digit array index */
293                     MakeMutexName(name, index);
294                     /* Create a Mutex for locking the control information storage TBL and store its handle into the control information storage TBL */
295                     p_semaphore_open->h_mutex = _pb_CreateMutex(NULL, FALSE, name);
296                     if (p_semaphore_open->h_mutex == NULL) {
297                         /* If the creation of a Mutex for locking the control data storage TBL fails, */
298                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "_CWORD64_api.dll:%s:LINE %d\r\n CreateMutex ERROR " \
299                             "In _pb_CreateSemaphore\r\n", LTEXT(__FILE__), __LINE__);
300                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Mutex_Name : %s\r\n", name);
301                         _pb_Exit();
302                     }
303                     /* Semaphore Lock for updating semaphore information control TBL */
304                     PbMutexLock(p_semaphore_open->h_mutex, INFINITE);
305                     p_semaphore_open->p_sys_semaphore->ref_counter = 1;
306                     /* Semaphore UnLock upon completion of updating semaphore-information-management-TBL */
307                     PbMutexUnlock(p_semaphore_open->h_mutex);
308                     /* Semaphore UnLock upon completion of updating semaphore-information-management-TBL */
309                     PbMutexUnlock(p_inst->h_mutex);
310
311                     ret_sem_id = static_cast<SemID>(index + 1);    /* Convert from an index of array to a semaphore ID and return */
312                     /* (A semaphore was created by another process or the created process was terminated.) */
313                     // LCOV_EXCL_STOP
314                 }
315             } else {
316                 /* If the semaphore name specified by the user does not exist, it is newly created in the following processing. */
317                 /* Free-space retrieval processing for the name storage table  */
318                 index = AllocNewSemaphoreTable(p_inst->p_semaphore_table, p_semaphore_name, p_inst->h_mutex);
319                 if (index == ((DWORD) - 1)) {  // LCOV_EXCL_BR_LINE 200: table buffer is enough, can not failed
320                     /* If there is no free space in the name storage table */
321                     /* Initialize the name storage TBL pointer of the control information storage TBL. (it may be No meaning due to release heap area in the following processing?) */
322                     // LCOV_EXCL_START 200: table buffer is enough, can not failed
323                     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
324                     p_semaphore_open->p_sys_semaphore = NULL;
325                     /* Free the Heap area allocated for control information storage TBL */
326                     PbProcessHeapFree(0, p_semaphore_open);
327                     /* Semaphore UnLock to recover from errors */
328                     PbMutexUnlock(p_inst->h_mutex);
329                     // LCOV_EXCL_STOP
330                 } else {
331                      /* Store the assigned semaphore ID in the control information storage table. */
332                     p_semaphore_open->index = index;
333                     /* Store this start address of the name storage table */
334                     p_semaphore_open->p_sys_semaphore = &p_inst->p_semaphore_table[index];
335                     p_semaphore_open->p_sys_semaphore->ref_counter = 1;            /* Reset reference counter. */
336                      /* Store the control information TBL (Heap) address in the semaphore information management TBL. */
337                     p_inst->p_handle_table[index] = p_semaphore_open;
338
339                     /* Create the object name of the semaphore from the position (array index) of the control information storage TBL. */
340                     /* "_CWORD64__SEMAPHORE_SEMAPHORExxxxx" : xxxxx is expanded with five-digit array index */
341                     MakeSemaphoreName(name, index);
342                     p_semaphore_open->h_semaphore = _pb_CreateMutex(NULL, FALSE, name);  // LCOV_EXCL_BR_LINE 200: cannot be null  // NOLINT(whitespace/line_length)
343                     if (p_semaphore_open->h_semaphore == NULL) {  // LCOV_EXCL_BR_LINE 200: cannot be null
344                         // LCOV_EXCL_START 200: can not be null
345                         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
346                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "_CWORD64_api.dll:%s:LINE %d\r\n CreateMutex ERROR " \
347                             "In _pb_CreateSemaphore\r\n", LTEXT(__FILE__), __LINE__);
348                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Mutex_Name : %s\r\n", name);
349                         _pb_Exit();
350                         // LCOV_EXCL_STOP
351                     }
352
353                     MakeMutexName(name, index);
354                     p_semaphore_open->h_mutex = _pb_CreateMutex(NULL, FALSE, name);  // LCOV_EXCL_BR_LINE 200: cannot be null  // NOLINT(whitespace/line_length)
355                     if (p_semaphore_open->h_mutex == NULL) {  // LCOV_EXCL_BR_LINE 200: cannot be null
356                         // LCOV_EXCL_START 200: can not be null
357                         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
358                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "_CWORD64_api.dll:%s:LINE %d\r\n CreateMutex ERROR " \
359                             "In _pb_CreateSemaphore\r\n", LTEXT(__FILE__), __LINE__);
360                         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Mutex_Name : %s\r\n", name);
361                         _pb_Exit();
362                         // LCOV_EXCL_STOP
363                     }
364                     /* Semaphore name registration */
365                     _tcscpy(p_semaphore_open->p_sys_semaphore->semaphore_name, p_semaphore_name);
366
367                     PbMutexUnlock(p_inst->h_mutex);  /* Mutex lock to new create semaphore ends here */  // LCOV_EXCL_BR_LINE 200: no branch  // NOLINT(whitespace/line_length)
368
369                     ret_sem_id = static_cast<SemID>(index + 1);    /* Convert from an array index to a semaphore ID and return */
370                 }
371             }
372         }
373     }
374
375     return ret_sem_id;        /* Return the allocated semaphore ID. */
376 }
377
378 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
379  * MODULE    : PbDeleteSemaphore
380  * ABSTRACT  : Semaphore deletion processing
381  * NOTE      : Delete the semaphore specified by semaphore ID
382  * ARGUMENT  : SemID        sem_id            Semaphore ID to be deleted
383  * RETURN    : RET_API        RET_NORMAL        Normal completion
384  *           :                RET_OSERROR        ABEND
385  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
386 RET_API
387 PbDeleteSemaphore(SemID sem_id) {  // LCOV_EXCL_START 8:dead code
388     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
389     RET_API                    ret_api = RET_NORMAL;
390     int                     index = 0;
391     PB_SEMAPHORE_INSTANCE    *p_inst = &g_instance;
392     PB_SEMAPHORE_OPEN_HANDLE  *p_semaphore_open = NULL;
393     DWORD                     dw_ret_sts = 0;
394     DWORD                     ref_counter = 0;
395
396     /* Parameter check */
397     if (sem_id == 0) {
398         /* Error if specified semaphore ID is zero */
399         ret_api = RET_OSERROR;
400     }
401
402     if (ret_api == RET_NORMAL) {
403         index = static_cast<int>(sem_id) - 1;  /* Calculate the index number of the semaphore table from the specified semaphore ID. */
404         if (index >= MAX_PB_SEMAPHORES) {
405             /* If the specified semaphore ID is out of range */
406             ret_api = RET_OSERROR;
407         }
408     }
409
410     if (ret_api == RET_NORMAL) {
411         PbMutexLock(p_inst->h_mutex, INFINITE);    /* Need this exclusion? Seems to not be used exclusion at Locking/Unlocking... */
412         p_semaphore_open = p_inst->p_handle_table[index];
413         PbMutexUnlock(p_inst->h_mutex);        /* Need this exclusion? Seems to not be used exclusion at Locking/Unlocking... */
414         if (p_semaphore_open == NULL)              /* If the specified semaphore ID is not registered in the table */ {
415             ret_api = RET_OSERROR;
416         }
417     }
418
419     if (ret_api == RET_NORMAL) {
420         /* Return an error if the semaphore is locked */
421         dw_ret_sts = PbMutexLock(p_semaphore_open->h_semaphore, 0);
422         if (dw_ret_sts == WAIT_TIMEOUT) {
423             ret_api = RET_OSERROR;
424         }
425     }
426
427     if (ret_api == RET_NORMAL) {
428         PbMutexUnlock(p_semaphore_open->h_semaphore);
429
430         PbMutexLock(p_semaphore_open->h_mutex, INFINITE);
431         if (p_semaphore_open->p_sys_semaphore->ref_counter > 0) {
432             p_semaphore_open->p_sys_semaphore->ref_counter--;
433         }
434
435         ref_counter = p_semaphore_open->p_sys_semaphore->ref_counter;
436         PbMutexUnlock(p_semaphore_open->h_mutex);
437
438         if (ref_counter == 0) {
439             PbMutexLock(p_inst->h_mutex, INFINITE);    /* Get Mutex */
440
441             FreeSemaphoreTable(p_inst->p_semaphore_table, index, p_inst->h_mutex);
442             p_semaphore_open->p_sys_semaphore = NULL;
443             if (p_semaphore_open->h_semaphore != NULL) {
444                 PbDeleteMutex(p_semaphore_open->h_semaphore);
445                 p_semaphore_open->h_semaphore = NULL;
446             }
447
448             if (p_semaphore_open->h_mutex != NULL) {
449                 PbDeleteMutex(p_semaphore_open->h_mutex);
450                 p_semaphore_open->h_mutex = NULL;
451             }
452
453             PbProcessHeapFree(0, p_semaphore_open);
454
455             p_inst->p_handle_table[index] = NULL;
456             PbMutexUnlock(p_inst->h_mutex);            /* Release Mutex */
457         }
458     }
459
460     return ret_api;
461 }
462 // LCOV_EXCL_STOP
463
464 /**
465  * @brief
466  *   Semaphore Lock
467  *
468  *   Get the semaphore with the specified semaphore ID. Do not return from this function until it is acquired.
469  *
470  * @param[in]    sem_id    Semaphore ID of the semaphore to be acquired
471  *
472  * @return RET_NORMAL    Normal completion<br>
473  *              RET_OSERROR    ABEND
474  */
475 RET_API _pb_SemLock(SemID sem_id) {    // NOLINT(readability/nolint) WPF_SYSAPI.h API
476     RET_API                     ret_api = RET_OSERROR;
477     PB_SEMAPHORE_INSTANCE       *p_inst = &g_instance;
478     PB_SEMAPHORE_OPEN_HANDLE    *p_semaphore_open = NULL;
479     int                         index = 0;
480     DWORD                       result = 0;
481
482     /* Parameter check */
483     if (sem_id != 0) {
484         /* The specified semaphore ID is non-zero */
485         index = static_cast<int>(sem_id) - 1;    /* Calculate the index number of the semaphore table from the specified semaphore ID. */
486         if (index >= MAX_PB_SEMAPHORES) {
487             /* If the specified semaphore ID is out of range */
488         } else {
489             p_semaphore_open = p_inst->p_handle_table[index];
490             if (p_semaphore_open != NULL) {
491                 /* If the specified semaphore ID is already registered in the table, */
492                 ret_api = RET_NORMAL;
493             }
494         }
495     }
496
497     if (ret_api == RET_NORMAL) {
498         /* Wait forever until a semaphore is acquired */
499         result = PbMutexLock(p_semaphore_open->h_semaphore, INFINITE);
500
501         switch (result) {
502             case WAIT_OBJECT_0: {
503                 ret_api = RET_NORMAL;
504                 break;
505             }
506             case WAIT_ABANDONED: {  // LCOV_EXCL_BR_LINE 200: function do not return this
507                 AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
508                 ret_api = RET_OSERROR;  // LCOV_EXCL_LINE 200: function do not return this
509                 break;  // LCOV_EXCL_LINE 200: function do not return this
510             }
511             case WAIT_TIMEOUT: {  // LCOV_EXCL_BR_LINE 200: parameter INFINITE not return this
512                 AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
513                 ret_api = RET_OSERROR;  // LCOV_EXCL_LINE 200: parameter INFINITE not return this
514                 break;  // LCOV_EXCL_LINE 200: parameter INFINITE not return this
515             }
516             default:
517                 ret_api = RET_OSERROR;
518                 break;
519         }
520     }
521
522     return ret_api;
523 }
524
525 /**
526  * @brief
527  *   Semaphore Unlock
528  *
529  *   Release the semaphore specified by semaphore ID.
530  *
531  * @param[in]    sem_id    Semaphore ID of the semaphore to be released
532  *
533  * @return RET_NORMAL    Normal completion<br>
534  *              RET_OSERROR    ABEND
535  */
536 RET_API _pb_SemUnlock(SemID sem_id) {    // NOLINT(readability/nolint) WPF_SYSAPI.h API
537     RET_API                        ret_api = RET_OSERROR;
538     int                            index = 0;
539     PB_SEMAPHORE_INSTANCE        *p_inst = &g_instance;
540     PB_SEMAPHORE_OPEN_HANDLE    *p_semaphore_open = NULL;
541     BOOL                        ok = FALSE;
542
543     /* Parameter check */
544     if (sem_id != 0) {
545         /* The specified semaphore ID is non-zero */
546         index = static_cast<int>(sem_id) - 1;    /* Calculate the index number of the semaphore table from the specified semaphore ID. */
547         if (index >= MAX_PB_SEMAPHORES) {
548             /* If the specified semaphore ID is out of range */
549         } else {
550             p_semaphore_open = p_inst->p_handle_table[index];
551             if (p_semaphore_open != NULL) {
552                 /* If the specified semaphore ID is already registered in the table, */
553                 ret_api = RET_NORMAL;
554             }
555         }
556     }
557
558     if (ret_api == RET_NORMAL) {
559         ok = PbMutexUnlock(p_semaphore_open->h_semaphore);  // LCOV_EXCL_BR_LINE 200: unlock can not failed
560         if (ok == FALSE) {  // LCOV_EXCL_BR_LINE 200: unlock can not failed
561             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
562             ret_api = RET_OSERROR;  // LCOV_EXCL_LINE 200: unlock can not failed
563         }
564     }
565
566     return ret_api;
567 }
568
569 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
570  * MODULE    : InitSemaphoreInProcess
571  * ABSTRACT  : Semaphore initialization processing
572  * NOTE      : Initialize to use semaphore that is valid only within a process
573  * ARGUMENT  : None
574  * RETURN    : RET_API        RET_NORMAL        Normal completion
575  *           :                RET_OSERROR        ABEND
576  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
577 RET_API
578 InitSemaphoreInProcess(void) {  // LCOV_EXCL_START 8:dead code
579     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
580     RET_API     ret_api = RET_NORMAL;
581     DWORD       pid;                       /* Process ID */
582     TCHAR       wcs_share_data_name[32];       /* Name of shared data area for in-process semaphore management table */
583     char        mbs_share_data_name[32];       /* Name of shared data area for in-process semaphore management table */
584     char        *cp_addr = NULL;               /* For returning the start address of the shared data area */
585     u_int32     dummy_size;                   /* For returning the size of shared data area */
586
587     pid = getpid();                                /* Get process ID */
588
589     memset(&wcs_share_data_name[0], 0, sizeof(wcs_share_data_name));
590     memset(&mbs_share_data_name[0], 0, sizeof(mbs_share_data_name));
591 #ifdef UNDER_CE
592     /* Create the name of shared data area for in-process semaphore management table */
593     wsprintf(&wcs_share_data_name[0], __TEXT("SemInProc_%08x"), pid);
594     wcstombs(&mbs_share_data_name[0], &wcs_share_data_name[0], sizeof(mbs_share_data_name));
595 #else
596     /* Create the name of shared data area for in-process semaphore management table */
597     wsprintf(&mbs_share_data_name[0], __TEXT("SemInProc_%08x"), static_cast<int32>(pid));
598 #endif
599
600     /* Link to shared data area for semaphore management table in process */
601     ret_api = _pb_LinkShareData(&mbs_share_data_name[0], reinterpret_cast<void**>(&cp_addr), &dummy_size);
602     if (ret_api == RET_NORMAL) {
603         /* Successful completion because _pb_InitSemaphoreInProcess has already been executed. */
604     } else {
605         /* Create shared data area for in-process semaphore management table */
606         ret_api = _pb_CreateShareData(&mbs_share_data_name[0],
607             static_cast<u_int32>(sizeof(PB_SEM_INPROC) * MAX_PB_SEMAPHORES_INPROC), \
608             reinterpret_cast<void**>(&cp_addr));
609         if (ret_api == RET_NORMAL) {
610             /* Save top address of in-process semaphore management table */
611             g_p_sem_in_proc_mng = reinterpret_cast<PB_SEM_INPROC *>(cp_addr);
612
613             /* Initialization processing of the critical section object for in-process semaphore management table lock */
614             PbInitializeCriticalSection(&g_sem_in_proc_tbl_mng_cs);
615         } else {
616             FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " _CWORD64_api.dll:%s:LINE %d\r\n ## " \
617                 "ERROR:InitSemaphoreInProcess --> _pb_CreateShareData ##\r\n", LTEXT(__FILE__), __LINE__);
618             ret_api = RET_OSERROR;
619         }
620     }
621
622     return ret_api;
623 }
624 // LCOV_EXCL_STOP
625
626 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
627  * MODULE    : DeinitSemaphoreInProcess
628  * ABSTRACT  : Semaphore function termination processing
629  * NOTE      : Terminate semaphore function that is valid only within a process
630  * ARGUMENT  : None
631  * RETURN    : RET_API        RET_NORMAL        Normal completion
632  *           :                RET_OSERROR        ABEND
633  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
634 RET_API
635 DeinitSemaphoreInProcess(void) {  // LCOV_EXCL_START 8:dead code
636     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
637     RET_API        ret_api = RET_NORMAL;
638     PB_SEM_INPROC  *p_sem_in_proc;                /* Pointer to the in-process semaphore management table */
639     DWORD          pid;                        /* Process ID */
640     TCHAR          wcs_share_data_name[32];        /* Name of shared data area for in-process semaphore management table */
641     char           mbs_share_data_name[32];        /* Name of shared data area for in-process semaphore management table */
642     char           *cp_addr = NULL;                /* For returning the start address of the shared data area */
643     u_int32        dummy_size;                    /* For returning the size of the shared data area */
644     int            i;
645
646     pid = getpid();                    /* Get process ID */
647
648     memset(&wcs_share_data_name[0], 0, sizeof(wcs_share_data_name));
649     memset(&mbs_share_data_name[0], 0, sizeof(mbs_share_data_name));
650 #ifdef UNDER_CE
651     /* Create the name of shared data area for in-process semaphore management table */
652     wsprintf(&wcs_share_data_name[0], __TEXT("SemInProc_%08x"), pid);
653     wcstombs(&mbs_share_data_name[0], &wcs_share_data_name[0], sizeof(mbs_share_data_name));
654 #else/* Create the name of shared data area for in-process semaphore management table */
655     wsprintf(&mbs_share_data_name[0], __TEXT("SemInProc_%08x"), static_cast<int32>(pid));
656 #endif
657
658     /* Link to shared data area for in-process semaphore management table */
659     ret_api = _pb_LinkShareData(&mbs_share_data_name[0], reinterpret_cast<void**>(&cp_addr), &dummy_size);
660     if (ret_api != RET_NORMAL) {
661         ret_api = RET_NORMAL;                            /* If the link fails, it is assumed to have been deleted and it completes normally. */
662     } else {
663         /* Get CS for exclusive control of in-process semaphore management table */
664         PbEnterCriticalSection(&g_sem_in_proc_tbl_mng_cs);
665
666         p_sem_in_proc = g_p_sem_in_proc_mng;            /* Get start address of in-process semaphore management table */
667         if (p_sem_in_proc == NULL) {
668             ret_api = RET_OSERROR;
669         } else {
670             /* Search in-process semaphore management table (delete all semaphores) */
671             for (i = 0; i < MAX_PB_SEMAPHORES_INPROC; i++, p_sem_in_proc++) {
672                 if (p_sem_in_proc->p_cs != 0) {
673                     PbDeleteCriticalSection(p_sem_in_proc->p_cs);    /* Delete critical section */
674                     /* Release the Heap area allocated as the critical section structured area */
675                     PbProcessHeapFree(0, p_sem_in_proc->p_cs);
676                 }
677             }
678
679             ret_api = PbDeleteShareData(&mbs_share_data_name[0]);        /* Delete shared data area */
680             if (ret_api != RET_NORMAL) {
681                 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " _CWORD64_api.dll:%s:LINE %d\r\n ## " \
682                     "ERROR:DeinitSemaphoreInProcess --> PbDeleteShareData ##\r\n", LTEXT(__FILE__), __LINE__);
683                 ret_api = RET_OSERROR;
684             } else {
685                 g_p_sem_in_proc_mng = NULL;
686             }
687         }
688
689         PbLeaveCriticalSection(&g_sem_in_proc_tbl_mng_cs);        /* Release CS for exclusive control of in-process semaphore management table */
690
691         if (ret_api == RET_NORMAL) {
692             /* When the process is completed normally up to this point */
693             PbDeleteCriticalSection(&g_sem_in_proc_tbl_mng_cs);        /* Delete critical section */
694         }
695     }
696
697     return ret_api;
698 }
699 // LCOV_EXCL_STOP
700
701 /*****    Internal functions    *****/
702
703 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
704  * MODULE    : FindSemaphoreTable
705  * ABSTRACT  : Name storage table retrieval processing
706  * NOTE      : Retrieve the specified name storage table with the specified name,
707  *           : and return its array index if the specified name exists in the table.
708  *           : The specified Mutex is locked during this table retrieval processing.
709  * ARGUMENT  : PB_SEMAPHORE*    p_semaphore_table        Pointer to the name storage TBL
710  *             TCHAR*            name                Pointer to the name to be retrieved 
711  *             HANDLE            h_mutex                Handle of the name storage TBL-locking Mutex
712  * RETURN    : DWORD            othe than -1            Array index of containing the name string to be retrieved
713  *           :                    -1                    Specified name does not exist
714  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
715 static DWORD
716 FindSemaphoreTable(PB_SEMAPHORE* p_semaphore_table, TCHAR* name, HANDLE h_mutex) {
717     DWORD ret = (DWORD) - 1;
718     /* Loop up to the maximum number of entries and search the name storage table. */
719     for (int n = 0; n < MAX_PB_SEMAPHORES; n++) {
720         /* If there is a matching name, */
721         if (_tcscmp(p_semaphore_table[n].semaphore_name, name) == 0) {
722             ret = n;                    /* Return the index of the array in which the given name existed */
723             break;
724         }
725     }
726     /* UnLock the lock Mutex because the search for the name storage table has been completed. */
727     /*    PbMutexUnlock(h_mutex);    */
728
729     return ret;                /* Since no search name exists, an error value of-1 is returned. */
730 }
731
732 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
733  * MODULE    : AllocNewSemaphoreTable
734  * ABSTRACT  : Name storage table free space retrieval processing
735  * NOTE      : Retrieve the specified name storage table from the beginning,
736  *           : return the array index of any free space.
737  *           : [Note] Because the Mutex part inside this function has been deleted
738  *           : to fix a bug caused by Mutex leaks, the whole function must be
739  *           : locked by Mutex from the outside when this function is used.
740  * ARGUMENT  : PB_SEMAPHORE    *p_semaphore_table
741  *             TCHAR            *name
742  *             HANDLE            h_mutex
743  * RETURN    : DWORD
744  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
745 static DWORD
746 AllocNewSemaphoreTable(PB_SEMAPHORE* p_semaphore_table, TCHAR* name, HANDLE h_mutex) {
747     DWORD ret = (DWORD) - 1;
748     /* Loop up to the maximum number of entries and search the name storage table. */
749     for (int n = 0; n < MAX_PB_SEMAPHORES; n++) {
750         /* If there is free space */
751         if (p_semaphore_table[n].semaphore_name[0] == __TEXT('\0')) {
752             ret = n;
753             break;
754         }
755     }
756
757     return ret;
758 }
759
760 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
761  * MODULE    : FreeSemaphoreTable
762  * ABSTRACT  :
763  * NOTE      :
764  * ARGUMENT  : PB_SEMAPHORE*    p_semaphore_table
765  *             int                index
766  *             HANDLE            h_mutex
767  * RETURN    : None
768  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
769 static void
770 FreeSemaphoreTable(PB_SEMAPHORE* p_semaphore_table, int index, HANDLE h_mutex) {  // LCOV_EXCL_START 8:dead code
771     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
772     p_semaphore_table[index].semaphore_name[0] = __TEXT('\0');
773 }
774 // LCOV_EXCL_STOP
775
776 /*
777 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
778  End of File : _sysSem.cpp
779 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
780 */