#ifndef _BIRD_BIRDLIB_H_
#define _BIRD_BIRDLIB_H_
+#include <stddef.h>
+#include <setjmp.h>
+
+#include "sysdep/config.h"
#include "lib/alloca.h"
+#include "lib/macro.h"
+
+ #include <stdarg.h>
+
/* Ugly structure offset handling macros */
-struct align_probe { char x; long int y; };
+#define SAME_TYPE(a, b) ({ int _ = ((a) != (b)); !_; })
+#define TYPE_CAST(from, to, what) ( SAME_TYPE(((from) NULL), (what)), ((to) (what)))
+#ifdef offsetof
+#define OFFSETOF offsetof
+#else
#define OFFSETOF(s, i) ((size_t) &((s *)0)->i)
-#define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i)))
+#endif
+
+#define SKIP_BACK(s, i, p) ({ \
+ typeof(p) _orig = p; \
+ s *_ptr = ((s *)((char *)_orig - OFFSETOF(s, i))); \
+ SAME_TYPE(&_ptr->i, _orig); \
+ _ptr; })
+#define SKIP_BACK_DECLARE(s, n, i, p) s *n = SKIP_BACK(s, i, p)
#define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1))
-#define CPU_STRUCT_ALIGN (sizeof(struct align_probe))
+#define BIRD_SET_ALIGNED_POINTER(ptr, val) do { \
+ size_t _alignment = _Alignof(typeof(*ptr)); \
+ ptr = (typeof(ptr)) BIRD_ALIGN((uintptr_t)(val), _alignment); \
+} while (0)
+#define CPU_STRUCT_ALIGN (MAX_(_Alignof(void*), _Alignof(u64)))
+#define BIRD_CPU_ALIGN(s) BIRD_ALIGN((s), CPU_STRUCT_ALIGN)
+
+/* Structure item alignment macros */
+
+#define PADDING_NAME(id) _padding_##id
+#define PADDING_(id, sz) u8 PADDING_NAME(id)[sz]
+
+#if CPU_POINTER_ALIGNMENT == 4
+#define PADDING(id, n32, n64) PADDING_(id, n32)
+#elif CPU_POINTER_ALIGNMENT == 8
+#define PADDING(id, n32, n64) PADDING_(id, n64)
+#else
+#error "Strange CPU pointer alignment: " CPU_POINTER_ALIGNMENT
+#endif
/* Utility macros */
int buffer_vprint(buffer *buf, const char *fmt, va_list args);
- static void
+void
+log_prepare(log_buffer *buf, int class)
+{
+ buf->class = class;
+
+ buf->buf.start = buf->buf.pos = buf->block;
+ buf->buf.end = buf->block + sizeof buf->block;
+
+ int lf = atomic_load_explicit(&logging_flags, memory_order_acquire);
+
+ buf->pos[LBP_TIMESTAMP] = buf->buf.pos;
+ if (BIT32_TEST(&lf, LBP_TIMESTAMP))
+ {
+ rcu_read_lock();
+ const char *fmt = atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_log.fmt1;
+ int t = tm_format_real_time(buf->buf.pos, buf->buf.end - buf->buf.pos, fmt, current_real_time());
+ rcu_read_unlock();
+ if (t)
+ buf->buf.pos += t;
+ else
+ buffer_puts(&buf->buf, "<time format error>");
+
+ *(buf->buf.pos++) = ' ';
+ }
+
+ buf->pos[LBP_UDP_HEADER] = buf->buf.pos;
+ if (BIT32_TEST(&lf, LBP_UDP_HEADER))
+ {
+ /* Legacy RFC 3164 format, but with us precision */
+ buffer_print(&buf->buf, "<%d>", LOG_DAEMON | syslog_priorities[class]);
+
+ const char *fmt = "%b %d %T.%6f";
+ int t = tm_format_real_time(buf->buf.pos, buf->buf.end - buf->buf.pos, fmt, current_real_time());
+ if (t)
+ buf->buf.pos += t;
+ else
+ buffer_puts(&buf->buf, "<time format error>");
+
+ rcu_read_lock();
+ const char *hostname = atomic_load_explicit(&global_runtime, memory_order_acquire)->hostname ?: "<none>";
+ buffer_print(&buf->buf, " %s %s: ", hostname, bird_name);
+ rcu_read_unlock();
+ }
+
+ buf->pos[LBP_THREAD_ID] = buf->buf.pos;
+ if (BIT32_TEST(&lf, LBP_THREAD_ID))
+ buffer_print(&buf->buf, "[%04x] ", THIS_THREAD_ID);
+
+ buf->pos[LBP_CLASS] = buf->buf.pos;
+ if (BIT32_TEST(&lf, LBP_CLASS))
+ buffer_print(&buf->buf, "<%s> ", class_names[class]);
+
+ buf->pos[LBP_MSG] = buf->buf.pos;
+}
+
+ void
vlog(int class, const char *msg, va_list args)
{
- buffer buf;
- LOG_BUFFER_INIT(buf);
- buffer_vprint(&buf, msg, args);
- log_commit(class, &buf);
+ static _Thread_local log_buffer buf;
+
+ /* No logging at all if nobody would receive the message either */
+ if (!(atomic_load_explicit(&logging_mask, memory_order_acquire) & (1 << class)))
+ return;
+
+ log_prepare(&buf, class);
+ buffer_vprint(&buf.buf, msg, args);
+ log_commit(&buf);
}