|
| 1 | +/** |
| 2 | + * SPDX-FileCopyrightText: 2019-2024 Infineon Technologies AG |
| 3 | + * SPDX-License-Identifier: MIT |
| 4 | + * |
| 5 | + * \author Infineon Technologies AG |
| 6 | + * |
| 7 | + * \file pal_shared_mutex.c |
| 8 | + * |
| 9 | + * \brief This file implements the platform abstraction layer APIs for shared |
| 10 | + * memory mutex. |
| 11 | + * |
| 12 | + * \ingroup grPAL |
| 13 | + * @{ |
| 14 | + */ |
| 15 | + |
| 16 | +#include "include/pal_shared_mutex.h" |
| 17 | + |
| 18 | +#include <errno.h> // errno, ENOENT |
| 19 | +#include <fcntl.h> // O_RDWR, O_CREATE |
| 20 | +#include <linux/limits.h> // NAME_MAX |
| 21 | +#include <sys/mman.h> // shm_open, shm_unlink, mmap, munmap, |
| 22 | +// PROT_READ, PROT_WRITE, MAP_SHARED, MAP_FAILED |
| 23 | +#include <stdio.h> // perror |
| 24 | +#include <stdlib.h> // malloc, free |
| 25 | +#include <string.h> // strcpy |
| 26 | +#include <unistd.h> // ftruncate, close |
| 27 | + |
| 28 | +pthread_mutex_t shm_lock; |
| 29 | + |
| 30 | +static shared_mutex_t shared_mutex_init(const char *name) { |
| 31 | + shared_mutex_t mutex = {NULL, 0, NULL, 0, NULL}; |
| 32 | + trustm_mutex_t *addr; |
| 33 | + trustm_mutex_t *mutex_ptr; |
| 34 | + |
| 35 | + // Open existing shared memory object, or create one. |
| 36 | + // Two separate calls are needed here, to mark fact of creation |
| 37 | + // for later initialization of pthread mutex. |
| 38 | + TRUSTM_MUTEX_DBGFN2(">"); |
| 39 | + TRUSTM_MUTEX_DBGFN2("pthread lock"); |
| 40 | + pthread_mutex_lock(&shm_lock); |
| 41 | + TRUSTM_MUTEX_DBGFN2("pthread lock successfully"); |
| 42 | + mutex.shm_fd = shm_open(name, O_RDWR, 0660); |
| 43 | + if (mutex.shm_fd == -1 && errno == ENOENT) { |
| 44 | + mutex.shm_fd = shm_open(name, O_RDWR | O_CREAT, 0660); |
| 45 | + mutex.created = 1; |
| 46 | + TRUSTM_MUTEX_DBGFN2("create new shm"); |
| 47 | + } |
| 48 | + TRUSTM_MUTEX_DBGFN2("pthread unlock"); |
| 49 | + pthread_mutex_unlock(&shm_lock); |
| 50 | + TRUSTM_MUTEX_DBGFN2("pthread unlock successfully"); |
| 51 | + if (mutex.shm_fd == -1) { |
| 52 | + perror("shm_open"); |
| 53 | + return mutex; |
| 54 | + } |
| 55 | + TRUSTM_MUTEX_DBGFN2("truncate shm "); |
| 56 | + // Truncate shared memory segment so it would contain |
| 57 | + // trustm_mutex_t. |
| 58 | + if (ftruncate(mutex.shm_fd, sizeof(trustm_mutex_t)) != 0) { |
| 59 | + perror("ftruncate"); |
| 60 | + return mutex; |
| 61 | + } |
| 62 | + |
| 63 | + // Map pthread mutex into the shared memory. |
| 64 | + addr = mmap(NULL, sizeof(trustm_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, mutex.shm_fd, 0); |
| 65 | + |
| 66 | + if (addr == MAP_FAILED) { |
| 67 | + perror("mmap"); |
| 68 | + return mutex; |
| 69 | + } |
| 70 | + mutex_ptr = addr; |
| 71 | + |
| 72 | + // If shared memory was just initialized - |
| 73 | + // initialize the mutex as well. |
| 74 | + |
| 75 | + if (mutex.created) { |
| 76 | + pthread_mutexattr_t attr; |
| 77 | + if (pthread_mutexattr_init(&attr)) { |
| 78 | + perror("pthread_mutexattr_init"); |
| 79 | + return mutex; |
| 80 | + } |
| 81 | + if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { |
| 82 | + perror("pthread_mutexattr_setpshared"); |
| 83 | + return mutex; |
| 84 | + } |
| 85 | + |
| 86 | + if (pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)) { |
| 87 | + perror("pthread_mutexattr_setrobust"); |
| 88 | + return mutex; |
| 89 | + } |
| 90 | + |
| 91 | + if (pthread_mutex_init(&mutex_ptr->mutex, &attr)) { |
| 92 | + perror("pthread_mutex_init"); |
| 93 | + return mutex; |
| 94 | + } |
| 95 | + } |
| 96 | + TRUSTM_MUTEX_DBGFN2("-----> mutes ptr:%x", &mutex_ptr->mutex); |
| 97 | +#ifdef DEBUG_TRUSTM_MUTEX |
| 98 | + for (int i = 0; i < sizeof(pthread_mutex_t); i++) { |
| 99 | + printf("%x", ((char *)&mutex_ptr->mutex)[i]); |
| 100 | + } |
| 101 | + printf("\n"); |
| 102 | +#endif |
| 103 | + mutex.ptr = &mutex_ptr->mutex; |
| 104 | + mutex.pid = &mutex_ptr->pid; |
| 105 | + mutex.name = (char *)malloc(NAME_MAX + 1); |
| 106 | + strcpy(mutex.name, name); |
| 107 | + TRUSTM_MUTEX_DBGFN2("<"); |
| 108 | + return mutex; |
| 109 | +} |
| 110 | + |
| 111 | +static int shared_mutex_close(shared_mutex_t mutex) { |
| 112 | + if (munmap((void *)mutex.ptr, sizeof(pthread_mutex_t))) { |
| 113 | + perror("munmap"); |
| 114 | + return -1; |
| 115 | + } |
| 116 | + mutex.ptr = NULL; |
| 117 | + if (close(mutex.shm_fd)) { |
| 118 | + perror("close"); |
| 119 | + return -1; |
| 120 | + } |
| 121 | + mutex.shm_fd = 0; |
| 122 | + free(mutex.name); |
| 123 | + return 0; |
| 124 | +} |
| 125 | + |
| 126 | +static int shared_mutex_destroy(shared_mutex_t mutex) { |
| 127 | + if ((errno = pthread_mutex_destroy(mutex.ptr))) { |
| 128 | + perror("pthread_mutex_destroy"); |
| 129 | + return -1; |
| 130 | + } |
| 131 | + if (munmap((void *)mutex.ptr, sizeof(pthread_mutex_t))) { |
| 132 | + perror("munmap"); |
| 133 | + return -1; |
| 134 | + } |
| 135 | + mutex.ptr = NULL; |
| 136 | + if (close(mutex.shm_fd)) { |
| 137 | + perror("close"); |
| 138 | + return -1; |
| 139 | + } |
| 140 | + mutex.shm_fd = 0; |
| 141 | + if (shm_unlink(mutex.name)) { |
| 142 | + perror("shm_unlink"); |
| 143 | + return -1; |
| 144 | + } |
| 145 | + free(mutex.name); |
| 146 | + return 0; |
| 147 | +} |
| 148 | + |
| 149 | +pal_status_t pal_shm_mutex_acquire(shared_mutex_t *shm_mutex, const char *mutex_name) { |
| 150 | + int result; |
| 151 | + TRUSTM_MUTEX_DBGFN1(">"); |
| 152 | + |
| 153 | + *shm_mutex = shared_mutex_init(mutex_name); |
| 154 | + if (shm_mutex->ptr == NULL) { |
| 155 | + TRUSTM_MUTEX_DBGFN1("Mutex create failed\n"); |
| 156 | + return PAL_STATUS_FAILURE; |
| 157 | + } |
| 158 | + |
| 159 | + result = pthread_mutex_lock(shm_mutex->ptr); |
| 160 | + TRUSTM_MUTEX_DBGFN1("Lock Mutex:%s: %x\n", mutex_name, (unsigned int)shm_mutex->ptr); |
| 161 | + if (result == EOWNERDEAD) { |
| 162 | + TRUSTM_MUTEX_DBGFN1("process owner dead, make it consistent\n"); |
| 163 | + result = pthread_mutex_consistent(shm_mutex->ptr); |
| 164 | + if (result != 0) { |
| 165 | + perror("pthread_mutex_consistent error"); |
| 166 | + return PAL_STATUS_FAILURE; |
| 167 | + } |
| 168 | + } |
| 169 | + if (shm_mutex->created) { |
| 170 | + TRUSTM_MUTEX_DBGFN1("The mutex was just created %x\n", *shm_mutex->pid); |
| 171 | + *shm_mutex->pid = EMPTY_PID; |
| 172 | + } |
| 173 | + TRUSTM_MUTEX_DBGFN1("<"); |
| 174 | + return PAL_STATUS_SUCCESS; |
| 175 | +} |
| 176 | + |
| 177 | +/********************************************************************** |
| 178 | + * pal_shm_mutex_release(shared_mutex_t *shm_mutex) |
| 179 | + **********************************************************************/ |
| 180 | +void pal_shm_mutex_release(shared_mutex_t *shm_mutex) { |
| 181 | + TRUSTM_MUTEX_DBGFN1(">"); |
| 182 | + pthread_mutex_unlock(shm_mutex->ptr); |
| 183 | + TRUSTM_MUTEX_DBGFN1("mutex unlock:%s:%x", shm_mutex->name, (unsigned int)shm_mutex->ptr); |
| 184 | + |
| 185 | + shared_mutex_close(*shm_mutex); |
| 186 | + TRUSTM_MUTEX_DBGFN1("mutex closed"); |
| 187 | + |
| 188 | + TRUSTM_MUTEX_DBGFN1("<"); |
| 189 | +} |
0 commit comments