HPCToolkit
safe-sampling.h
Go to the documentation of this file.
1
// -*-Mode: C++;-*- // technically C99
2
3
// * BeginRiceCopyright *****************************************************
4
//
5
// $HeadURL$
6
// $Id$
7
//
8
// --------------------------------------------------------------------------
9
// Part of HPCToolkit (hpctoolkit.org)
10
//
11
// Information about sources of support for research and development of
12
// HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13
// --------------------------------------------------------------------------
14
//
15
// Copyright ((c)) 2002-2019, Rice University
16
// All rights reserved.
17
//
18
// Redistribution and use in source and binary forms, with or without
19
// modification, are permitted provided that the following conditions are
20
// met:
21
//
22
// * Redistributions of source code must retain the above copyright
23
// notice, this list of conditions and the following disclaimer.
24
//
25
// * Redistributions in binary form must reproduce the above copyright
26
// notice, this list of conditions and the following disclaimer in the
27
// documentation and/or other materials provided with the distribution.
28
//
29
// * Neither the name of Rice University (RICE) nor the names of its
30
// contributors may be used to endorse or promote products derived from
31
// this software without specific prior written permission.
32
//
33
// This software is provided by RICE and contributors "as is" and any
34
// express or implied warranties, including, but not limited to, the
35
// implied warranties of merchantability and fitness for a particular
36
// purpose are disclaimed. In no event shall RICE or contributors be
37
// liable for any direct, indirect, incidental, special, exemplary, or
38
// consequential damages (including, but not limited to, procurement of
39
// substitute goods or services; loss of use, data, or profits; or
40
// business interruption) however caused and on any theory of liability,
41
// whether in contract, strict liability, or tort (including negligence
42
// or otherwise) arising in any way out of the use of this software, even
43
// if advised of the possibility of such damage.
44
//
45
// ******************************************************* EndRiceCopyright *
46
47
//***************************************************************************
48
//
49
// File:
50
// $HeadURL$
51
//
52
// Purpose:
53
// This file implements the "safe sampling" rules.
54
//
55
// Safe sampling extends the async blocks by tracking all entry and
56
// exit points in and out of the hpcrun code. Every thread keeps an
57
// 'inside_hpcrun' bit in the thread data struct. Set this bit via
58
// hpcrun_safe_enter() when entering hpcrun code and unset it via
59
// hpcrun_safe_exit() when returning to the application. Thus, at
60
// every entry point, we know if we just came from inside our own
61
// code.
62
//
63
// A synchronous override that was called from inside our code should
64
// call the real function and return (see IO overrides). An async
65
// interrupt that interrupted our code should restart the next signal
66
// (if needed) and return (see PAPI handler). In both cases, if
67
// coming from inside our code, then don't take a sample and don't
68
// call MSG.
69
//
70
// Notes:
71
// 1. Put the safe enter and exit functions in the first, top-level
72
// function that enters our code. Don't use them deep in the middle
73
// of our code.
74
//
75
// 2. Don't call MSG before hpcrun_safe_enter().
76
//
77
// 3. Check the return value of hpcrun_safe_enter() and don't call
78
// hpcrun_safe_exit() if safe enter returned false (unsafe).
79
//
80
// 4. In a sync override, it's ok to call safe exit and enter
81
// surrounding the call to the real function. For example,
82
//
83
// hpcrun_safe_exit();
84
// ret = real_function(...);
85
// hpcrun_safe_enter();
86
//
87
// 5. Be sure to #include <safe-sampling.h> in any file using these
88
// functions or else you'll get 'undefined reference' at runtime.
89
//
90
// 6. Technically, we don't need atomic test and set here. There is
91
// no race condition between threads. And if an interrupt happens
92
// inside hpcrun_safe_enter(), then the signal handler will restore
93
// inside_hpcrun to whatever it was when the interrupt happened.
94
//
95
// "Welcome to the Joe Hackett Flight School where our motto is,
96
// 'safety first, fun second.'" -- Joe Hackett in "Wings"
97
//
98
//***************************************************************************
99
100
#ifndef _HPCRUN_SAFE_SAMPLING_H_
101
#define _HPCRUN_SAFE_SAMPLING_H_
102
103
#include <
hpcrun/main.h
>
104
#include <
hpcrun/thread_data.h
>
105
#include <
hpcrun/trampoline/common/trampoline.h
>
106
107
108
// Use hpcrun_safe_enter() at entry into our code in a synchronous
109
// override. If unsafe (false), then call the real function and
110
// return.
111
//
112
// A sync override can occur anywhere, including before hpcrun init.
113
// So, if uninit or if thread data is not set up, then assume we're in
114
// our init code and return unsafe.
115
//
116
// Returns: true if safe, ie, not already inside our code.
117
//
118
static
inline
int
119
hpcrun_safe_enter
(
void
)
120
{
121
thread_data_t
*td;
122
int
prev;
123
124
if
(!
hpcrun_is_initialized
() || !
hpcrun_td_avail
()) {
125
return
0;
126
}
127
td =
hpcrun_get_thread_data
();
128
prev = td->
inside_hpcrun
;
129
td->
inside_hpcrun
= 1;
130
131
return
(prev == 0);
132
}
133
134
135
// Use hpcrun_safe_enter_async() at entry into our code in an async
136
// interrupt. If unsafe (false), then restart the next interrupt and
137
// return.
138
//
139
// Use the program counter address (pc) to test if the interrupt came
140
// from inside the trampoline assembler code.
141
//
142
// Returns: true if safe, ie, not already inside our code.
143
//
144
static
inline
int
145
hpcrun_safe_enter_async
(
void
*pc)
146
{
147
thread_data_t
*td;
148
int
prev;
149
150
if
(
hpcrun_trampoline_interior
(pc) ||
hpcrun_trampoline_at_entry
(pc)
151
|| !
hpcrun_td_avail
()) {
152
return
0;
153
}
154
155
td =
hpcrun_get_thread_data
();
156
prev = td->
inside_hpcrun
;
157
td->
inside_hpcrun
= 1;
158
159
return
(prev == 0);
160
}
161
162
163
// Use hpcrun_safe_exit() at return from our code back to the
164
// application. But call this only if the previous safe enter
165
// returned true.
166
//
167
static
inline
void
168
hpcrun_safe_exit
(
void
)
169
{
170
thread_data_t
*td =
hpcrun_get_thread_data
();
171
172
td->
inside_hpcrun
= 0;
173
}
174
175
176
#endif // _HPCRUN_SAFE_SAMPLING_H_
hpcrun_safe_exit
static void hpcrun_safe_exit(void)
Definition:
safe-sampling.h:168
hpcrun_is_initialized
bool hpcrun_is_initialized()
Definition:
main.c:272
main.h
hpcrun_td_avail
bool(* hpcrun_td_avail)(void)
Definition:
thread_data.c:169
trampoline.h
hpcrun_trampoline_at_entry
bool hpcrun_trampoline_at_entry(void *addr)
Definition:
trampoline.c:118
thread_data_t::inside_hpcrun
int inside_hpcrun
Definition:
thread_data.h:234
hpcrun_safe_enter_async
static int hpcrun_safe_enter_async(void *pc)
Definition:
safe-sampling.h:145
thread_data.h
thread_data_t
Definition:
thread_data.h:137
hpcrun_trampoline_interior
bool hpcrun_trampoline_interior(void *addr)
Definition:
trampoline.c:109
hpcrun_safe_enter
static int hpcrun_safe_enter(void)
Definition:
safe-sampling.h:119
hpcrun_get_thread_data
thread_data_t *(* hpcrun_get_thread_data)(void)
Definition:
thread_data.c:168
src
tool
hpcrun
safe-sampling.h
Generated by
1.8.13