Merge branch 'ds/trace2-tolerate-failed-timestamp' into seen
Functions like `xstrfmt()` and `xcalloc()` have been banned from use in the trace2 API codebase to prevent calls to `die()` which lead to unwanted process exits and recursion when memory allocation fails. * ds/trace2-tolerate-failed-timestamp: trace2: remove use of xcalloc() trace2: remove use of ALLOC_GROW() trace2: remove use of xstrfmt() trace2: remove use of ALLOC_ARRAY() trace2: remove use of xstrdup() trace2: tolerate failed timestamp formatting banned-die: create header for banning of functionsseen
commit
075cd7bce4
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef BANNED_DIE_H
|
||||
#define BANNED_DIE_H
|
||||
|
||||
#include "banned.h"
|
||||
|
||||
/*
|
||||
* This header lists functions that must not be used by low-level APIs
|
||||
* because they can cause Git to terminate.
|
||||
*/
|
||||
|
||||
#undef die
|
||||
#define die BANNED(die)
|
||||
|
||||
#undef xsnprintf
|
||||
#define xsnprintf(...) BANNED(xsnprintf)
|
||||
|
||||
#undef xstrdup
|
||||
#define xstrdup(str) BANNED(xstrdup)
|
||||
|
||||
#undef xcalloc
|
||||
#define xcalloc(nmemb, size) BANNED(xcalloc)
|
||||
|
||||
#undef xstrfmt
|
||||
#define xstrfmt(...) BANNED(xstrfmt)
|
||||
|
||||
#undef ALLOC_ARRAY
|
||||
#define ALLOC_ARRAY(x, alloc) BANNED(ALLOC_ARRAY)
|
||||
|
||||
#undef ALLOC_GROW
|
||||
#define ALLOC_GROW(x, nr, alloc) BANNED(ALLOC_GROW)
|
||||
|
||||
#endif /* BANNED_DIE_H */
|
||||
|
|
@ -332,7 +332,8 @@ test_expect_success 'unsafe URLs are redacted by default in cmd_start events' '
|
|||
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||
test-tool trace2 300redact_start git clone https://user:pwd@example.com/ clone2 &&
|
||||
test_grep ! user:pwd trace.event
|
||||
test_grep ! user:pwd trace.event &&
|
||||
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||
'
|
||||
|
||||
test_expect_success 'unsafe URLs are redacted by default in child_start events' '
|
||||
|
|
@ -341,7 +342,8 @@ test_expect_success 'unsafe URLs are redacted by default in child_start events'
|
|||
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||
test-tool trace2 301redact_child_start git clone https://user:pwd@example.com/ clone2 &&
|
||||
test_grep ! user:pwd trace.event
|
||||
test_grep ! user:pwd trace.event &&
|
||||
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||
'
|
||||
|
||||
test_expect_success 'unsafe URLs are redacted by default in exec events' '
|
||||
|
|
@ -350,7 +352,8 @@ test_expect_success 'unsafe URLs are redacted by default in exec events' '
|
|||
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||
test-tool trace2 302redact_exec git clone https://user:pwd@example.com/ clone2 &&
|
||||
test_grep ! user:pwd trace.event
|
||||
test_grep ! user:pwd trace.event &&
|
||||
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||
'
|
||||
|
||||
test_expect_success 'unsafe URLs are redacted by default in def_param events' '
|
||||
|
|
@ -359,7 +362,8 @@ test_expect_success 'unsafe URLs are redacted by default in def_param events' '
|
|||
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||
test-tool trace2 303redact_def_param url https://user:pwd@example.com/ &&
|
||||
test_grep ! user:pwd trace.event
|
||||
test_grep ! user:pwd trace.event &&
|
||||
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
|||
52
trace2.c
52
trace2.c
|
|
@ -17,6 +17,8 @@
|
|||
#include "trace2/tr2_tgt.h"
|
||||
#include "trace2/tr2_tls.h"
|
||||
#include "trace2/tr2_tmr.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
static int trace2_enabled;
|
||||
static int trace2_redact = 1;
|
||||
|
|
@ -259,7 +261,10 @@ int trace2_is_enabled(void)
|
|||
static const char *redact_arg(const char *arg)
|
||||
{
|
||||
const char *p, *colon;
|
||||
const char *redact = ":<REDACTED>";
|
||||
char *redacted;
|
||||
size_t at;
|
||||
size_t prefix_len, suffix_len, redacted_len, redact_len;
|
||||
|
||||
if (!trace2_redact ||
|
||||
(!skip_prefix(arg, "https://", &p) &&
|
||||
|
|
@ -274,7 +279,25 @@ static const char *redact_arg(const char *arg)
|
|||
if (!colon)
|
||||
return arg;
|
||||
|
||||
return xstrfmt("%.*s:<REDACTED>%s", (int)(colon - arg), arg, p + at);
|
||||
redact_len = strlen(redact);
|
||||
prefix_len = colon - arg;
|
||||
suffix_len = strlen(p + at);
|
||||
|
||||
if (unsigned_add_overflows(prefix_len, suffix_len) ||
|
||||
unsigned_add_overflows(prefix_len + suffix_len, redact_len) ||
|
||||
unsigned_add_overflows(prefix_len + suffix_len + redact_len, 1))
|
||||
return NULL;
|
||||
|
||||
redacted_len = prefix_len + suffix_len + redact_len + 1;
|
||||
|
||||
redacted = malloc(redacted_len);
|
||||
if (!redacted)
|
||||
return NULL;
|
||||
|
||||
memcpy(redacted, arg, prefix_len);
|
||||
memcpy(redacted + prefix_len, redact, redact_len);
|
||||
memcpy(redacted + prefix_len + redact_len, p + at, suffix_len + 1);
|
||||
return redacted;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -299,11 +322,17 @@ static const char **redact_argv(const char **argv)
|
|||
|
||||
if (!argv[i])
|
||||
return argv;
|
||||
if (!redacted)
|
||||
return NULL;
|
||||
|
||||
for (j = 0; argv[j]; j++)
|
||||
; /* keep counting */
|
||||
|
||||
ALLOC_ARRAY(ret, j + 1);
|
||||
ret = calloc(j + 1, sizeof(*ret));
|
||||
if (!ret) {
|
||||
free((char *)redacted);
|
||||
return NULL;
|
||||
}
|
||||
ret[j] = NULL;
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
|
|
@ -311,7 +340,14 @@ static const char **redact_argv(const char **argv)
|
|||
ret[i] = redacted;
|
||||
for (++i; argv[i]; i++) {
|
||||
redacted = redact_arg(argv[i]);
|
||||
ret[i] = redacted ? redacted : argv[i];
|
||||
if (!redacted) {
|
||||
for (j = 0; j < i; j++)
|
||||
if (ret[j] != argv[j])
|
||||
free((void *)ret[j]);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret[i] = redacted;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -344,6 +380,8 @@ void trace2_cmd_start_fl(const char *file, int line, const char **argv)
|
|||
us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
|
||||
|
||||
redacted = redact_argv(argv);
|
||||
if (!redacted)
|
||||
return;
|
||||
|
||||
for_each_wanted_builtin (j, tgt_j)
|
||||
if (tgt_j->pfn_start_fl)
|
||||
|
|
@ -512,6 +550,7 @@ void trace2_child_start_fl(const char *file, int line,
|
|||
uint64_t us_now;
|
||||
uint64_t us_elapsed_absolute;
|
||||
const char **orig_argv = cmd->args.v;
|
||||
const char **redacted;
|
||||
|
||||
if (!trace2_enabled)
|
||||
return;
|
||||
|
|
@ -529,7 +568,10 @@ void trace2_child_start_fl(const char *file, int line,
|
|||
* temporarily replace the original argv (inside the `strvec`)
|
||||
* with a possibly redacted version.
|
||||
*/
|
||||
cmd->args.v = redact_argv(orig_argv);
|
||||
redacted = redact_argv(orig_argv);
|
||||
if (!redacted)
|
||||
return;
|
||||
cmd->args.v = redacted;
|
||||
|
||||
for_each_wanted_builtin (j, tgt_j)
|
||||
if (tgt_j->pfn_child_start_fl)
|
||||
|
|
@ -621,6 +663,8 @@ int trace2_exec_fl(const char *file, int line, const char *exe,
|
|||
exec_id = tr2tls_locked_increment(&tr2_next_exec_id);
|
||||
|
||||
redacted = redact_argv(argv);
|
||||
if (!redacted)
|
||||
return exec_id;
|
||||
|
||||
for_each_wanted_builtin (j, tgt_j)
|
||||
if (tgt_j->pfn_exec_fl)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include "trace2/tr2_cfg.h"
|
||||
#include "trace2/tr2_sysenv.h"
|
||||
#include "wildmatch.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
static struct string_list tr2_cfg_patterns = STRING_LIST_INIT_DUP;
|
||||
static int tr2_cfg_loaded;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "git-compat-util.h"
|
||||
#include "strbuf.h"
|
||||
#include "trace2/tr2_cmd_name.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
#define TR2_ENVVAR_PARENT_NAME "GIT_TRACE2_PARENT_NAME"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include "trace2/tr2_tgt.h"
|
||||
#include "trace2/tr2_tls.h"
|
||||
#include "trace2/tr2_ctr.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
/*
|
||||
* A global counter block to aggregate values from the partial sums
|
||||
|
|
@ -53,7 +55,11 @@ static struct tr2_counter_metadata tr2_counter_metadata[TRACE2_NUMBER_OF_COUNTER
|
|||
void tr2_counter_increment(enum trace2_counter_id cid, uint64_t value)
|
||||
{
|
||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
struct tr2_counter *c = &ctx->counter_block.counter[cid];
|
||||
struct tr2_counter *c;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
c = &ctx->counter_block.counter[cid];
|
||||
|
||||
c->value += value;
|
||||
|
||||
|
|
@ -67,6 +73,8 @@ void tr2_update_final_counters(void)
|
|||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
enum trace2_counter_id cid;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
if (!ctx->used_any_counter)
|
||||
return;
|
||||
|
||||
|
|
@ -88,6 +96,8 @@ void tr2_emit_per_thread_counters(tr2_tgt_evt_counter_t *fn_apply)
|
|||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
enum trace2_counter_id cid;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
if (!ctx->used_any_per_thread_counter)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include "trace2/tr2_dst.h"
|
||||
#include "trace2/tr2_sid.h"
|
||||
#include "trace2/tr2_sysenv.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
/*
|
||||
* How many attempts we will make at creating an automatically-named trace file.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "strbuf.h"
|
||||
#include "trace2/tr2_tbuf.h"
|
||||
#include "trace2/tr2_sid.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
#define TR2_ENVVAR_PARENT_SID "GIT_TRACE2_PARENT_SID"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "tr2_sysenv.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
/*
|
||||
* Each entry represents a trace2 setting.
|
||||
|
|
@ -73,7 +75,9 @@ static int tr2_sysenv_cb(const char *key, const char *value,
|
|||
if (!value)
|
||||
return config_error_nonbool(key);
|
||||
free(tr2_sysenv_settings[k].value);
|
||||
tr2_sysenv_settings[k].value = xstrdup(value);
|
||||
tr2_sysenv_settings[k].value = strdup(value);
|
||||
if (!tr2_sysenv_settings[k].value)
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +113,7 @@ const char *tr2_sysenv_get(enum tr2_sysenv_variable var)
|
|||
const char *v = getenv(tr2_sysenv_settings[var].env_var_name);
|
||||
if (v && *v) {
|
||||
free(tr2_sysenv_settings[var].value);
|
||||
tr2_sysenv_settings[var].value = xstrdup(v);
|
||||
tr2_sysenv_settings[var].value = strdup(v);
|
||||
}
|
||||
tr2_sysenv_settings[var].getenv_called = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,68 @@
|
|||
#include "git-compat-util.h"
|
||||
#include "tr2_tbuf.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
void tr2_tbuf_local_time(struct tr2_tbuf *tb)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm tm;
|
||||
struct timeval tv = { 0 };
|
||||
struct tm tm = { 0 };
|
||||
time_t secs;
|
||||
int len;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
secs = tv.tv_sec;
|
||||
localtime_r(&secs, &tm);
|
||||
|
||||
xsnprintf(tb->buf, sizeof(tb->buf), "%02d:%02d:%02d.%06ld", tm.tm_hour,
|
||||
tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||
len = snprintf(tb->buf, sizeof(tb->buf), "%02d:%02d:%02d.%06ld",
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||
|
||||
if (len < 0 || (size_t)len >= sizeof(tb->buf)) {
|
||||
const char *blank = "00:00:00.000000";
|
||||
strlcpy(tb->buf, blank, sizeof(tb->buf));
|
||||
}
|
||||
}
|
||||
|
||||
void tr2_tbuf_utc_datetime_extended(struct tr2_tbuf *tb)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm tm;
|
||||
struct timeval tv = { 0 };
|
||||
struct tm tm = { 0 };
|
||||
time_t secs;
|
||||
int len;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
secs = tv.tv_sec;
|
||||
gmtime_r(&secs, &tm);
|
||||
|
||||
xsnprintf(tb->buf, sizeof(tb->buf),
|
||||
"%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ", tm.tm_year + 1900,
|
||||
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||
(long)tv.tv_usec);
|
||||
len = snprintf(tb->buf, sizeof(tb->buf),
|
||||
"%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||
|
||||
if (len < 0 || (size_t)len >= sizeof(tb->buf)) {
|
||||
const char *blank = "1900-00-00T00:00:00.000000Z";
|
||||
strlcpy(tb->buf, blank, sizeof(tb->buf));
|
||||
}
|
||||
}
|
||||
|
||||
void tr2_tbuf_utc_datetime(struct tr2_tbuf *tb)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm tm;
|
||||
struct timeval tv = { 0 };
|
||||
struct tm tm = { 0 };
|
||||
time_t secs;
|
||||
int len;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
secs = tv.tv_sec;
|
||||
gmtime_r(&secs, &tm);
|
||||
|
||||
xsnprintf(tb->buf, sizeof(tb->buf), "%4d%02d%02dT%02d%02d%02d.%06ldZ",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
|
||||
tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||
len = snprintf(tb->buf, sizeof(tb->buf),
|
||||
"%4d%02d%02dT%02d%02d%02d.%06ldZ",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||
|
||||
if (len < 0 || (size_t)len >= sizeof(tb->buf)) {
|
||||
const char *blank = "19000000T000000.000000Z";
|
||||
strlcpy(tb->buf, blank, sizeof(tb->buf));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
#include "trace2/tr2_tgt.h"
|
||||
#include "trace2/tr2_tls.h"
|
||||
#include "trace2/tr2_tmr.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
static struct tr2_dst tr2dst_event = {
|
||||
.sysenv_var = TR2_SYSENV_EVENT,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include "trace2/tr2_tgt.h"
|
||||
#include "trace2/tr2_tls.h"
|
||||
#include "trace2/tr2_tmr.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
static struct tr2_dst tr2dst_normal = {
|
||||
.sysenv_var = TR2_SYSENV_NORMAL,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include "trace2/tr2_tgt.h"
|
||||
#include "trace2/tr2_tls.h"
|
||||
#include "trace2/tr2_tmr.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
static struct tr2_dst tr2dst_perf = {
|
||||
.sysenv_var = TR2_SYSENV_PERF,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "thread-utils.h"
|
||||
#include "trace.h"
|
||||
#include "trace2/tr2_tls.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
/*
|
||||
* Initialize size of the thread stack for nested regions.
|
||||
|
|
@ -12,6 +14,9 @@
|
|||
#define TR2_REGION_NESTING_INITIAL_SIZE (100)
|
||||
|
||||
static struct tr2tls_thread_ctx *tr2tls_thread_main;
|
||||
static struct tr2tls_thread_ctx tr2tls_thread_fallback = {
|
||||
.thread_name = "unknown",
|
||||
};
|
||||
static uint64_t tr2tls_us_start_process;
|
||||
|
||||
static pthread_mutex_t tr2tls_mutex;
|
||||
|
|
@ -36,16 +41,23 @@ void tr2tls_start_process_clock(void)
|
|||
struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_base_name,
|
||||
uint64_t us_thread_start)
|
||||
{
|
||||
struct tr2tls_thread_ctx *ctx = xcalloc(1, sizeof(*ctx));
|
||||
struct tr2tls_thread_ctx *ctx = calloc(1, sizeof(*ctx));
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (!ctx)
|
||||
goto fallback;
|
||||
|
||||
/*
|
||||
* Implicitly "tr2tls_push_self()" to capture the thread's start
|
||||
* time in array_us_start[0]. For the main thread this gives us the
|
||||
* application run time.
|
||||
*/
|
||||
ctx->alloc = TR2_REGION_NESTING_INITIAL_SIZE;
|
||||
ctx->array_us_start = (uint64_t *)xcalloc(ctx->alloc, sizeof(uint64_t));
|
||||
ctx->array_us_start = calloc(ctx->alloc, sizeof(uint64_t));
|
||||
if (!ctx->array_us_start) {
|
||||
free(ctx);
|
||||
goto fallback;
|
||||
}
|
||||
ctx->array_us_start[ctx->nr_open_regions++] = us_thread_start;
|
||||
|
||||
ctx->thread_id = tr2tls_locked_increment(&tr2_next_thread_id);
|
||||
|
|
@ -61,6 +73,10 @@ struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_base_name,
|
|||
pthread_setspecific(tr2tls_key, ctx);
|
||||
|
||||
return ctx;
|
||||
|
||||
fallback:
|
||||
pthread_setspecific(tr2tls_key, &tr2tls_thread_fallback);
|
||||
return &tr2tls_thread_fallback;
|
||||
}
|
||||
|
||||
struct tr2tls_thread_ctx *tr2tls_get_self(void)
|
||||
|
|
@ -83,6 +99,11 @@ struct tr2tls_thread_ctx *tr2tls_get_self(void)
|
|||
return ctx;
|
||||
}
|
||||
|
||||
int tr2tls_is_fallback(const struct tr2tls_thread_ctx *ctx)
|
||||
{
|
||||
return ctx == &tr2tls_thread_fallback;
|
||||
}
|
||||
|
||||
int tr2tls_is_main_thread(void)
|
||||
{
|
||||
if (!HAVE_THREADS)
|
||||
|
|
@ -99,6 +120,9 @@ void tr2tls_unset_self(void)
|
|||
|
||||
pthread_setspecific(tr2tls_key, NULL);
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
|
||||
free((char *)ctx->thread_name);
|
||||
free(ctx->array_us_start);
|
||||
free(ctx);
|
||||
|
|
@ -107,8 +131,36 @@ void tr2tls_unset_self(void)
|
|||
void tr2tls_push_self(uint64_t us_now)
|
||||
{
|
||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
uint64_t *new_array;
|
||||
size_t new_alloc;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
|
||||
if (ctx->nr_skipped_regions) {
|
||||
ctx->nr_skipped_regions++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->nr_open_regions >= ctx->alloc) {
|
||||
if (ctx->alloc >
|
||||
SIZE_MAX / (2 * sizeof(*ctx->array_us_start))) {
|
||||
ctx->nr_skipped_regions++;
|
||||
return;
|
||||
}
|
||||
new_alloc = ctx->alloc * 2;
|
||||
|
||||
new_array = realloc(ctx->array_us_start,
|
||||
new_alloc * sizeof(*ctx->array_us_start));
|
||||
if (!new_array) {
|
||||
ctx->nr_skipped_regions++;
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->array_us_start = new_array;
|
||||
ctx->alloc = new_alloc;
|
||||
}
|
||||
|
||||
ALLOC_GROW(ctx->array_us_start, ctx->nr_open_regions + 1, ctx->alloc);
|
||||
ctx->array_us_start[ctx->nr_open_regions++] = us_now;
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +168,14 @@ void tr2tls_pop_self(void)
|
|||
{
|
||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
|
||||
if (ctx->nr_skipped_regions) {
|
||||
ctx->nr_skipped_regions--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ctx->nr_open_regions)
|
||||
BUG("no open regions in thread '%s'", ctx->thread_name);
|
||||
|
||||
|
|
@ -126,6 +186,9 @@ void tr2tls_pop_unwind_self(void)
|
|||
{
|
||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
|
||||
while (ctx->nr_open_regions > 1)
|
||||
tr2tls_pop_self();
|
||||
}
|
||||
|
|
@ -136,6 +199,10 @@ uint64_t tr2tls_region_elasped_self(uint64_t us)
|
|||
uint64_t us_start;
|
||||
|
||||
ctx = tr2tls_get_self();
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return 0;
|
||||
if (ctx->nr_skipped_regions)
|
||||
return 0;
|
||||
if (!ctx->nr_open_regions)
|
||||
return 0;
|
||||
|
||||
|
|
@ -155,6 +222,10 @@ uint64_t tr2tls_absolute_elapsed(uint64_t us)
|
|||
static void tr2tls_key_destructor(void *payload)
|
||||
{
|
||||
struct tr2tls_thread_ctx *ctx = payload;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
|
||||
free((char *)ctx->thread_name);
|
||||
free(ctx->array_us_start);
|
||||
free(ctx);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ struct tr2tls_thread_ctx {
|
|||
uint64_t *array_us_start;
|
||||
size_t alloc;
|
||||
size_t nr_open_regions; /* plays role of "nr" in ALLOC_GROW */
|
||||
size_t nr_skipped_regions;
|
||||
int thread_id;
|
||||
struct tr2_timer_block timer_block;
|
||||
struct tr2_counter_block counter_block;
|
||||
|
|
@ -53,6 +54,12 @@ struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_base_name,
|
|||
*/
|
||||
struct tr2tls_thread_ctx *tr2tls_get_self(void);
|
||||
|
||||
/*
|
||||
* Return true if the context is the non-allocating fallback used after an
|
||||
* allocation failure. Callers must not modify a fallback context.
|
||||
*/
|
||||
int tr2tls_is_fallback(const struct tr2tls_thread_ctx *ctx);
|
||||
|
||||
/*
|
||||
* return true if the current thread is the main thread.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "trace2/tr2_tls.h"
|
||||
#include "trace2/tr2_tmr.h"
|
||||
#include "trace.h"
|
||||
/* banned-die must be last. */
|
||||
#include "banned-die.h"
|
||||
|
||||
#define MY_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MY_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
|
@ -37,8 +39,11 @@ static struct tr2_timer_metadata tr2_timer_metadata[TRACE2_NUMBER_OF_TIMERS] = {
|
|||
void tr2_start_timer(enum trace2_timer_id tid)
|
||||
{
|
||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
struct tr2_timer *t = &ctx->timer_block.timer[tid];
|
||||
struct tr2_timer *t;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
t = &ctx->timer_block.timer[tid];
|
||||
t->recursion_count++;
|
||||
if (t->recursion_count > 1)
|
||||
return; /* ignore recursive starts */
|
||||
|
|
@ -49,10 +54,13 @@ void tr2_start_timer(enum trace2_timer_id tid)
|
|||
void tr2_stop_timer(enum trace2_timer_id tid)
|
||||
{
|
||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
struct tr2_timer *t = &ctx->timer_block.timer[tid];
|
||||
struct tr2_timer *t;
|
||||
uint64_t ns_now;
|
||||
uint64_t ns_interval;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
t = &ctx->timer_block.timer[tid];
|
||||
assert(t->recursion_count > 0);
|
||||
|
||||
t->recursion_count--;
|
||||
|
|
@ -90,6 +98,8 @@ void tr2_update_final_timers(void)
|
|||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
enum trace2_timer_id tid;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
if (!ctx->used_any_timer)
|
||||
return;
|
||||
|
||||
|
|
@ -136,6 +146,8 @@ void tr2_emit_per_thread_timers(tr2_tgt_evt_timer_t *fn_apply)
|
|||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||
enum trace2_timer_id tid;
|
||||
|
||||
if (tr2tls_is_fallback(ctx))
|
||||
return;
|
||||
if (!ctx->used_any_per_thread_timer)
|
||||
return;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue