Fix: Hide pipe symbols in common lib
[lttng-tools.git] / src / common / pipe.c
CommitLineData
9fd92637
DG
1/*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
6c1c0768 19#define _LGPL_SOURCE
9fd92637
DG
20#include <assert.h>
21#include <fcntl.h>
22#include <unistd.h>
23
24#include <common/common.h>
25
26#include "pipe.h"
27
28/*
29 * Lock read side of a pipe.
30 */
31static void lock_read_side(struct lttng_pipe *pipe)
32{
33 pthread_mutex_lock(&pipe->read_mutex);
34}
35
36/*
37 * Unlock read side of a pipe.
38 */
39static void unlock_read_side(struct lttng_pipe *pipe)
40{
41 pthread_mutex_unlock(&pipe->read_mutex);
42}
43
44/*
45 * Lock write side of a pipe.
46 */
47static void lock_write_side(struct lttng_pipe *pipe)
48{
49 pthread_mutex_lock(&pipe->write_mutex);
50}
51
52/*
53 * Unlock write side of a pipe.
54 */
55static void unlock_write_side(struct lttng_pipe *pipe)
56{
57 pthread_mutex_unlock(&pipe->write_mutex);
58}
59
60/*
61 * Internal function. Close read side of pipe WITHOUT locking the mutex.
62 *
63 * Return 0 on success else a negative errno from close(2).
64 */
65static int _pipe_read_close(struct lttng_pipe *pipe)
66{
67 int ret, ret_val = 0;
68
69 assert(pipe);
70
71 if (!lttng_pipe_is_read_open(pipe)) {
72 goto end;
73 }
74
75 do {
76 ret = close(pipe->fd[0]);
77 } while (ret < 0 && errno == EINTR);
78 if (ret < 0) {
79 PERROR("close lttng read pipe");
80 ret_val = -errno;
81 }
82 pipe->r_state = LTTNG_PIPE_STATE_CLOSED;
83
84end:
85 return ret_val;
86}
87
88/*
89 * Internal function. Close write side of pipe WITHOUT locking the mutex.
90 *
91 * Return 0 on success else a negative errno from close(2).
92 */
93static int _pipe_write_close(struct lttng_pipe *pipe)
94{
95 int ret, ret_val = 0;
96
97 assert(pipe);
98
99 if (!lttng_pipe_is_write_open(pipe)) {
100 goto end;
101 }
102
103 do {
104 ret = close(pipe->fd[1]);
105 } while (ret < 0 && errno == EINTR);
106 if (ret < 0) {
107 PERROR("close lttng write pipe");
108 ret_val = -errno;
109 }
110 pipe->w_state = LTTNG_PIPE_STATE_CLOSED;
111
112end:
113 return ret_val;
114}
115
116
117/*
118 * Open a new lttng pipe and set flags using fcntl().
119 *
120 * Return a newly allocated lttng pipe on success or else NULL.
121 */
a247c6e0 122LTTNG_HIDDEN
9fd92637
DG
123struct lttng_pipe *lttng_pipe_open(int flags)
124{
125 int ret;
126 struct lttng_pipe *p;
127
128 p = zmalloc(sizeof(*p));
129 if (!p) {
130 PERROR("zmalloc pipe open");
131 goto error;
132 }
133
134 ret = pipe(p->fd);
135 if (ret < 0) {
136 PERROR("lttng pipe");
137 goto error;
138 }
139
140 if (flags) {
141 int i;
142
143 for (i = 0; i < 2; i++) {
144 ret = fcntl(p->fd[i], F_SETFD, flags);
145 if (ret < 0) {
146 PERROR("fcntl lttng pipe %d", flags);
147 goto error;
148 }
149 }
150 }
151
152 pthread_mutex_init(&p->read_mutex, NULL);
153 pthread_mutex_init(&p->write_mutex, NULL);
154 p->r_state = LTTNG_PIPE_STATE_OPENED;
155 p->w_state = LTTNG_PIPE_STATE_OPENED;
156 p->flags = flags;
157
158 return p;
159
160error:
161 lttng_pipe_destroy(p);
162 return NULL;
163}
164
165/*
166 * Close read side of a lttng pipe.
167 *
168 * Return 0 on success else a negative value.
169 */
a247c6e0 170LTTNG_HIDDEN
9fd92637
DG
171int lttng_pipe_read_close(struct lttng_pipe *pipe)
172{
173 int ret;
174
175 assert(pipe);
176
177 /* Handle read side first. */
178 lock_read_side(pipe);
179 ret = _pipe_read_close(pipe);
180 unlock_read_side(pipe);
181
182 return ret;
183}
184
185/*
186 * Close write side of a lttng pipe.
187 *
188 * Return 0 on success else a negative value.
189 */
a247c6e0 190LTTNG_HIDDEN
9fd92637
DG
191int lttng_pipe_write_close(struct lttng_pipe *pipe)
192{
193 int ret;
194
195 assert(pipe);
196
197 lock_write_side(pipe);
198 ret = _pipe_write_close(pipe);
199 unlock_write_side(pipe);
200
201 return ret;
202}
203
204/*
205 * Close both read and write side of a lttng pipe.
206 *
207 * Return 0 on success else a negative value.
208 */
a247c6e0 209LTTNG_HIDDEN
9fd92637
DG
210int lttng_pipe_close(struct lttng_pipe *pipe)
211{
212 int ret, ret_val = 0;
213
214 assert(pipe);
215
216 ret = lttng_pipe_read_close(pipe);
217 if (ret < 0) {
218 ret_val = ret;
219 }
220
221 ret = lttng_pipe_write_close(pipe);
222 if (ret < 0) {
223 ret_val = ret;
224 }
225
226 return ret_val;
227}
228
229/*
230 * Close and destroy a lttng pipe object. Finally, pipe is freed.
231 */
a247c6e0 232LTTNG_HIDDEN
9fd92637
DG
233void lttng_pipe_destroy(struct lttng_pipe *pipe)
234{
235 int ret;
236
237 if (!pipe) {
238 return;
239 }
240
241 /*
242 * Destroy should *never* be called with a locked mutex. These must always
243 * succeed so we unlock them after the close pipe below.
244 */
245 ret = pthread_mutex_trylock(&pipe->read_mutex);
246 assert(!ret);
247 ret = pthread_mutex_trylock(&pipe->write_mutex);
248 assert(!ret);
249
250 /* Close pipes WITHOUT trying to lock the pipes. */
251 (void) _pipe_read_close(pipe);
252 (void) _pipe_write_close(pipe);
253
254 unlock_read_side(pipe);
255 unlock_write_side(pipe);
256
257 (void) pthread_mutex_destroy(&pipe->read_mutex);
258 (void) pthread_mutex_destroy(&pipe->write_mutex);
259
260 free(pipe);
261}
262
263/*
264 * Read on a lttng pipe and put the data in buf of at least size count.
265 *
6cd525e8
MD
266 * Return "count" on success. Return < count on error. errno can be used
267 * to check the actual error.
9fd92637 268 */
a247c6e0 269LTTNG_HIDDEN
9fd92637
DG
270ssize_t lttng_pipe_read(struct lttng_pipe *pipe, void *buf, size_t count)
271{
6cd525e8 272 ssize_t ret;
9fd92637
DG
273
274 assert(pipe);
275 assert(buf);
276
277 lock_read_side(pipe);
9fd92637 278 if (!lttng_pipe_is_read_open(pipe)) {
6cd525e8
MD
279 ret = -1;
280 errno = EBADF;
9fd92637
DG
281 goto error;
282 }
6cd525e8 283 ret = lttng_read(pipe->fd[0], buf, count);
9fd92637
DG
284error:
285 unlock_read_side(pipe);
286 return ret;
287}
288
289/*
290 * Write on a lttng pipe using the data in buf and size of count.
291 *
6cd525e8
MD
292 * Return "count" on success. Return < count on error. errno can be used
293 * to check the actual error.
9fd92637 294 */
a247c6e0 295LTTNG_HIDDEN
9fd92637
DG
296ssize_t lttng_pipe_write(struct lttng_pipe *pipe, const void *buf,
297 size_t count)
298{
6cd525e8 299 ssize_t ret;
9fd92637
DG
300
301 assert(pipe);
302 assert(buf);
303
304 lock_write_side(pipe);
9fd92637 305 if (!lttng_pipe_is_write_open(pipe)) {
6cd525e8
MD
306 ret = -1;
307 errno = EBADF;
9fd92637
DG
308 goto error;
309 }
6cd525e8 310 ret = lttng_write(pipe->fd[1], buf, count);
9fd92637
DG
311error:
312 unlock_write_side(pipe);
313 return ret;
314}
This page took 0.040745 seconds and 4 git commands to generate.