]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/ringbuf.c
3 * Copyright © 2017 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2017 Canonical Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #define __STDC_FORMAT_MACROS
35 #include "syscall_wrappers.h"
38 int lxc_ringbuf_create(struct lxc_ringbuf
*buf
, size_t size
)
48 /* verify that we are at least given the multiple of a page size */
49 if (buf
->size
% lxc_getpagesize())
52 buf
->addr
= mmap(NULL
, buf
->size
* 2, PROT_NONE
,
53 MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
54 if (buf
->addr
== MAP_FAILED
)
57 memfd
= memfd_create(".lxc_ringbuf", MFD_CLOEXEC
);
59 char template[] = P_tmpdir
"/.lxc_ringbuf_XXXXXX";
64 memfd
= lxc_make_tmpfile(template, true);
69 ret
= ftruncate(memfd
, buf
->size
);
73 tmp
= mmap(buf
->addr
, buf
->size
, PROT_READ
| PROT_WRITE
,
74 MAP_FIXED
| MAP_SHARED
, memfd
, 0);
75 if (tmp
== MAP_FAILED
|| tmp
!= buf
->addr
)
78 tmp
= mmap(buf
->addr
+ buf
->size
, buf
->size
, PROT_READ
| PROT_WRITE
,
79 MAP_FIXED
| MAP_SHARED
, memfd
, 0);
80 if (tmp
== MAP_FAILED
|| tmp
!= (buf
->addr
+ buf
->size
))
88 lxc_ringbuf_release(buf
);
94 void lxc_ringbuf_move_read_addr(struct lxc_ringbuf
*buf
, size_t len
)
98 if (buf
->r_off
< buf
->size
)
102 buf
->r_off
-= buf
->size
;
103 buf
->w_off
-= buf
->size
;
107 * lxc_ringbuf_write - write a message to the ringbuffer
108 * - The size of the message should never be greater than the size of the whole
110 * - The write method will always succeed i.e. it will always advance the r_off
111 * if it detects that there's not enough space available to write the
114 int lxc_ringbuf_write(struct lxc_ringbuf
*buf
, const char *msg
, size_t len
)
119 /* sanity check: a write should never exceed the ringbuffer's total size */
123 free
= lxc_ringbuf_free(buf
);
125 /* not enough space left so advance read address */
127 lxc_ringbuf_move_read_addr(buf
, len
);
128 w_addr
= lxc_ringbuf_get_write_addr(buf
);
129 memcpy(w_addr
, msg
, len
);
130 lxc_ringbuf_move_write_addr(buf
, len
);
134 int lxc_ringbuf_read(struct lxc_ringbuf
*buf
, char *out
, size_t *len
)
138 /* there's nothing to read */
139 if (buf
->r_off
== buf
->w_off
)
142 /* read maximum amount available */
143 used
= lxc_ringbuf_used(buf
);
147 /* copy data to reader but don't advance addr */
148 memcpy(out
, lxc_ringbuf_get_read_addr(buf
), *len
);
149 out
[*len
- 1] = '\0';