File: lttng-context-procname.c

package info (click to toggle)
ust 2.12.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,360 kB
  • sloc: ansic: 33,193; sh: 5,404; java: 1,898; makefile: 1,198; python: 701; cpp: 177
file content (136 lines) | stat: -rw-r--r-- 4,477 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * lttng-context-procname.c
 *
 * LTTng UST procname context.
 *
 * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; only
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#define _LGPL_SOURCE
#include <lttng/ust-events.h>
#include <lttng/ust-tracer.h>
#include <lttng/ringbuffer-config.h>
#include <urcu/tls-compat.h>
#include <assert.h>
#include "compat.h"

/* Maximum number of nesting levels for the procname cache. */
#define PROCNAME_NESTING_MAX	2

/*
 * We cache the result to ensure we don't trigger a system call for
 * each event.
 * Upon exec, procname changes, but exec takes care of throwing away
 * this cached version.
 * The procname can also change by calling prctl(). The procname should
 * be set for a thread before the first event is logged within this
 * thread.
 */
typedef char procname_array[PROCNAME_NESTING_MAX][17];

static DEFINE_URCU_TLS(procname_array, cached_procname);

static DEFINE_URCU_TLS(int, procname_nesting);

static inline
char *wrapper_getprocname(void)
{
	int nesting = CMM_LOAD_SHARED(URCU_TLS(procname_nesting));

	if (caa_unlikely(nesting >= PROCNAME_NESTING_MAX))
		return "<unknown>";
	if (caa_unlikely(!URCU_TLS(cached_procname)[nesting][0])) {
		CMM_STORE_SHARED(URCU_TLS(procname_nesting), nesting + 1);
		/* Increment nesting before updating cache. */
		cmm_barrier();
		lttng_ust_getprocname(URCU_TLS(cached_procname)[nesting]);
		URCU_TLS(cached_procname)[nesting][LTTNG_UST_PROCNAME_LEN - 1] = '\0';
		/* Decrement nesting after updating cache. */
		cmm_barrier();
		CMM_STORE_SHARED(URCU_TLS(procname_nesting), nesting);
	}
	return URCU_TLS(cached_procname)[nesting];
}

/* Reset should not be called from a signal handler. */
void lttng_context_procname_reset(void)
{
	CMM_STORE_SHARED(URCU_TLS(cached_procname)[1][0], '\0');
	CMM_STORE_SHARED(URCU_TLS(procname_nesting), 1);
	CMM_STORE_SHARED(URCU_TLS(cached_procname)[0][0], '\0');
	CMM_STORE_SHARED(URCU_TLS(procname_nesting), 0);
}

static
size_t procname_get_size(struct lttng_ctx_field *field, size_t offset)
{
	return LTTNG_UST_PROCNAME_LEN;
}

static
void procname_record(struct lttng_ctx_field *field,
		 struct lttng_ust_lib_ring_buffer_ctx *ctx,
		 struct lttng_channel *chan)
{
	char *procname;

	procname = wrapper_getprocname();
	chan->ops->event_write(ctx, procname, LTTNG_UST_PROCNAME_LEN);
}

static
void procname_get_value(struct lttng_ctx_field *field,
		struct lttng_ctx_value *value)
{
	value->u.str = wrapper_getprocname();
}

int lttng_add_procname_to_ctx(struct lttng_ctx **ctx)
{
	struct lttng_ctx_field *field;

	field = lttng_append_context(ctx);
	if (!field)
		return -ENOMEM;
	if (lttng_find_context(*ctx, "procname")) {
		lttng_remove_context_field(ctx, field);
		return -EEXIST;
	}
	field->event_field.name = "procname";
	field->event_field.type.atype = atype_array;
	field->event_field.type.u.array.elem_type.atype = atype_integer;
	field->event_field.type.u.array.elem_type.u.basic.integer.size = sizeof(char) * CHAR_BIT;
	field->event_field.type.u.array.elem_type.u.basic.integer.alignment = lttng_alignof(char) * CHAR_BIT;
	field->event_field.type.u.array.elem_type.u.basic.integer.signedness = lttng_is_signed_type(char);
	field->event_field.type.u.array.elem_type.u.basic.integer.reverse_byte_order = 0;
	field->event_field.type.u.array.elem_type.u.basic.integer.base = 10;
	field->event_field.type.u.array.elem_type.u.basic.integer.encoding = lttng_encode_UTF8;
	field->event_field.type.u.array.length = LTTNG_UST_PROCNAME_LEN;
	field->get_size = procname_get_size;
	field->record = procname_record;
	field->get_value = procname_get_value;
	lttng_context_update(*ctx);
	return 0;
}

/*
 * Force a read (imply TLS fixup for dlopen) of TLS variables.
 */
void lttng_fixup_procname_tls(void)
{
	asm volatile ("" : : "m" (URCU_TLS(cached_procname)[0]));
}