]>
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.
21 #define __STDC_FORMAT_MACROS
34 int lxc_ringbuf_create(struct lxc_ringbuf
*buf
, size_t size
)
44 /* verify that we are at least given the multiple of a page size */
45 if (buf
->size
% lxc_getpagesize())
48 buf
->addr
= mmap(NULL
, buf
->size
* 2, PROT_NONE
,
49 MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
50 if (buf
->addr
== MAP_FAILED
)
53 memfd
= memfd_create(".lxc_ringbuf", MFD_CLOEXEC
);
58 memfd
= lxc_make_tmpfile((char *){P_tmpdir
"/.lxc_ringbuf_XXXXXX"}, true);
63 ret
= ftruncate(memfd
, buf
->size
);
67 tmp
= mmap(buf
->addr
, buf
->size
, PROT_READ
| PROT_WRITE
,
68 MAP_FIXED
| MAP_SHARED
, memfd
, 0);
69 if (tmp
== MAP_FAILED
|| tmp
!= buf
->addr
)
72 tmp
= mmap(buf
->addr
+ buf
->size
, buf
->size
, PROT_READ
| PROT_WRITE
,
73 MAP_FIXED
| MAP_SHARED
, memfd
, 0);
74 if (tmp
== MAP_FAILED
|| tmp
!= (buf
->addr
+ buf
->size
))
82 lxc_ringbuf_release(buf
);
88 void lxc_ringbuf_move_read_addr(struct lxc_ringbuf
*buf
, size_t len
)
92 if (buf
->r_off
< buf
->size
)
96 buf
->r_off
-= buf
->size
;
97 buf
->w_off
-= buf
->size
;
101 * lxc_ringbuf_write - write a message to the ringbuffer
102 * - The size of the message should never be greater than the size of the whole
104 * - The write method will always succeed i.e. it will always advance the r_off
105 * if it detects that there's not enough space available to write the
108 int lxc_ringbuf_write(struct lxc_ringbuf
*buf
, const char *msg
, size_t len
)
113 /* sanity check: a write should never exceed the ringbuffer's total size */
117 free
= lxc_ringbuf_free(buf
);
119 /* not enough space left so advance read address */
121 lxc_ringbuf_move_read_addr(buf
, len
);
122 w_addr
= lxc_ringbuf_get_write_addr(buf
);
123 memcpy(w_addr
, msg
, len
);
124 lxc_ringbuf_move_write_addr(buf
, len
);
128 int lxc_ringbuf_read(struct lxc_ringbuf
*buf
, char *out
, size_t *len
)
132 /* there's nothing to read */
133 if (buf
->r_off
== buf
->w_off
)
136 /* read maximum amount available */
137 used
= lxc_ringbuf_used(buf
);
141 /* copy data to reader but don't advance addr */
142 memcpy(out
, lxc_ringbuf_get_read_addr(buf
), *len
);
143 out
[*len
- 1] = '\0';