blob: 861f02ee970372be992a50bfbd91aa9a0414c431 [file] [log] [blame]
John Park398c74a2018-10-20 21:17:39 -07001#include "aos/ipc_lib/shared_mem.h"
brians343bc112013-02-10 01:53:46 +00002
brians343bc112013-02-10 01:53:46 +00003#include <fcntl.h>
Stephan Pleines682928d2024-05-31 20:43:48 -07004#include <stdint.h>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07005#include <sys/mman.h>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07006#include <unistd.h>
7
8#include <cassert>
9#include <cerrno>
10#include <cstdio>
11#include <cstdlib>
12#include <cstring>
Stephan Pleines682928d2024-05-31 20:43:48 -070013#include <ostream>
brians343bc112013-02-10 01:53:46 +000014
Austin Schuh99f7c6a2024-06-25 22:07:44 -070015#include "absl/log/check.h"
16#include "absl/log/log.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070017
John Park398c74a2018-10-20 21:17:39 -070018#include "aos/ipc_lib/aos_sync.h"
Brian Silverman08661c72013-09-01 17:24:38 -070019
brians343bc112013-02-10 01:53:46 +000020// the path for the shared memory segment. see shm_open(3) for restrictions
21#define AOS_SHM_NAME "/aos_shared_mem"
22// Size of the shared mem segment.
Austin Schuh0480bc82014-10-25 18:01:51 -070023// This must fit in the tmpfs for /dev/shm/
Austin Schuh3e252e72019-12-29 16:25:58 -080024#define SIZEOFSHMSEG (4096 * 0x800)
brians343bc112013-02-10 01:53:46 +000025
Brian Silverman08661c72013-09-01 17:24:38 -070026void init_shared_mem_core(aos_shm_core *shm_core) {
Tyler Chatowbf0609c2021-07-31 16:13:27 -070027 memset(&shm_core->time_offset, 0, sizeof(shm_core->time_offset));
Brian Silvermandc1eb272014-08-19 14:25:59 -040028 memset(&shm_core->msg_alloc_lock, 0, sizeof(shm_core->msg_alloc_lock));
Brian Silverman4aeac5f2014-02-11 22:17:07 -080029 shm_core->queues.pointer = NULL;
Brian Silvermandc1eb272014-08-19 14:25:59 -040030 memset(&shm_core->queues.lock, 0, sizeof(shm_core->queues.lock));
Brian Silverman4aeac5f2014-02-11 22:17:07 -080031 shm_core->queue_types.pointer = NULL;
Brian Silvermandc1eb272014-08-19 14:25:59 -040032 memset(&shm_core->queue_types.lock, 0, sizeof(shm_core->queue_types.lock));
Brian Silverman08661c72013-09-01 17:24:38 -070033}
34
brians343bc112013-02-10 01:53:46 +000035ptrdiff_t aos_core_get_mem_usage(void) {
Tyler Chatowbf0609c2021-07-31 16:13:27 -070036 return global_core->size - ((ptrdiff_t)global_core->mem_struct->msg_alloc -
37 (ptrdiff_t)global_core->mem_struct);
brians343bc112013-02-10 01:53:46 +000038}
39
brians343bc112013-02-10 01:53:46 +000040struct aos_core *global_core = NULL;
41
Brian Silverman67e34f52014-03-13 15:52:57 -070042// TODO(brians): madvise(2) it to put this shm in core dumps.
Brian Silverman8a6dac92015-02-21 20:08:24 -050043void aos_core_create_shared_mem(int create, int lock) {
Brian Silverman6da04272014-05-18 18:47:48 -070044 assert(global_core == NULL);
Brian Silverman08661c72013-09-01 17:24:38 -070045 static struct aos_core global_core_data;
brians343bc112013-02-10 01:53:46 +000046 global_core = &global_core_data;
Brian Silvermanbf2f9462014-02-25 13:33:52 -080047
48 {
49 char *shm_name = getenv("AOS_SHM_NAME");
50 if (shm_name == NULL) {
51 global_core->shm_name = AOS_SHM_NAME;
52 } else {
Austin Schuh293d37c2015-03-08 18:47:45 -070053 printf("AOS_SHM_NAME defined, using %s\n", shm_name);
Brian Silvermanbf2f9462014-02-25 13:33:52 -080054 global_core->shm_name = shm_name;
55 }
56 }
57
brians343bc112013-02-10 01:53:46 +000058 int shm;
Brian Silverman8a6dac92015-02-21 20:08:24 -050059 if (create) {
Brian48610152014-04-02 12:28:19 -070060 while (1) {
Brian48610152014-04-02 12:28:19 -070061 shm = shm_open(global_core->shm_name, O_RDWR | O_CREAT | O_EXCL, 0666);
62 global_core->owner = 1;
63 if (shm == -1 && errno == EEXIST) {
64 printf("shared_mem: going to shm_unlink(%s)\n", global_core->shm_name);
65 if (shm_unlink(global_core->shm_name) == -1) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070066 PLOG(WARNING) << "shm_unlink(" << global_core->shm_name << ") failed";
Brian48610152014-04-02 12:28:19 -070067 break;
68 }
brians343bc112013-02-10 01:53:46 +000069 } else {
Brian48610152014-04-02 12:28:19 -070070 break;
brians343bc112013-02-10 01:53:46 +000071 }
72 }
73 } else {
Brian Silvermanbf2f9462014-02-25 13:33:52 -080074 shm = shm_open(global_core->shm_name, O_RDWR, 0);
brians343bc112013-02-10 01:53:46 +000075 global_core->owner = 0;
76 }
77 if (shm == -1) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070078 PLOG(FATAL) << "shm_open(" << global_core->shm_name
79 << ", O_RDWR [| O_CREAT | O_EXCL, 0|0666) failed";
brians343bc112013-02-10 01:53:46 +000080 }
81 if (global_core->owner) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070082 PCHECK(ftruncate(shm, SIZEOFSHMSEG) == 0)
83 << ": fruncate(" << shm << ", 0x" << std::hex << (size_t)SIZEOFSHMSEG
84 << ") failed";
brians343bc112013-02-10 01:53:46 +000085 }
Brian Silverman8a6dac92015-02-21 20:08:24 -050086 int flags = MAP_SHARED | MAP_FIXED;
87 if (lock) flags |= MAP_LOCKED | MAP_POPULATE;
88 void *shm_address = mmap((void *)SHM_START, SIZEOFSHMSEG,
89 PROT_READ | PROT_WRITE, flags, shm, 0);
Alex Perrycb7da4b2019-08-28 19:35:56 -070090 PCHECK(shm_address != MAP_FAILED)
91 << std::hex << "shared_mem: mmap(" << (void *)SHM_START << ", 0x"
92 << (size_t)SIZEOFSHMSEG << ", stuff, " << flags << ", " << shm
93 << ", 0) failed";
Austin Schuh293d37c2015-03-08 18:47:45 -070094 if (create) {
95 printf("shared_mem: creating %s, shm at: %p\n", global_core->shm_name,
96 shm_address);
97 } else {
98 printf("shared_mem: not creating, shm at: %p\n", shm_address);
99 }
brians343bc112013-02-10 01:53:46 +0000100 if (close(shm) == -1) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700101 PLOG(WARNING) << "close(" << shm << "(=shm) failed";
brians343bc112013-02-10 01:53:46 +0000102 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700103 PCHECK(shm_address == (void *)SHM_START)
104 << "shm isn't at hard-coded " << (void *)SHM_START << ". at "
105 << shm_address << " instead";
Brian Silverman01be0002014-05-10 15:44:38 -0700106 aos_core_use_address_as_shared_mem(shm_address, SIZEOFSHMSEG);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700107 LOG(INFO) << "shared_mem: end of create_shared_mem owner="
108 << global_core->owner;
brians343bc112013-02-10 01:53:46 +0000109}
110
Brian Silverman01be0002014-05-10 15:44:38 -0700111void aos_core_use_address_as_shared_mem(void *address, size_t size) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700112 global_core->mem_struct = reinterpret_cast<aos_shm_core_t *>(address);
brians343bc112013-02-10 01:53:46 +0000113 global_core->size = size;
Brian Silvermanbf2f9462014-02-25 13:33:52 -0800114 global_core->shared_mem =
115 (uint8_t *)address + sizeof(*global_core->mem_struct);
brians343bc112013-02-10 01:53:46 +0000116 if (global_core->owner) {
117 global_core->mem_struct->msg_alloc = (uint8_t *)address + global_core->size;
118 init_shared_mem_core(global_core->mem_struct);
Brian Silvermanaf221b82013-09-01 13:57:50 -0700119 futex_set(&global_core->mem_struct->creation_condition);
brians343bc112013-02-10 01:53:46 +0000120 } else {
Brian Silvermanaf221b82013-09-01 13:57:50 -0700121 if (futex_wait(&global_core->mem_struct->creation_condition) != 0) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700122 LOG(FATAL) << "waiting on creation_condition failed";
brians343bc112013-02-10 01:53:46 +0000123 }
124 }
brians343bc112013-02-10 01:53:46 +0000125}
126
Brian Silverman01be0002014-05-10 15:44:38 -0700127void aos_core_free_shared_mem() {
Austin Schuh32fd5a72019-12-01 22:20:26 -0800128 if (global_core != nullptr) {
129 void *shm_address = global_core->shared_mem;
130 PCHECK(munmap((void *)SHM_START, SIZEOFSHMSEG) != -1)
131 << ": munmap(" << shm_address << ", 0x" << std::hex
132 << (size_t)SIZEOFSHMSEG << ") failed";
133 if (global_core->owner) {
134 PCHECK(shm_unlink(global_core->shm_name) == 0)
135 << ": shared_mem: shm_unlink(" << global_core->shm_name << ") failed";
136 }
137 global_core = nullptr;
Brian Silverman01be0002014-05-10 15:44:38 -0700138 }
brians343bc112013-02-10 01:53:46 +0000139}
Brian Silvermanb263d302014-02-16 00:01:43 -0800140
Austin Schuh32fd5a72019-12-01 22:20:26 -0800141int aos_core_is_init(void) { return global_core != NULL; }