forked from frc971/971-Robot-Code
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshared_mem.cc
139 lines (126 loc) · 4.64 KB
/
shared_mem.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "aos/ipc_lib/shared_mem.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "aos/ipc_lib/aos_sync.h"
#include "aos/ipc_lib/core_lib.h"
#include "glog/logging.h"
// the path for the shared memory segment. see shm_open(3) for restrictions
#define AOS_SHM_NAME "/aos_shared_mem"
// Size of the shared mem segment.
// This must fit in the tmpfs for /dev/shm/
#define SIZEOFSHMSEG (4096 * 0x800)
void init_shared_mem_core(aos_shm_core *shm_core) {
memset(&shm_core->time_offset, 0, sizeof(shm_core->time_offset));
memset(&shm_core->msg_alloc_lock, 0, sizeof(shm_core->msg_alloc_lock));
shm_core->queues.pointer = NULL;
memset(&shm_core->queues.lock, 0, sizeof(shm_core->queues.lock));
shm_core->queue_types.pointer = NULL;
memset(&shm_core->queue_types.lock, 0, sizeof(shm_core->queue_types.lock));
}
ptrdiff_t aos_core_get_mem_usage(void) {
return global_core->size - ((ptrdiff_t)global_core->mem_struct->msg_alloc -
(ptrdiff_t)global_core->mem_struct);
}
struct aos_core *global_core = NULL;
// TODO(brians): madvise(2) it to put this shm in core dumps.
void aos_core_create_shared_mem(int create, int lock) {
assert(global_core == NULL);
static struct aos_core global_core_data;
global_core = &global_core_data;
{
char *shm_name = getenv("AOS_SHM_NAME");
if (shm_name == NULL) {
global_core->shm_name = AOS_SHM_NAME;
} else {
printf("AOS_SHM_NAME defined, using %s\n", shm_name);
global_core->shm_name = shm_name;
}
}
int shm;
if (create) {
while (1) {
shm = shm_open(global_core->shm_name, O_RDWR | O_CREAT | O_EXCL, 0666);
global_core->owner = 1;
if (shm == -1 && errno == EEXIST) {
printf("shared_mem: going to shm_unlink(%s)\n", global_core->shm_name);
if (shm_unlink(global_core->shm_name) == -1) {
PLOG(WARNING) << "shm_unlink(" << global_core->shm_name << ") failed";
break;
}
} else {
break;
}
}
} else {
shm = shm_open(global_core->shm_name, O_RDWR, 0);
global_core->owner = 0;
}
if (shm == -1) {
PLOG(FATAL) << "shm_open(" << global_core->shm_name
<< ", O_RDWR [| O_CREAT | O_EXCL, 0|0666) failed";
}
if (global_core->owner) {
PCHECK(ftruncate(shm, SIZEOFSHMSEG) == 0)
<< ": fruncate(" << shm << ", 0x" << std::hex << (size_t)SIZEOFSHMSEG
<< ") failed";
}
int flags = MAP_SHARED | MAP_FIXED;
if (lock) flags |= MAP_LOCKED | MAP_POPULATE;
void *shm_address = mmap((void *)SHM_START, SIZEOFSHMSEG,
PROT_READ | PROT_WRITE, flags, shm, 0);
PCHECK(shm_address != MAP_FAILED)
<< std::hex << "shared_mem: mmap(" << (void *)SHM_START << ", 0x"
<< (size_t)SIZEOFSHMSEG << ", stuff, " << flags << ", " << shm
<< ", 0) failed";
if (create) {
printf("shared_mem: creating %s, shm at: %p\n", global_core->shm_name,
shm_address);
} else {
printf("shared_mem: not creating, shm at: %p\n", shm_address);
}
if (close(shm) == -1) {
PLOG(WARNING) << "close(" << shm << "(=shm) failed";
}
PCHECK(shm_address == (void *)SHM_START)
<< "shm isn't at hard-coded " << (void *)SHM_START << ". at "
<< shm_address << " instead";
aos_core_use_address_as_shared_mem(shm_address, SIZEOFSHMSEG);
LOG(INFO) << "shared_mem: end of create_shared_mem owner="
<< global_core->owner;
}
void aos_core_use_address_as_shared_mem(void *address, size_t size) {
global_core->mem_struct = reinterpret_cast<aos_shm_core_t *>(address);
global_core->size = size;
global_core->shared_mem =
(uint8_t *)address + sizeof(*global_core->mem_struct);
if (global_core->owner) {
global_core->mem_struct->msg_alloc = (uint8_t *)address + global_core->size;
init_shared_mem_core(global_core->mem_struct);
futex_set(&global_core->mem_struct->creation_condition);
} else {
if (futex_wait(&global_core->mem_struct->creation_condition) != 0) {
LOG(FATAL) << "waiting on creation_condition failed";
}
}
}
void aos_core_free_shared_mem() {
if (global_core != nullptr) {
void *shm_address = global_core->shared_mem;
PCHECK(munmap((void *)SHM_START, SIZEOFSHMSEG) != -1)
<< ": munmap(" << shm_address << ", 0x" << std::hex
<< (size_t)SIZEOFSHMSEG << ") failed";
if (global_core->owner) {
PCHECK(shm_unlink(global_core->shm_name) == 0)
<< ": shared_mem: shm_unlink(" << global_core->shm_name << ") failed";
}
global_core = nullptr;
}
}
int aos_core_is_init(void) { return global_core != NULL; }