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

github.com/checkpoint-restore/criu.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/flog
diff options
context:
space:
mode:
authorprakritigoyal19 <prakritigoyal19@gmail.com>2020-06-07 06:52:53 +0300
committerAndrei Vagin <avagin@google.com>2022-05-13 03:55:45 +0300
commit6f8d5435bbb54bf44f73802ada0b351f2f473156 (patch)
treeb8a40272e2903f6c5a2dfce097ae6d17ed556afc /flog
parent4f8f295e57e68740699479d12c1ad251e6dd859f (diff)
Add flog to CRIU
Change made through this commit: - Include copy of flog as a seperate tree. - Modify the makefile to add and compile flog code. Signed-off-by: prakritigoyal19 <prakritigoyal19@gmail.com>
Diffstat (limited to 'flog')
-rw-r--r--flog/Makefile29
-rw-r--r--flog/built-in.S4
-rw-r--r--flog/include/compiler.h71
-rw-r--r--flog/include/flog.h9
-rw-r--r--flog/include/log.h17
-rw-r--r--flog/include/types.h16
-rw-r--r--flog/include/uapi/flog.h149
-rw-r--r--flog/include/util.h37
-rw-r--r--flog/src/Makefile5
-rw-r--r--flog/src/flog.c215
-rw-r--r--flog/src/main.c170
-rwxr-xr-xflog/tests/test0022
12 files changed, 744 insertions, 0 deletions
diff --git a/flog/Makefile b/flog/Makefile
new file mode 100644
index 000000000..12255af71
--- /dev/null
+++ b/flog/Makefile
@@ -0,0 +1,29 @@
+OPTS=-ggdb3 -Wall -Werror
+export OPTS
+
+CFLAGS += -iquote include
+CFLAGS += -iquote flog/include
+CFLAGS += -iquote flog/include/uapi
+
+include $(__nmk_dir)msg.mk
+
+$(eval $(call gen-built-in,src))
+
+flog:
+ $(Q) $(MAKE) $(build)=$(obj)/src all
+.PHONY: flog
+
+clean-flog:
+ $(call msg-gen, $@)
+ $(Q) $(MAKE) $(build)=$(obj)/src clean
+ $(Q) $(RM) built-in.o
+.PHONY: clean-flog
+
+clean: clean-flog
+mrproper: clean
+
+test:
+ ./tests/test00
+
+all-y += flog
+
diff --git a/flog/built-in.S b/flog/built-in.S
new file mode 100644
index 000000000..26627d054
--- /dev/null
+++ b/flog/built-in.S
@@ -0,0 +1,4 @@
+SECTIONS
+{
+ .rodata : { _rodata_start = . ; *(.rodata*) ; _rodata_end = . ;}
+}
diff --git a/flog/include/compiler.h b/flog/include/compiler.h
new file mode 100644
index 000000000..3e56eb0e6
--- /dev/null
+++ b/flog/include/compiler.h
@@ -0,0 +1,71 @@
+#ifndef __COMPILER_H__
+#define __COMPILER_H__
+
+/*
+ * Various definitions for success build,
+ * picked from various places, mostly from
+ * the linux kernel.
+ */
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+
+#define __stringify_1(x...) #x
+#define __stringify(x...) __stringify_1(x)
+
+#define NORETURN __attribute__((__noreturn__))
+#define __packed __attribute__((__packed__))
+#define __used __attribute__((__used__))
+#define __maybe_unused __attribute__((unused))
+#define __always_unused __attribute__((unused))
+
+#define __section(S) __attribute__ ((__section__(#S)))
+
+#ifndef __always_inline
+# define __always_inline inline __attribute__((always_inline))
+#endif
+
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#ifndef always_inline
+# define always_inline __always_inline
+#endif
+
+#ifndef noinline
+# define noinline __attribute__((noinline))
+#endif
+
+#define __aligned(x) __attribute__((aligned(x)))
+
+#ifndef offsetof
+# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#define barrier() asm volatile("" ::: "memory")
+
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define __round_mask(x, y) ((__typeof__(x))((y) - 1))
+#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+
+#define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({ \
+ typeof(x) _max1 = (x); \
+ typeof(y) _max2 = (y); \
+ (void) (&_max1 == &_max2); \
+ _max1 > _max2 ? _max1 : _max2; })
+
+#define is_log2(v) (((v) & ((v) - 1)) == 0)
+
+#endif /* __COMPILER_H__ */
diff --git a/flog/include/flog.h b/flog/include/flog.h
new file mode 100644
index 000000000..f00c20541
--- /dev/null
+++ b/flog/include/flog.h
@@ -0,0 +1,9 @@
+#ifndef __FLOG_H__
+#define __FLOG_H__
+
+#include <string.h>
+#include <errno.h>
+
+#include "uapi/flog.h"
+
+#endif /* __FLOG_H__ */
diff --git a/flog/include/log.h b/flog/include/log.h
new file mode 100644
index 000000000..1a165ea9f
--- /dev/null
+++ b/flog/include/log.h
@@ -0,0 +1,17 @@
+#ifndef __LOG_H__
+#define __LOG_H__
+
+#include <stdio.h>
+
+#define pr_out(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
+
+#if 1
+# define pr_debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+# define pr_debug(fmt, ...)
+#endif
+
+#define pr_err(fmt, ...) fprintf(stderr, "Error (%s:%d): "fmt, __FILE__, __LINE__, ##__VA_ARGS__)
+#define pr_perror(fmt, ...) fprintf(stderr, "Error (%s:%d): "fmt "%m\n", __FILE__, __LINE__, ##__VA_ARGS__)
+
+#endif /* __LOG_H__ */
diff --git a/flog/include/types.h b/flog/include/types.h
new file mode 100644
index 000000000..0e15bfbff
--- /dev/null
+++ b/flog/include/types.h
@@ -0,0 +1,16 @@
+#ifndef __FLOG_TYPES_H__
+#define __FLOG_TYPES_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef uint64_t u64;
+typedef int64_t s64;
+typedef uint32_t u32;
+typedef int32_t s32;
+typedef uint16_t u16;
+typedef int16_t s16;
+typedef uint8_t u8;
+typedef int8_t s8;
+
+#endif /* __FLOG_TYPES_H__ */
diff --git a/flog/include/uapi/flog.h b/flog/include/uapi/flog.h
new file mode 100644
index 000000000..2d879110f
--- /dev/null
+++ b/flog/include/uapi/flog.h
@@ -0,0 +1,149 @@
+#ifndef __UAPI_FLOG_H__
+#define __UAPI_FLOG_H__
+
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * We work with up to 32 arguments in macros here.
+ * If more provided -- behaviour is undefined.
+ */
+
+/*
+ * By Laurent Deniau at https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s
+ */
+#define FLOG_PP_NARG_(...) FLOG_PP_ARG_N(__VA_ARGS__)
+#define FLOG_PP_NARG(...) FLOG_PP_NARG_(1, ##__VA_ARGS__, FLOG_PP_RSEQ_N())
+
+#define FLOG_PP_ARG_N( _0, _1, _2, _3, _4, \
+ _5, _6, _7, _8, _9, \
+ _10,_11,_12,_13,_14, \
+ _15,_16,_17,_18,_19, \
+ _20,_21,_22,_23,_24, \
+ _25,_26,_27,_28,_29, \
+ _30,_31, N, ...) N
+
+#define FLOG_PP_RSEQ_N() \
+ 31, 30, 29, 28, 27, \
+ 26, 25, 24, 23, 22, \
+ 21, 20, 19, 18, 17, \
+ 16, 15, 14, 13, 12, \
+ 11, 10, 9, 8, 7, \
+ 6, 5, 4, 3, 2, \
+ 1, 0
+
+#define FLOG_GENMASK_0(N, x) 0
+#define FLOG_GENMASK_1(N, op, x, ...) (op(N, 0, x))
+#define FLOG_GENMASK_2(N, op, x, ...) ((op(N, 1, x)) | FLOG_GENMASK_1(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_3(N, op, x, ...) ((op(N, 2, x)) | FLOG_GENMASK_2(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_4(N, op, x, ...) ((op(N, 3, x)) | FLOG_GENMASK_3(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_5(N, op, x, ...) ((op(N, 4, x)) | FLOG_GENMASK_4(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_6(N, op, x, ...) ((op(N, 5, x)) | FLOG_GENMASK_5(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_7(N, op, x, ...) ((op(N, 6, x)) | FLOG_GENMASK_6(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_8(N, op, x, ...) ((op(N, 7, x)) | FLOG_GENMASK_7(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_9(N, op, x, ...) ((op(N, 8, x)) | FLOG_GENMASK_8(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_10(N, op, x, ...) ((op(N, 9, x)) | FLOG_GENMASK_9(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_11(N, op, x, ...) ((op(N, 10, x)) | FLOG_GENMASK_10(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_12(N, op, x, ...) ((op(N, 11, x)) | FLOG_GENMASK_11(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_13(N, op, x, ...) ((op(N, 12, x)) | FLOG_GENMASK_12(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_14(N, op, x, ...) ((op(N, 13, x)) | FLOG_GENMASK_13(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_15(N, op, x, ...) ((op(N, 14, x)) | FLOG_GENMASK_14(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_16(N, op, x, ...) ((op(N, 15, x)) | FLOG_GENMASK_15(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_17(N, op, x, ...) ((op(N, 16, x)) | FLOG_GENMASK_16(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_18(N, op, x, ...) ((op(N, 17, x)) | FLOG_GENMASK_17(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_19(N, op, x, ...) ((op(N, 18, x)) | FLOG_GENMASK_18(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_20(N, op, x, ...) ((op(N, 19, x)) | FLOG_GENMASK_19(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_21(N, op, x, ...) ((op(N, 20, x)) | FLOG_GENMASK_20(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_22(N, op, x, ...) ((op(N, 21, x)) | FLOG_GENMASK_21(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_23(N, op, x, ...) ((op(N, 22, x)) | FLOG_GENMASK_22(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_24(N, op, x, ...) ((op(N, 23, x)) | FLOG_GENMASK_23(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_25(N, op, x, ...) ((op(N, 24, x)) | FLOG_GENMASK_24(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_26(N, op, x, ...) ((op(N, 25, x)) | FLOG_GENMASK_25(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_27(N, op, x, ...) ((op(N, 26, x)) | FLOG_GENMASK_26(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_28(N, op, x, ...) ((op(N, 27, x)) | FLOG_GENMASK_27(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_29(N, op, x, ...) ((op(N, 28, x)) | FLOG_GENMASK_28(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_30(N, op, x, ...) ((op(N, 29, x)) | FLOG_GENMASK_29(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_31(N, op, x, ...) ((op(N, 30, x)) | FLOG_GENMASK_30(N, op, __VA_ARGS__))
+#define FLOG_GENMASK_32(N, op, x, ...) ((op(N, 31, x)) | FLOG_GENMASK_31(N, op, __VA_ARGS__))
+
+#define FLOG_CONCAT(arg1, arg2) FLOG_CONCAT1(arg1, arg2)
+#define FLOG_CONCAT1(arg1, arg2) FLOG_CONCAT2(arg1, arg2)
+#define FLOG_CONCAT2(arg1, arg2) arg1##arg2
+
+#define FLOG_GENMASK_(N, op, ...) FLOG_CONCAT(FLOG_GENMASK_, N)(N, op, ##__VA_ARGS__)
+#define FLOG_GENMASK(op, ...) FLOG_GENMASK_(FLOG_PP_NARG(__VA_ARGS__), op, ##__VA_ARGS__)
+
+#define flog_genbit(ord, n, v, ...) \
+ _Generic((v), \
+ \
+ /* Basic types */ \
+ char: 0, \
+ signed char: 0, \
+ unsigned char: 0, \
+ signed short int: 0, \
+ unsigned short int: 0, \
+ signed int: 0, \
+ unsigned int: 0, \
+ signed long: 0, \
+ unsigned long: 0, \
+ signed long long: 0, \
+ unsigned long long: 0, \
+ \
+ /* Not used for a while */ \
+ /* float: 12, */ \
+ /* double: 13, */ \
+ /* long double: 14, */ \
+ \
+ /* Basic poniters */ \
+ char *: (1u << (ord - n - 1)), \
+ signed char *: (1u << (ord - n - 1)), \
+ unsigned char *: (1u << (ord - n - 1)), \
+ signed short int *: 0, \
+ unsigned short int *: 0, \
+ signed int *: 0, \
+ unsigned int *: 0, \
+ signed long *: 0, \
+ unsigned long *: 0, \
+ signed long long *: 0, \
+ unsigned long long *: 0, \
+ void *: 0, \
+ \
+ /* Const basic pointers */ \
+ const char *: (1u << (ord - n - 1)), \
+ const signed char *: (1u << (ord - n - 1)), \
+ const unsigned char *: (1u << (ord - n - 1)), \
+ const signed short int *: 0, \
+ const unsigned short int *: 0, \
+ const signed int *: 0, \
+ const unsigned int *: 0, \
+ const signed long *: 0, \
+ const unsigned long *: 0, \
+ const signed long long *: 0, \
+ const unsigned long long *: 0, \
+ const void *: 0, \
+ \
+ /* Systypes and pointers */ \
+ default: -1)
+
+typedef struct {
+ unsigned int magic;
+ unsigned int size;
+ unsigned int nargs;
+ unsigned int mask;
+ long fmt;
+ long args[0];
+} flog_msg_t;
+
+extern int flog_encode_msg(int fdout, unsigned int nargs, unsigned int mask, const char *format, ...);
+void flog_decode_msg(int fdout, const char *format, ...);
+extern int flog_decode_all(int fdin, int fdout);
+
+#define flog_encode(fdout, fmt, ...) \
+ flog_encode_msg(fdout, FLOG_PP_NARG(__VA_ARGS__), \
+ FLOG_GENMASK(flog_genbit, ##__VA_ARGS__), fmt, ##__VA_ARGS__)
+
+int flog_map_buf(int fdout);
+int flog_close(int fdout);
+
+#endif /* __UAPI_FLOG_H__ */
diff --git a/flog/include/util.h b/flog/include/util.h
new file mode 100644
index 000000000..17a4d7799
--- /dev/null
+++ b/flog/include/util.h
@@ -0,0 +1,37 @@
+#ifndef __UTIL_H__
+#define __UTIL_H__
+
+#include <string.h>
+#include <errno.h>
+
+#include "log.h"
+#include "types.h"
+
+#define __xalloc(op, size, ...) \
+ ({ \
+ void *___p = op(__VA_ARGS__); \
+ ___p; \
+ })
+
+#define xstrdup(str) __xalloc(strdup, strlen(str) + 1, str)
+#define xmalloc(size) __xalloc(malloc, size, size)
+#define xzalloc(size) __xalloc(calloc, size, 1, size)
+#define xrealloc(p, size) __xalloc(realloc, size, p, size)
+
+#define xfree(p) do { if (p) free(p); } while (0)
+
+#define xrealloc_safe(pptr, size) \
+ ({ \
+ int __ret = -ENOMEM; \
+ void *new = xrealloc(*pptr, size); \
+ if (new) { \
+ *pptr = new; \
+ __ret = 0; \
+ } \
+ __ret; \
+ })
+
+#define memzero_p(p) memset(p, 0, sizeof(*p))
+#define memzero(p, size) memset(p, 0, size)
+
+#endif /* __UTIL_H__ */
diff --git a/flog/src/Makefile b/flog/src/Makefile
new file mode 100644
index 000000000..ee73ea725
--- /dev/null
+++ b/flog/src/Makefile
@@ -0,0 +1,5 @@
+ccflags-y += -DCONFIG_X86_64 -iquote ./include $(OPTS)
+ldflags-y += -r
+
+#obj-y += main.o
+obj-y += flog.o
diff --git a/flog/src/flog.c b/flog/src/flog.c
new file mode 100644
index 000000000..533625de6
--- /dev/null
+++ b/flog/src/flog.c
@@ -0,0 +1,215 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+
+//#include <ffi.h>
+
+#include "uapi/flog.h"
+#include "util.h"
+
+#define MAGIC 0xABCDABCD
+
+#define BUF_SIZE (1<<20)
+static char _mbuf[BUF_SIZE];
+static char *mbuf = _mbuf;
+static char *fbuf;
+static uint64_t fsize;
+static uint64_t mbuf_size = sizeof(_mbuf);
+
+/*int flog_decode_all(int fdin, int fdout)
+{
+ flog_msg_t *m = (void *)mbuf;
+ ffi_type *args[34] = {
+ [0] = &ffi_type_sint,
+ [1] = &ffi_type_pointer,
+ [2 ... 33] = &ffi_type_slong
+ };
+ void *values[34];
+ ffi_cif cif;
+ ffi_arg rc;
+ size_t i, ret;
+ char *fmt;
+
+ values[0] = (void *)&fdout;
+
+ while (1) {
+ ret = read(fdin, mbuf, sizeof(m));
+ if (ret == 0)
+ break;
+ if (ret < 0) {
+ fprintf(stderr, "Unable to read a message: %m");
+ return -1;
+ }
+ if (m->magic != MAGIC) {
+ fprintf(stderr, "The log file was not properly closed\n");
+ break;
+ }
+ ret = m->size - sizeof(m);
+ if (m->size > mbuf_size) {
+ fprintf(stderr, "The buffer is too small");
+ return -1;
+ }
+ if (read(fdin, mbuf + sizeof(m), ret) != ret) {
+ fprintf(stderr, "Unable to read a message: %m");
+ return -1;
+ }
+
+ fmt = mbuf + m->fmt;
+ values[1] = &fmt;
+
+ for (i = 0; i < m->nargs; i++) {
+ values[i + 2] = (void *)&m->args[i];
+ if (m->mask & (1u << i)) {
+ m->args[i] = (long)(mbuf + m->args[i]);
+ }
+ }
+
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, m->nargs + 2,
+ &ffi_type_sint, args) == FFI_OK)
+ ffi_call(&cif, FFI_FN(dprintf), &rc, values);
+ }
+ return 0;
+}*/
+
+static int flog_enqueue(flog_msg_t *m)
+{
+ if (write(1, m, m->size) != m->size) {
+ fprintf(stderr, "Unable to write a message\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*extern char *rodata_start;
+extern char *rodata_end;
+*/
+/* Pre-allocate a buffer in a file and map it into memory. */
+int flog_map_buf(int fdout)
+{
+ uint64_t off = 0;
+ void *addr;
+
+ /*
+ * Two buffers are mmaped into memory. A new one is mapped when a first
+ * one is completly filled.
+ */
+ if (fbuf && (mbuf - fbuf < BUF_SIZE))
+ return 0;
+
+ if (fbuf) {
+ if (munmap(fbuf, BUF_SIZE * 2)) {
+ fprintf(stderr, "Unable to unmap a buffer: %m");
+ return -1;
+ }
+ off = mbuf - fbuf - BUF_SIZE;
+ fbuf = NULL;
+ }
+
+ if (fsize == 0)
+ fsize += BUF_SIZE;
+ fsize += BUF_SIZE;
+
+ if (ftruncate(fdout, fsize)) {
+ fprintf(stderr, "Unable to truncate a file: %m");
+ return -1;
+ }
+
+ if (!fbuf)
+ addr = mmap(NULL, BUF_SIZE * 2, PROT_WRITE | PROT_READ,
+ MAP_FILE | MAP_SHARED, fdout, fsize - 2 * BUF_SIZE);
+ else
+ addr = mremap(fbuf + BUF_SIZE, BUF_SIZE,
+ BUF_SIZE * 2, MREMAP_FIXED, fbuf);
+ if (addr == MAP_FAILED) {
+ fprintf(stderr, "Unable to map a buffer: %m");
+ return -1;
+ }
+
+ fbuf = addr;
+ mbuf = fbuf + off;
+ mbuf_size = 2 * BUF_SIZE;
+
+ return 0;
+}
+
+int flog_close(int fdout)
+{
+ if (mbuf == _mbuf)
+ return 0;
+
+ munmap(fbuf, BUF_SIZE * 2);
+
+ if (ftruncate(fdout, fsize - 2 * BUF_SIZE + mbuf - fbuf)) {
+ fprintf(stderr, "Unable to truncate a file: %m");
+ return -1;
+ }
+ return 0;
+}
+
+int flog_encode_msg(int fdout, unsigned int nargs, unsigned int mask, const char *format, ...)
+{
+ flog_msg_t *m;
+ va_list argptr;
+ char *str_start, *p;
+ size_t i;
+
+ if (mbuf != _mbuf && flog_map_buf(fdout))
+ return -1;
+
+ m = (void *) mbuf;
+
+ m->nargs = nargs;
+ m->mask = mask;
+
+ str_start = (void *)m->args + sizeof(m->args[0]) * nargs;
+ p = memccpy(str_start, format, 0, mbuf_size - (str_start - mbuf));
+ if (p == NULL) {
+ fprintf(stderr, "No memory for string argument\n");
+ return -1;
+ }
+ m->fmt = str_start - mbuf;
+ str_start = p;
+
+ va_start(argptr, format);
+ for (i = 0; i < nargs; i++) {
+ m->args[i] = (long)va_arg(argptr, long);
+ /*
+ * If we got a string, we should either
+ * reference it when in rodata, or make
+ * a copy (FIXME implement rodata refs).
+ */
+ if (mask & (1u << i)) {
+ p = memccpy(str_start, (void *)m->args[i], 0, mbuf_size - (str_start - mbuf));
+ if (p == NULL) {
+ fprintf(stderr, "No memory for string argument\n");
+ return -1;
+ }
+ m->args[i] = str_start - mbuf;
+ str_start = p;
+ }
+ }
+ va_end(argptr);
+ m->size = str_start - mbuf;
+
+ /*
+ * A magic is required to know where we stop writing into a log file,
+ * if it was not properly closed. The file is mapped into memory, so a
+ * space in the file is allocated in advance and at the end it can have
+ * some unused tail.
+ */
+ m->magic = MAGIC;
+
+ m->size = roundup(m->size, 8);
+ if (mbuf == _mbuf) {
+ if (flog_enqueue(m))
+ return -1;
+ } else {
+ mbuf += m->size;
+ mbuf_size -= m->size;
+ }
+ return 0;
+}
diff --git a/flog/src/main.c b/flog/src/main.c
new file mode 100644
index 000000000..c84e77478
--- /dev/null
+++ b/flog/src/main.c
@@ -0,0 +1,170 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "flog.h"
+
+extern char _rodata_start, _rodata_end;
+char *rodata_start = &_rodata_start;
+char *rodata_end = &_rodata_end;
+
+enum {
+ MODE_BINARY,
+ MODE_FPRINTF,
+ MODE_SPRINTF,
+ MODE_DPRINTF,
+};
+
+int main(int argc, char *argv[])
+{
+ static const char str1[] = "String1 String1";
+ static const char str2[] = "string2 string2 string2";
+ int fdout = STDOUT_FILENO;
+ bool use_decoder = false;
+ int mode = MODE_BINARY;
+ size_t niter = 100;
+ int opt, idx;
+ size_t i;
+
+ static const char short_opts[] = "m:o:di:h";
+ static struct option long_opts[] = {
+ { "mode", required_argument, 0, 'm' },
+ { "output", required_argument, 0, 'o' },
+ { "decode", no_argument, 0, 'd' },
+ { "iter", required_argument, 0, 'i' },
+ { "help", no_argument, 0, 'h' },
+ { },
+ };
+
+ while (1) {
+ idx = -1;
+ opt = getopt_long(argc, argv, short_opts, long_opts, &idx);
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'm':
+ if (strcmp(optarg, "binary") == 0) {
+ mode = MODE_BINARY;
+ } else if (strcmp(optarg, "fprintf") == 0) {
+ mode = MODE_FPRINTF;
+ } else if (strcmp(optarg, "sprintf") == 0) {
+ mode = MODE_SPRINTF;
+ } else if (strcmp(optarg, "dprintf") == 0) {
+ mode = MODE_DPRINTF;
+ } else
+ goto usage;
+ break;
+ case 'o':
+ if (strcmp(optarg, "stdout") == 0) {
+ fdout = fileno(stdout);
+ } else if (strcmp(optarg, "stderr") == 0) {
+ fdout = fileno(stderr);
+ } else {
+ fdout = open(optarg, O_RDWR | O_CREAT | O_TRUNC, 0644);
+ if (fdout < 0) {
+ fprintf(stderr, "Can't open %s: %s\n",
+ optarg, strerror(errno));
+ exit(1);
+ }
+ }
+ break;
+ case 'i':
+ niter = atoi(optarg);
+ break;
+ case 'd':
+ use_decoder = true;
+ break;
+ case 'h':
+ default:
+ goto usage;
+ }
+ }
+
+ switch (mode) {
+ case MODE_BINARY:
+ if (use_decoder)
+ return flog_decode_all(STDIN_FILENO, fdout);
+
+ if (fdout != STDOUT_FILENO && flog_map_buf(fdout))
+ return 1;
+ for (i = 0; i < niter; i++)
+ if (flog_encode(fdout, "Some message %s %s %c %li %d %lu\n",
+ str1, str2, 'c', (long)-4, (short)2,
+ (unsigned long)2))
+ return 1;
+ if (flog_close(fdout))
+ return 1;
+ break;
+ case MODE_DPRINTF:
+ {
+ for (i = 0; i < niter; i++) {
+ dprintf(fdout, "Some message %s %s %c %li %d %lu\n",
+ str1, str2, 'c', (long)-4, (short)2,
+ (unsigned long)2);
+ }
+ break;
+ }
+ case MODE_FPRINTF:
+ {
+ FILE *f = fdopen(fdout, "w");
+
+ for (i = 0; i < niter; i++) {
+ fprintf(f, "Some message %s %s %c %li %d %lu\n",
+ str1, str2, 'c', (long)-4, (short)2,
+ (unsigned long)2);
+ fflush(f);
+ }
+ fclose(f);
+ break;
+ }
+ case MODE_SPRINTF:
+ {
+ static char buf[4096];
+
+ for (i = 0; i < niter; i++) {
+ sprintf(buf, "Some message %s %s %c %li %d %lu\n",
+ str1, str2, 'c', (long)-4, (short)2,
+ (unsigned long)2);
+ }
+ break;
+ }
+ default:
+ return 1;
+ }
+
+ return 0;
+usage:
+ fprintf(stderr,
+ "flog [--mode binary|dprintf] [--output stdout|stderr|filename] [--decode] [--iter number]\n"
+ "\n"
+
+ "Examples:\n"
+ "\n"
+
+ " - run 100000 iterations of instant message processing (immediate dprintf calls)\n"
+ "\n"
+ " flog -m dprintf -i 100000\n"
+ "\n"
+
+ " - run 100000 iterations in binary mode without processing (queue messages only)\n"
+ "\n"
+ " flog -i 100000\n"
+ "\n"
+
+ " - run 100000 iterations in binary mode with decoding after\n"
+ "\n"
+ " flog -i 100000 -d\n"
+ "\n"
+
+ " - run 100000 iterations in binary mode with decoding after, writting results into 'out' file\n"
+ "\n"
+ " flog -i 100000 -d -o out\n"
+ "\n");
+ return 1;
+}
diff --git a/flog/tests/test00 b/flog/tests/test00
new file mode 100755
index 000000000..a7937e4a1
--- /dev/null
+++ b/flog/tests/test00
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+set -e -x
+
+echo Map a log file into memory
+time ./flog run -i 1000000 -o /tmp/flog.raw.map
+echo Write into a log file
+time ./flog run -i 1000000 > /tmp/flog.raw
+echo Use fprintf
+time ./flog run -m fprintf -i 1000000 -o /tmp/flog.fprintf.txt
+echo Use dprintf
+time ./flog run -m dprintf -i 1000000 -o /tmp/flog.dprintf.txt
+echo Use sprintf
+time ./flog run -m sprintf -i 1000000
+
+time ./flog run -d < /tmp/flog.raw > /tmp/flog.raw.txt
+cmp /tmp/flog.raw.txt /tmp/flog.fprintf.txt
+
+time ./flog run -d < /tmp/flog.raw.map > /tmp/flog.raw.map.txt
+cmp /tmp/flog.raw.map.txt /tmp/flog.fprintf.txt
+
+cmp /tmp/flog.dprintf.txt /tmp/flog.fprintf.txt