File: common_session_state.h

package info (click to toggle)
systemtap 2.6-0.2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 21,220 kB
  • ctags: 10,944
  • sloc: cpp: 53,239; ansic: 50,615; exp: 33,694; sh: 9,906; xml: 7,665; perl: 2,089; python: 1,534; tcl: 1,236; makefile: 797; java: 148; lisp: 104; awk: 94; asm: 91; sed: 16
file content (225 lines) | stat: -rw-r--r-- 6,803 bytes parent folder | download | duplicates (2)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// Will be included once by runtime/common_session_state.h, which is included
// once by translate.cxx c_unparser::emit_common_header ().


// Forward declarations for things in runtime/dyninst/shm.c
static void *_stp_shm_base;
static void *_stp_shm_alloc(size_t size);

#include "session_attributes.h"
#include "transport.h"

// Global state shared throughout the module
struct stp_runtime_session {
	atomic_t _session_state;

	atomic_t _error_count;
	atomic_t _skipped_count;
	atomic_t _skipped_count_lowstack;
	atomic_t _skipped_count_reentrant;
	atomic_t _skipped_count_uprobe_reg;
	atomic_t _skipped_count_uprobe_unreg;

        unsigned long _hash_seed;

	struct _stp_session_attributes _session_attributes;

#ifdef STP_ALIBI
	atomic_t _probe_alibi[STP_PROBE_COUNT];
#endif

#ifdef STP_TIMING
	offptr_t _probe_timing[STP_PROBE_COUNT]; // offptr<Stat>
#endif

	struct stp_globals _global;

	struct _stp_transport_session_data _transport_data;

	// NB: the context includes a number of pointers, which wouldn't be
	// kosher for shared memory, but it's ok as long as they're only set
	// and dereferenced within each separate handler invocation.
	struct context _context[]; // variably-sized to cpu count
};

static inline struct stp_runtime_session* _stp_session(void)
{
	// Since the session is always the first thing allocated, it lives
	// directly at the start of shared memory.
	// NB: We always reference the main shm pointer, rather than our own
	// local copy, because reallocations may cause it to move dynamically.
	return _stp_shm_base;
}


#define GET_SESSION_ATOMIC(name)			\
	static inline atomic_t *name(void) {		\
		if (unlikely(_stp_session() == NULL))	\
			return NULL;			\
		return &_stp_session()->_##name;	\
	}

GET_SESSION_ATOMIC(session_state);

GET_SESSION_ATOMIC(error_count);
GET_SESSION_ATOMIC(skipped_count);
GET_SESSION_ATOMIC(skipped_count_lowstack);
GET_SESSION_ATOMIC(skipped_count_reentrant);
GET_SESSION_ATOMIC(skipped_count_uprobe_reg);
GET_SESSION_ATOMIC(skipped_count_uprobe_unreg);

#undef GET_SESSION_ATOMIC


static inline unsigned long _stap_hash_seed()
{
	if (likely(_stp_session()))
		return _stp_session()->_hash_seed;
	return 0;
}


static inline struct _stp_session_attributes *stp_session_attributes(void)
{
	if (likely(_stp_session()))
		return &_stp_session()->_session_attributes;
	return NULL;
}


#ifdef STP_ALIBI
static inline atomic_t *probe_alibi(size_t index)
{
	// Do some simple bounds-checking.  Translator-generated code
	// should never get this wrong, but better to be safe.
	index = clamp_t(size_t, index, 0, STP_PROBE_COUNT - 1);
	if (likely(_stp_session()))
		return &_stp_session()->_probe_alibi[index];
	return NULL;
}
#endif

#ifdef STP_TIMING
static inline Stat probe_timing(size_t index)
{
	// Do some simple bounds-checking.  Translator-generated code
	// should never get this wrong, but better to be safe.
	index = clamp_t(size_t, index, 0, STP_PROBE_COUNT - 1);
	if (likely(_stp_session()))
		return offptr_get(&_stp_session()->_probe_timing[index]);
	return NULL;
}
#endif


static inline struct context* stp_session_context(size_t index)
{
	// Do some simple bounds-checking.  Translator-generated code
	// should never get this wrong, but better to be safe.
	index = clamp_t(size_t, index, 0, _stp_runtime_num_contexts - 1);
	if (likely(_stp_session()))
		return &_stp_session()->_context[index];
	return NULL;
}


static inline struct _stp_transport_session_data *stp_transport_data(void)
{
	if (_stp_session())
		return &_stp_session()->_transport_data;
	return NULL;
}

#define _global_raw(name)	(_stp_session()->_global.name)
#define _global_type(name)	typeof(_global_raw(name))
#define _global_cast_type(name)	_global_type(name ## _typed)
#define _global_offptr_p(name)	\
	__builtin_types_compatible_p(_global_type(name), offptr_t)
#define _global_compat_p(name, value)	\
	__builtin_types_compatible_p(_global_cast_type(name), typeof(value))

// NB: The (offptr_t*) cast is unfortunately necessary for the first expression
// to pass syntax on long/string types, but __builtin_choose_expr will still
// direct them to the second expression due to the _global_offptr_p check.
#define global(name)							\
	__builtin_choose_expr(_global_offptr_p(name),			\
		((_global_cast_type(name))				\
			offptr_get((offptr_t*)&_global_raw(name))),	\
		_global_raw(name))

// NB: This is only used for pointer->offptr assignments, for stats and maps.
// Unlike global() which just returns string/long types by value, here we'd
// have to encode their separate assignment schemes, in a way that stays
// syntax-compatible with all others.  The translator can do that simpler.
// NB: Evaluate the value *before* the offptr destination is computed, in
// case the value's allocation causes shm to move.
#define global_set(name, value)	({					\
	typeof(value) __value = (value);				\
	offptr_set(&_global_raw(name),					\
		__builtin_choose_expr(_global_compat_p(name, __value),	\
			__value, (void)0));				\
	__value; })

#define global_lock(name)	(&_global_raw(name ## _lock))
#define global_lock_init(name)	\
	stp_pthread_rwlock_init_shared(global_lock(name))

#ifdef STP_TIMING
#define global_skipped(name)	(&_global_raw(name ## _lock_skip_count))
#endif


static int stp_session_init(void)
{
	size_t i;

	// Reserve space for the session at the beginning of shared memory.
	size_t session_size = sizeof(struct stp_runtime_session)
		+ sizeof(struct context) * _stp_runtime_num_contexts;
	void *session = _stp_shm_zalloc(session_size);
	if (!session)
		return -ENOMEM;

	// If we weren't the very first thing allocated, then something is wrong!
	if (session != _stp_shm_base)
		return -EINVAL;

	atomic_set(session_state(), STAP_SESSION_STARTING);

	atomic_set(error_count(), 0);
	atomic_set(skipped_count(), 0);
	atomic_set(skipped_count_lowstack(), 0);
	atomic_set(skipped_count_reentrant(), 0);
	atomic_set(skipped_count_uprobe_reg(), 0);
	atomic_set(skipped_count_uprobe_unreg(), 0);

	_stp_session()->_hash_seed = _stp_random_u ((unsigned long)-1);

	stp_session_attributes_init();

#ifdef STP_ALIBI
	// Initialize all the alibi counters
	for (i = 0; i < STP_PROBE_COUNT; ++i)
		atomic_set(probe_alibi(i), 0);
#endif

#ifdef STP_TIMING
	// Initialize each Stat used for timing information
	for (i = 0; i < STP_PROBE_COUNT; ++i) {
		// NB: we don't check for null return here, but instead at
		// passage to probe handlers and at final printing.
		Stat st = _stp_stat_init(HIST_NONE);

		// NB: allocate first, then dereference the session after, in case
		// allocation-resizing causes the whole thing to move around.
		offptr_set(&_stp_session()->_probe_timing[i], st);
	}
#endif

	return _stp_dyninst_transport_session_init();
}

static int stp_session_init_finished(void)
{
	return stp_dyninst_session_init_finished();
}