John Park | 398c74a | 2018-10-20 21:17:39 -0700 | [diff] [blame] | 1 | #include "aos/ipc_lib/shared_mem.h" |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 2 | |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 3 | #include <fcntl.h> |
Stephan Pleines | 682928d | 2024-05-31 20:43:48 -0700 | [diff] [blame^] | 4 | #include <stdint.h> |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame] | 5 | #include <sys/mman.h> |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame] | 6 | #include <unistd.h> |
| 7 | |
| 8 | #include <cassert> |
| 9 | #include <cerrno> |
| 10 | #include <cstdio> |
| 11 | #include <cstdlib> |
| 12 | #include <cstring> |
Stephan Pleines | 682928d | 2024-05-31 20:43:48 -0700 | [diff] [blame^] | 13 | #include <ostream> |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 14 | |
Philipp Schrader | 790cb54 | 2023-07-05 21:06:52 -0700 | [diff] [blame] | 15 | #include "glog/logging.h" |
| 16 | |
John Park | 398c74a | 2018-10-20 21:17:39 -0700 | [diff] [blame] | 17 | #include "aos/ipc_lib/aos_sync.h" |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 18 | |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 19 | // the path for the shared memory segment. see shm_open(3) for restrictions |
| 20 | #define AOS_SHM_NAME "/aos_shared_mem" |
| 21 | // Size of the shared mem segment. |
Austin Schuh | 0480bc8 | 2014-10-25 18:01:51 -0700 | [diff] [blame] | 22 | // This must fit in the tmpfs for /dev/shm/ |
Austin Schuh | 3e252e7 | 2019-12-29 16:25:58 -0800 | [diff] [blame] | 23 | #define SIZEOFSHMSEG (4096 * 0x800) |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 24 | |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 25 | void init_shared_mem_core(aos_shm_core *shm_core) { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame] | 26 | memset(&shm_core->time_offset, 0, sizeof(shm_core->time_offset)); |
Brian Silverman | dc1eb27 | 2014-08-19 14:25:59 -0400 | [diff] [blame] | 27 | memset(&shm_core->msg_alloc_lock, 0, sizeof(shm_core->msg_alloc_lock)); |
Brian Silverman | 4aeac5f | 2014-02-11 22:17:07 -0800 | [diff] [blame] | 28 | shm_core->queues.pointer = NULL; |
Brian Silverman | dc1eb27 | 2014-08-19 14:25:59 -0400 | [diff] [blame] | 29 | memset(&shm_core->queues.lock, 0, sizeof(shm_core->queues.lock)); |
Brian Silverman | 4aeac5f | 2014-02-11 22:17:07 -0800 | [diff] [blame] | 30 | shm_core->queue_types.pointer = NULL; |
Brian Silverman | dc1eb27 | 2014-08-19 14:25:59 -0400 | [diff] [blame] | 31 | memset(&shm_core->queue_types.lock, 0, sizeof(shm_core->queue_types.lock)); |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 32 | } |
| 33 | |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 34 | ptrdiff_t aos_core_get_mem_usage(void) { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame] | 35 | return global_core->size - ((ptrdiff_t)global_core->mem_struct->msg_alloc - |
| 36 | (ptrdiff_t)global_core->mem_struct); |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 37 | } |
| 38 | |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 39 | struct aos_core *global_core = NULL; |
| 40 | |
Brian Silverman | 67e34f5 | 2014-03-13 15:52:57 -0700 | [diff] [blame] | 41 | // TODO(brians): madvise(2) it to put this shm in core dumps. |
Brian Silverman | 8a6dac9 | 2015-02-21 20:08:24 -0500 | [diff] [blame] | 42 | void aos_core_create_shared_mem(int create, int lock) { |
Brian Silverman | 6da0427 | 2014-05-18 18:47:48 -0700 | [diff] [blame] | 43 | assert(global_core == NULL); |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 44 | static struct aos_core global_core_data; |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 45 | global_core = &global_core_data; |
Brian Silverman | bf2f946 | 2014-02-25 13:33:52 -0800 | [diff] [blame] | 46 | |
| 47 | { |
| 48 | char *shm_name = getenv("AOS_SHM_NAME"); |
| 49 | if (shm_name == NULL) { |
| 50 | global_core->shm_name = AOS_SHM_NAME; |
| 51 | } else { |
Austin Schuh | 293d37c | 2015-03-08 18:47:45 -0700 | [diff] [blame] | 52 | printf("AOS_SHM_NAME defined, using %s\n", shm_name); |
Brian Silverman | bf2f946 | 2014-02-25 13:33:52 -0800 | [diff] [blame] | 53 | global_core->shm_name = shm_name; |
| 54 | } |
| 55 | } |
| 56 | |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 57 | int shm; |
Brian Silverman | 8a6dac9 | 2015-02-21 20:08:24 -0500 | [diff] [blame] | 58 | if (create) { |
Brian | 4861015 | 2014-04-02 12:28:19 -0700 | [diff] [blame] | 59 | while (1) { |
Brian | 4861015 | 2014-04-02 12:28:19 -0700 | [diff] [blame] | 60 | shm = shm_open(global_core->shm_name, O_RDWR | O_CREAT | O_EXCL, 0666); |
| 61 | global_core->owner = 1; |
| 62 | if (shm == -1 && errno == EEXIST) { |
| 63 | printf("shared_mem: going to shm_unlink(%s)\n", global_core->shm_name); |
| 64 | if (shm_unlink(global_core->shm_name) == -1) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 65 | PLOG(WARNING) << "shm_unlink(" << global_core->shm_name << ") failed"; |
Brian | 4861015 | 2014-04-02 12:28:19 -0700 | [diff] [blame] | 66 | break; |
| 67 | } |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 68 | } else { |
Brian | 4861015 | 2014-04-02 12:28:19 -0700 | [diff] [blame] | 69 | break; |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 70 | } |
| 71 | } |
| 72 | } else { |
Brian Silverman | bf2f946 | 2014-02-25 13:33:52 -0800 | [diff] [blame] | 73 | shm = shm_open(global_core->shm_name, O_RDWR, 0); |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 74 | global_core->owner = 0; |
| 75 | } |
| 76 | if (shm == -1) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 77 | PLOG(FATAL) << "shm_open(" << global_core->shm_name |
| 78 | << ", O_RDWR [| O_CREAT | O_EXCL, 0|0666) failed"; |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 79 | } |
| 80 | if (global_core->owner) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 81 | PCHECK(ftruncate(shm, SIZEOFSHMSEG) == 0) |
| 82 | << ": fruncate(" << shm << ", 0x" << std::hex << (size_t)SIZEOFSHMSEG |
| 83 | << ") failed"; |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 84 | } |
Brian Silverman | 8a6dac9 | 2015-02-21 20:08:24 -0500 | [diff] [blame] | 85 | int flags = MAP_SHARED | MAP_FIXED; |
| 86 | if (lock) flags |= MAP_LOCKED | MAP_POPULATE; |
| 87 | void *shm_address = mmap((void *)SHM_START, SIZEOFSHMSEG, |
| 88 | PROT_READ | PROT_WRITE, flags, shm, 0); |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 89 | PCHECK(shm_address != MAP_FAILED) |
| 90 | << std::hex << "shared_mem: mmap(" << (void *)SHM_START << ", 0x" |
| 91 | << (size_t)SIZEOFSHMSEG << ", stuff, " << flags << ", " << shm |
| 92 | << ", 0) failed"; |
Austin Schuh | 293d37c | 2015-03-08 18:47:45 -0700 | [diff] [blame] | 93 | if (create) { |
| 94 | printf("shared_mem: creating %s, shm at: %p\n", global_core->shm_name, |
| 95 | shm_address); |
| 96 | } else { |
| 97 | printf("shared_mem: not creating, shm at: %p\n", shm_address); |
| 98 | } |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 99 | if (close(shm) == -1) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 100 | PLOG(WARNING) << "close(" << shm << "(=shm) failed"; |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 101 | } |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 102 | PCHECK(shm_address == (void *)SHM_START) |
| 103 | << "shm isn't at hard-coded " << (void *)SHM_START << ". at " |
| 104 | << shm_address << " instead"; |
Brian Silverman | 01be000 | 2014-05-10 15:44:38 -0700 | [diff] [blame] | 105 | aos_core_use_address_as_shared_mem(shm_address, SIZEOFSHMSEG); |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 106 | LOG(INFO) << "shared_mem: end of create_shared_mem owner=" |
| 107 | << global_core->owner; |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 108 | } |
| 109 | |
Brian Silverman | 01be000 | 2014-05-10 15:44:38 -0700 | [diff] [blame] | 110 | void aos_core_use_address_as_shared_mem(void *address, size_t size) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 111 | global_core->mem_struct = reinterpret_cast<aos_shm_core_t *>(address); |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 112 | global_core->size = size; |
Brian Silverman | bf2f946 | 2014-02-25 13:33:52 -0800 | [diff] [blame] | 113 | global_core->shared_mem = |
| 114 | (uint8_t *)address + sizeof(*global_core->mem_struct); |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 115 | if (global_core->owner) { |
| 116 | global_core->mem_struct->msg_alloc = (uint8_t *)address + global_core->size; |
| 117 | init_shared_mem_core(global_core->mem_struct); |
Brian Silverman | af221b8 | 2013-09-01 13:57:50 -0700 | [diff] [blame] | 118 | futex_set(&global_core->mem_struct->creation_condition); |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 119 | } else { |
Brian Silverman | af221b8 | 2013-09-01 13:57:50 -0700 | [diff] [blame] | 120 | if (futex_wait(&global_core->mem_struct->creation_condition) != 0) { |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 121 | LOG(FATAL) << "waiting on creation_condition failed"; |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 122 | } |
| 123 | } |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 124 | } |
| 125 | |
Brian Silverman | 01be000 | 2014-05-10 15:44:38 -0700 | [diff] [blame] | 126 | void aos_core_free_shared_mem() { |
Austin Schuh | 32fd5a7 | 2019-12-01 22:20:26 -0800 | [diff] [blame] | 127 | if (global_core != nullptr) { |
| 128 | void *shm_address = global_core->shared_mem; |
| 129 | PCHECK(munmap((void *)SHM_START, SIZEOFSHMSEG) != -1) |
| 130 | << ": munmap(" << shm_address << ", 0x" << std::hex |
| 131 | << (size_t)SIZEOFSHMSEG << ") failed"; |
| 132 | if (global_core->owner) { |
| 133 | PCHECK(shm_unlink(global_core->shm_name) == 0) |
| 134 | << ": shared_mem: shm_unlink(" << global_core->shm_name << ") failed"; |
| 135 | } |
| 136 | global_core = nullptr; |
Brian Silverman | 01be000 | 2014-05-10 15:44:38 -0700 | [diff] [blame] | 137 | } |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 138 | } |
Brian Silverman | b263d30 | 2014-02-16 00:01:43 -0800 | [diff] [blame] | 139 | |
Austin Schuh | 32fd5a7 | 2019-12-01 22:20:26 -0800 | [diff] [blame] | 140 | int aos_core_is_init(void) { return global_core != NULL; } |