]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tinfo: start to add basic thread_exec_ctx
authorWilly Tarreau <w@1wt.eu>
Tue, 3 Mar 2026 08:37:10 +0000 (09:37 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 12 Mar 2026 17:06:37 +0000 (18:06 +0100)
We have the struct made of a type and a pointer in the th_ctx and a
function to switch it for the current thread. Two macros are provided
to enclose a callee within a temporary context. For now only type OTHER
is supported (only a generic pointer).

include/haproxy/tinfo-t.h
include/haproxy/tinfo.h

index dc713cc1f48f0ccb5da33b7d28ee894ad1d944df..9e0b950e17c436d6b8083bdf0d63a32c67630104 100644 (file)
@@ -75,6 +75,20 @@ enum {
 /* 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
@@ -172,8 +186,7 @@ struct thread_ctx {
        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);
index a6497f558561f2253d8cbdaebd58f3af52be6548..ba9f21b618c039aa2224d204e024c86b5ea7d0e6 100644 (file)
@@ -117,4 +117,42 @@ static inline void thread_set_pin_grp1(struct thread_set *ts, ulong mask)
                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 */