Implement shm object table
[lttng-ust.git] / libringbuffer / shm.c
CommitLineData
1d498196
MD
1/*
2 * libringbuffer/shm.c
3 *
4 * Copyright 2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * Dual LGPL v2.1/GPL v2 license.
7 */
8
9#include "shm.h"
10#include <unistd.h>
11#include <fcntl.h>
12#include <sys/mman.h>
13#include <sys/stat.h> /* For mode constants */
14#include <fcntl.h> /* For O_* constants */
15#include <assert.h>
16#include <ust/align.h>
17
18struct shm_object_table *shm_object_table_create(size_t max_nb_obj)
19{
20 struct shm_object_table *table;
21
22 table = zmalloc(sizeof(struct shm_object_table) +
23 max_nb_obj * sizeof(table->objects[0]));
24 table->size = max_nb_obj;
25 return table;
26}
27
28struct shm_object *shm_object_table_append(struct shm_object_table *table,
29 size_t memory_map_size)
30{
31 int shmfd, waitfd[2], ret, i;
32 struct shm_object *obj;
33 char *memory_map;
34
35 if (table->allocated_len >= table->size)
36 return NULL;
37 obj = &table->objects[table->allocated_len++];
38
39 /* wait_fd: create pipe */
40 ret = pipe(waitfd);
41 if (ret < 0) {
42 PERROR("pipe");
43 goto error_pipe;
44 }
45 for (i = 0; i < 2; i++) {
46 ret = fcntl(waitfd[i], F_SETFD, FD_CLOEXEC);
47 if (ret < 0) {
48 PERROR("fcntl");
49 goto error_fcntl;
50 }
51 }
52 *obj->wait_fd = *waitfd;
53
54 /* shm_fd: create shm */
55
56 /*
57 * Allocate shm, and immediately unlink its shm oject, keeping
58 * only the file descriptor as a reference to the object. If it
59 * already exists (caused by short race window during which the
60 * global object exists in a concurrent shm_open), simply retry.
61 * We specifically do _not_ use the / at the beginning of the
62 * pathname so that some OS implementations can keep it local to
63 * the process (POSIX leaves this implementation-defined).
64 */
65 do {
66 shmfd = shm_open("ust-shm-tmp",
67 O_CREAT | O_EXCL | O_RDWR, 0700);
68 } while (shmfd < 0 && errno == EEXIST);
69 if (shmfd < 0) {
70 PERROR("shm_open");
71 goto error_shm_open;
72 }
73 ret = shm_unlink("ust-shm-tmp");
74 if (ret) {
75 PERROR("shm_unlink");
76 goto error_unlink;
77 }
78 ret = ftruncate(shmfd, memory_map_size);
79 if (ret) {
80 PERROR("ftruncate");
81 goto error_ftruncate;
82 }
83 obj->shm_fd = shmfd;
84
85 /* memory_map: mmap */
86 memory_map = mmap(NULL, memory_map_size, PROT_READ | PROT_WRITE,
87 MAP_SHARED, shmfd, 0);
88 if (memory_map == MAP_FAILED) {
89 PERROR("mmap");
90 goto error_mmap;
91 }
92 obj->memory_map = memory_map;
93 obj->memory_map_size = memory_map_size;
94 obj->allocated_len = 0;
95 return obj;
96
97error_mmap:
98error_ftruncate:
99error_unlink:
100 ret = close(shmfd);
101 if (ret) {
102 PERROR("close");
103 assert(0);
104 }
105error_shm_open:
106error_fcntl:
107 for (i = 0; i < 2; i++) {
108 ret = close(waitfd[i]);
109 if (ret) {
110 PERROR("close");
111 assert(0);
112 }
113 }
114error_pipe:
115 free(obj);
116 return NULL;
117
118}
119
120static
121void shmp_object_destroy(struct shm_object *obj)
122{
123 int ret, i;
124
125 ret = munmap(obj->memory_map, obj->memory_map_size);
126 if (ret) {
127 PERROR("umnmap");
128 assert(0);
129 }
130 ret = close(obj->shm_fd);
131 if (ret) {
132 PERROR("close");
133 assert(0);
134 }
135 for (i = 0; i < 2; i++) {
136 ret = close(obj->wait_fd[i]);
137 if (ret) {
138 PERROR("close");
139 assert(0);
140 }
141 }
142}
143
144void shm_object_table_destroy(struct shm_object_table *table)
145{
146 int i;
147
148 for (i = 0; i < table->allocated_len; i++)
149 shmp_object_destroy(&table->objects[i]);
150 free(table);
151}
152
153/*
154 * zalloc_shm - allocate memory within a shm object.
155 *
156 * Shared memory is already zeroed by shmget.
157 * *NOT* multithread-safe (should be protected by mutex).
158 * Returns a -1, -1 tuple on error.
159 */
160struct shm_ref zalloc_shm(struct shm_object *obj, size_t len)
161{
162 struct shm_ref ref;
163 struct shm_ref shm_ref_error = { -1, -1 };
164
165 if (obj->memory_map_size - obj->allocated_len < len)
166 return shm_ref_error;
167 ref.index = obj->index;
168 ref.offset = obj->allocated_len;
169 obj->allocated_len += len;
170 return ref;
171}
172
173void align_shm(struct shm_object *obj, size_t align)
174{
175 size_t offset_len = offset_align(obj->allocated_len, align);
176 obj->allocated_len += offset_len;
177}
This page took 0.028831 seconds and 4 git commands to generate.