From 3de38e3991fc89141bdccb18b5fce32d5e7b2782 Mon Sep 17 00:00:00 2001 From: Utz-Uwe Haus <uhaus@cray.com> Date: Tue, 2 Mar 2021 18:21:46 +0100 Subject: [PATCH] Ensure mstro_cdo_state_describe() uses ringbuffer This fixes #121, where the state updates (which print two states in one log statement) always got the second description wrong. --- include/maestro/i_cdo.h | 9 ++++++++- maestro/cdo.c | 20 ++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/maestro/i_cdo.h b/include/maestro/i_cdo.h index d4e2fbd4..93f20dab 100644 --- a/include/maestro/i_cdo.h +++ b/include/maestro/i_cdo.h @@ -156,7 +156,14 @@ typedef uint32_t mstro_cdo_state; /** The NIL UUID */ #define MSTRO_CDO_ID_INVALID { .id = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 } } -/** return a string describing the CDO state @arg s */ +/** return a string describing the CDO state @arg s + ** + ** The string is owned by this function, but this function can safely + ** be called from multiple threads (the buffer is thread-local). The + ** buffer will be re-used by subsequent calls in the same thread + ** after a small number of invocations (currently: 3, see @ref + ** MAX_STATE_DESCRIPTION_BUFFERS). + **/ const char * mstro_cdo_state_describe(mstro_cdo_state s); diff --git a/maestro/cdo.c b/maestro/cdo.c index 867151da..8ec685e4 100644 --- a/maestro/cdo.c +++ b/maestro/cdo.c @@ -1633,22 +1633,34 @@ struct { /** a reasonably safe way to count the number of entries in an array of structures */ #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +/** we support this many concurrent state buffers in flight per + * thread. Hideous, but callers typically will use this function in a + * PRINT statement, with up to two states (to compare them) at most + */ + +#define MAX_STATE_DESCRIPTION_BUFFERS 3 const char * mstro_cdo_state_describe(mstro_cdo_state s) { - static _Thread_local char buf[sizeof(states_and_names)]; + static _Thread_local char buf[MAX_STATE_DESCRIPTION_BUFFERS][sizeof(states_and_names)]; + static _Thread_local size_t bufid = 0; - buf[0]='\0'; + // switch to new buffer + bufid = (bufid+1) % MAX_STATE_DESCRIPTION_BUFFERS; + + buf[bufid][0]='\0'; if(s==MSTRO_CDO_STATE_INVALID) return "INVALID"; else { for(size_t i=0; i<COUNT_OF(states_and_names); i++) { if(s&states_and_names[i].state) { - strcat(buf, states_and_names[i].name); + strcat(buf[bufid], states_and_names[i].name); } } - return buf+1; /* cut off leading '|' we put there for simplicity + + return buf[bufid]+1; /* cut off leading '|' we put there for simplicity * of the loop above */ } } -- GitLab