Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.openwrt.org/project/libubox.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2016-12-15 01:26:51 +0300
committerFelix Fietkau <nbd@nbd.name>2016-12-29 00:44:30 +0300
commit0fe13749d095ca22c788e55902979323e85367c3 (patch)
tree661be57db5a17836674b90e650a2f8fe16c21125
parent8fc1c3053e1cdaa341a6009e18eced821f1eda3e (diff)
utils: add helper functions useful for allocating a ring buffer
This creates a mapping with twice the size of the allocated memory. The second half of that mapping points at the same memory as the first half. This is useful for ring buffers, because any read starting in the first half can overflow into the second half as long as the read size is smaller than the size of the memory area. Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--utils.c48
-rw-r--r--utils.h20
2 files changed, 67 insertions, 1 deletions
diff --git a/utils.c b/utils.c
index 91dd71e..e59002e 100644
--- a/utils.c
+++ b/utils.c
@@ -16,10 +16,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "utils.h"
+#include <sys/mman.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
+#include "utils.h"
#define foreach_arg(_arg, _addr, _len, _first_addr, _first_len) \
for (_addr = (_first_addr), _len = (_first_len); \
@@ -103,3 +104,48 @@ out:
}
#endif
+
+void *cbuf_alloc(unsigned int order)
+{
+ char path[] = "/tmp/cbuf-XXXXXX";
+ unsigned long size = cbuf_size(order);
+ void *ret = NULL;
+ int fd;
+
+ fd = mkstemp(path);
+ if (fd < 0)
+ return NULL;
+
+ if (unlink(path))
+ goto close;
+
+ if (ftruncate(fd, cbuf_size(order)))
+ goto close;
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+ ret = mmap(NULL, size * 2, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (ret == MAP_FAILED) {
+ ret = NULL;
+ goto close;
+ }
+
+ if (mmap(ret, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
+ fd, 0) != ret ||
+ mmap(ret + size, size, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_SHARED, fd, 0) != ret + size) {
+ munmap(ret, size * 2);
+ ret = NULL;
+ }
+
+close:
+ close(fd);
+ return ret;
+}
+
+void cbuf_free(void *ptr, unsigned int order)
+{
+ munmap(ptr, cbuf_size(order) * 2);
+}
diff --git a/utils.h b/utils.h
index d00e76b..803150b 100644
--- a/utils.h
+++ b/utils.h
@@ -23,6 +23,7 @@
#include <sys/time.h>
#include <stdint.h>
#include <stdbool.h>
+#include <unistd.h>
#include <time.h>
/*
@@ -192,4 +193,23 @@ int b64_decode(const void *src, void *dest, size_t dest_len);
#define B64_ENCODE_LEN(_len) ((((_len) + 2) / 3) * 4 + 1)
#define B64_DECODE_LEN(_len) (((_len) / 4) * 3 + 1)
+static inline unsigned int cbuf_order(unsigned int x)
+{
+ return 32 - __builtin_clz(x - 1);
+}
+
+static inline unsigned long cbuf_size(int order)
+{
+ unsigned long page_size = sysconf(_SC_PAGESIZE);
+ unsigned long ret = 1ULL << order;
+
+ if (ret < page_size)
+ ret = page_size;
+
+ return ret;
+}
+
+void *cbuf_alloc(unsigned int order);
+void cbuf_free(void *ptr, unsigned int order);
+
#endif