/* we have 4 buffer-wait queues, in highest to lowest emergency order */
#define DYNBUF_NBQ 4
+/* execution context, for tracing resource usage or warning origins */
+enum thread_exec_ctx_type {
+ TH_EX_CTX_NONE = 0, /* context not filled */
+ TH_EX_CTX_OTHER, /* context only known by a generic pointer */
+};
+
+struct thread_exec_ctx {
+ enum thread_exec_ctx_type type;
+ /* 32-bit hole here on 64-bit platforms */
+ union {
+ const void *pointer; /* generic pointer (for other) */
+ };
+};
+
/* Thread group information. This defines a base and a count of global thread
* IDs which belong to it, and which can be looked up into thread_info/ctx. It
* is set up during parsing and is stable during operation. Thread groups start
uint64_t curr_mono_time; /* latest system wide monotonic time (leaving poll) */
ulong lock_history; /* history of used locks, see thread.h for more details */
-
- /* around 56 unused bytes here */
+ struct thread_exec_ctx exec_ctx; /* current execution context when known, or NULL */
// fourth cache line here on 64 bits: accessed mostly using atomic ops
ALWAYS_ALIGN(64);
ts->rel[i] = 0;
}
+/* switches the current execution context to <ctx> and returns the previous one
+ * so that this may even be used to save and restore. Setting EXEC_CTX_NONE
+ * resets it. It's efficient because it uses a pair of registers on input and
+ * output.
+ */
+static inline struct thread_exec_ctx switch_exec_ctx(const struct thread_exec_ctx ctx)
+{
+ const struct thread_exec_ctx prev = th_ctx->exec_ctx;
+
+ th_ctx->exec_ctx = ctx;
+ return prev;
+}
+
+/* used to reset the execution context */
+#define EXEC_CTX_NONE ((struct thread_exec_ctx){ .type = 0, .pointer = NULL })
+
+/* make an execution context from a type and a pointer */
+#define EXEC_CTX_MAKE(_type, _pointer) ((struct thread_exec_ctx){ .type = (_type), .pointer = (_pointer) })
+
+/* execute expression <expr> under context <new_ctx> then restore the previous
+ * one, and return the expression's return value.
+ */
+#define EXEC_CTX_WITH_RET(new_ctx, expr) ({ \
+ const struct thread_exec_ctx __prev_ctx = switch_exec_ctx(new_ctx); \
+ typeof(expr) __ret = (expr); \
+ switch_exec_ctx(__prev_ctx); \
+ __ret; \
+})
+
+/* execute expression <expr> under context <new_ctx> then restore the previous
+ * one. This one has no return value.
+ */
+#define EXEC_CTX_NO_RET(new_ctx, expr) do { \
+ const struct thread_exec_ctx __prev_ctx = switch_exec_ctx(new_ctx); \
+ do { expr; } while (0); \
+ switch_exec_ctx(__prev_ctx); \
+} while (0)
+
#endif /* _HAPROXY_TINFO_H */