blob: e8edc9ed7efdde78257405ae2c5d6ff37cac8c63 [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
3#include <stdio.h>
4#include <string.h>
5#include <sys/mman.h>
6#include <fcntl.h>
7#include <unistd.h>
8#include <sys/types.h>
9#include <errno.h>
Brian Silvermanbf2f9462014-02-25 13:33:52 -080010#include <stdlib.h>
Brian Silverman6da04272014-05-18 18:47:48 -070011#include <assert.h>
brians343bc112013-02-10 01:53:46 +000012
John Park398c74a2018-10-20 21:17:39 -070013#include "aos/ipc_lib/core_lib.h"
John Park33858a32018-09-28 23:05:48 -070014#include "aos/logging/logging.h"
John Park398c74a2018-10-20 21:17:39 -070015#include "aos/ipc_lib/aos_sync.h"
Brian Silverman08661c72013-09-01 17:24:38 -070016
brians343bc112013-02-10 01:53:46 +000017// the path for the shared memory segment. see shm_open(3) for restrictions
18#define AOS_SHM_NAME "/aos_shared_mem"
19// Size of the shared mem segment.
Austin Schuh0480bc82014-10-25 18:01:51 -070020// This must fit in the tmpfs for /dev/shm/
21#define SIZEOFSHMSEG (4096 * 0x3000)
brians343bc112013-02-10 01:53:46 +000022
Brian Silverman08661c72013-09-01 17:24:38 -070023void init_shared_mem_core(aos_shm_core *shm_core) {
Brian Silvermand0575692015-02-21 16:24:02 -050024 memset(&shm_core->time_offset, 0 , sizeof(shm_core->time_offset));
Brian Silvermandc1eb272014-08-19 14:25:59 -040025 memset(&shm_core->msg_alloc_lock, 0, sizeof(shm_core->msg_alloc_lock));
Brian Silverman4aeac5f2014-02-11 22:17:07 -080026 shm_core->queues.pointer = NULL;
Brian Silvermandc1eb272014-08-19 14:25:59 -040027 memset(&shm_core->queues.lock, 0, sizeof(shm_core->queues.lock));
Brian Silverman4aeac5f2014-02-11 22:17:07 -080028 shm_core->queue_types.pointer = NULL;
Brian Silvermandc1eb272014-08-19 14:25:59 -040029 memset(&shm_core->queue_types.lock, 0, sizeof(shm_core->queue_types.lock));
Brian Silverman08661c72013-09-01 17:24:38 -070030}
31
brians343bc112013-02-10 01:53:46 +000032ptrdiff_t aos_core_get_mem_usage(void) {
33 return global_core->size -
34 ((ptrdiff_t)global_core->mem_struct->msg_alloc -
35 (ptrdiff_t)global_core->mem_struct);
36}
37
brians343bc112013-02-10 01:53:46 +000038struct aos_core *global_core = NULL;
39
Brian Silverman67e34f52014-03-13 15:52:57 -070040// TODO(brians): madvise(2) it to put this shm in core dumps.
Brian Silverman8a6dac92015-02-21 20:08:24 -050041void aos_core_create_shared_mem(int create, int lock) {
Brian Silverman6da04272014-05-18 18:47:48 -070042 assert(global_core == NULL);
Brian Silverman08661c72013-09-01 17:24:38 -070043 static struct aos_core global_core_data;
brians343bc112013-02-10 01:53:46 +000044 global_core = &global_core_data;
Brian Silvermanbf2f9462014-02-25 13:33:52 -080045
46 {
47 char *shm_name = getenv("AOS_SHM_NAME");
48 if (shm_name == NULL) {
49 global_core->shm_name = AOS_SHM_NAME;
50 } else {
Austin Schuh293d37c2015-03-08 18:47:45 -070051 printf("AOS_SHM_NAME defined, using %s\n", shm_name);
Brian Silvermanbf2f9462014-02-25 13:33:52 -080052 global_core->shm_name = shm_name;
53 }
54 }
55
brians343bc112013-02-10 01:53:46 +000056 int shm;
Brian Silverman8a6dac92015-02-21 20:08:24 -050057 if (create) {
Brian48610152014-04-02 12:28:19 -070058 while (1) {
Brian48610152014-04-02 12:28:19 -070059 shm = shm_open(global_core->shm_name, O_RDWR | O_CREAT | O_EXCL, 0666);
60 global_core->owner = 1;
61 if (shm == -1 && errno == EEXIST) {
62 printf("shared_mem: going to shm_unlink(%s)\n", global_core->shm_name);
63 if (shm_unlink(global_core->shm_name) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070064 PLOG(WARNING, "shm_unlink(%s) failed", global_core->shm_name);
Brian48610152014-04-02 12:28:19 -070065 break;
66 }
brians343bc112013-02-10 01:53:46 +000067 } else {
Brian48610152014-04-02 12:28:19 -070068 break;
brians343bc112013-02-10 01:53:46 +000069 }
70 }
71 } else {
Brian Silvermanbf2f9462014-02-25 13:33:52 -080072 shm = shm_open(global_core->shm_name, O_RDWR, 0);
brians343bc112013-02-10 01:53:46 +000073 global_core->owner = 0;
74 }
75 if (shm == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070076 PLOG(FATAL, "shm_open(%s, O_RDWR [| O_CREAT | O_EXCL, 0|0666) failed",
77 global_core->shm_name);
brians343bc112013-02-10 01:53:46 +000078 }
79 if (global_core->owner) {
80 if (ftruncate(shm, SIZEOFSHMSEG) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070081 PLOG(FATAL, "fruncate(%d, 0x%zx) failed", shm, (size_t)SIZEOFSHMSEG);
brians343bc112013-02-10 01:53:46 +000082 }
83 }
Brian Silverman8a6dac92015-02-21 20:08:24 -050084 int flags = MAP_SHARED | MAP_FIXED;
85 if (lock) flags |= MAP_LOCKED | MAP_POPULATE;
86 void *shm_address = mmap((void *)SHM_START, SIZEOFSHMSEG,
87 PROT_READ | PROT_WRITE, flags, shm, 0);
brians343bc112013-02-10 01:53:46 +000088 if (shm_address == MAP_FAILED) {
Brian Silverman8a6dac92015-02-21 20:08:24 -050089 PLOG(FATAL, "shared_mem: mmap(%p, 0x%zx, stuff, %x, %d, 0) failed",
90 (void *)SHM_START, (size_t)SIZEOFSHMSEG, flags, shm);
brians343bc112013-02-10 01:53:46 +000091 }
Austin Schuh293d37c2015-03-08 18:47:45 -070092 if (create) {
93 printf("shared_mem: creating %s, shm at: %p\n", global_core->shm_name,
94 shm_address);
95 } else {
96 printf("shared_mem: not creating, shm at: %p\n", shm_address);
97 }
brians343bc112013-02-10 01:53:46 +000098 if (close(shm) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070099 PLOG(WARNING, "close(%d(=shm) failed", shm);
brians343bc112013-02-10 01:53:46 +0000100 }
101 if (shm_address != (void *)SHM_START) {
Brian Silverman01be0002014-05-10 15:44:38 -0700102 LOG(FATAL, "shm isn't at hard-coded %p. at %p instead\n",
brians343bc112013-02-10 01:53:46 +0000103 (void *)SHM_START, shm_address);
brians343bc112013-02-10 01:53:46 +0000104 }
Brian Silverman01be0002014-05-10 15:44:38 -0700105 aos_core_use_address_as_shared_mem(shm_address, SIZEOFSHMSEG);
106 LOG(INFO, "shared_mem: end of create_shared_mem owner=%d\n",
107 global_core->owner);
brians343bc112013-02-10 01:53:46 +0000108}
109
Brian Silverman01be0002014-05-10 15:44:38 -0700110void aos_core_use_address_as_shared_mem(void *address, size_t size) {
brians343bc112013-02-10 01:53:46 +0000111 global_core->mem_struct = address;
112 global_core->size = size;
Brian Silvermanbf2f9462014-02-25 13:33:52 -0800113 global_core->shared_mem =
114 (uint8_t *)address + sizeof(*global_core->mem_struct);
brians343bc112013-02-10 01:53:46 +0000115 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 Silvermanaf221b82013-09-01 13:57:50 -0700118 futex_set(&global_core->mem_struct->creation_condition);
brians343bc112013-02-10 01:53:46 +0000119 } else {
Brian Silvermanaf221b82013-09-01 13:57:50 -0700120 if (futex_wait(&global_core->mem_struct->creation_condition) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -0700121 LOG(FATAL, "waiting on creation_condition failed\n");
brians343bc112013-02-10 01:53:46 +0000122 }
123 }
brians343bc112013-02-10 01:53:46 +0000124}
125
Brian Silverman01be0002014-05-10 15:44:38 -0700126void aos_core_free_shared_mem() {
brians343bc112013-02-10 01:53:46 +0000127 void *shm_address = global_core->shared_mem;
Brian Silverman01be0002014-05-10 15:44:38 -0700128 if (munmap((void *)SHM_START, SIZEOFSHMSEG) == -1) {
129 PLOG(FATAL, "munmap(%p, 0x%zx) failed", shm_address,
130 (size_t)SIZEOFSHMSEG);
brians343bc112013-02-10 01:53:46 +0000131 }
Brian Silverman01be0002014-05-10 15:44:38 -0700132 if (global_core->owner) {
133 if (shm_unlink(global_core->shm_name)) {
134 PLOG(FATAL, "shared_mem: shm_unlink(%s) failed", global_core->shm_name);
135 }
136 }
brians343bc112013-02-10 01:53:46 +0000137}
Brian Silvermanb263d302014-02-16 00:01:43 -0800138
139int aos_core_is_init(void) {
140 return global_core != NULL;
141}