diff --git a/include/haproxy/tinfo-t.h b/include/haproxy/tinfo-t.h index dc713cc1f..9e0b950e1 100644 --- a/include/haproxy/tinfo-t.h +++ b/include/haproxy/tinfo-t.h @@ -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); diff --git a/include/haproxy/tinfo.h b/include/haproxy/tinfo.h index a6497f558..ba9f21b61 100644 --- a/include/haproxy/tinfo.h +++ b/include/haproxy/tinfo.h @@ -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 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 under context 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 under context 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 */