HPCToolkit
messages-async.c
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 // File: messages-async.c
49 //
50 // Description:
51 // This half of the messaging system must be async-signal safe.
52 // Namely, it must be safe to call these operations from within signal
53 // handlers. Operations in this file may not directly or indirectly
54 // allocate memory using malloc. They may not call functions that
55 // acquire locks that may be already held by the application code or
56 // functions that may be called during synchronous profiler operations
57 // that may be interrupted by asynchronous profiler operations.
58 //
59 // History:
60 // 19 July 2009
61 // created by partitioning pmsg.c into messages-sync.c and
62 // messages-async.c
63 //
64 //*****************************************************************************
65 
66 
67 
68 //*****************************************************************************
69 // global includes
70 //*****************************************************************************
71 
72 #include <stdio.h>
73 #include <sys/types.h>
74 #include <unistd.h>
75 
76 
77 
78 //*****************************************************************************
79 // local includes
80 //*****************************************************************************
81 
82 #include "disabled.h"
83 #include "messages.h"
84 #include "messages.i"
85 #include "fmt.h"
86 #include "sample_event.h"
87 #include "sample_prob.h"
88 #include "thread_data.h"
89 #include "thread_use.h"
90 
91 
92 
93 //*****************************************************************************
94 // macros
95 //*****************************************************************************
96 
97 #define DEBUG_PMSG_ASYNC 0
98 
99 //*****************************************************************************
100 // constants
101 //*****************************************************************************
102 
103 static const unsigned int msg_limit = 5000; // limit log file lines
104 
105 //*****************************************************************************
106 // global variables
107 //*****************************************************************************
108 
110 
111 //*****************************************************************************
112 // (file) local variables
113 //*****************************************************************************
114 
115 static unsigned int msgs_out = 0;
116 static bool check_limit = true; // by default, limit messages
117 
118 //*****************************************************************************
119 // forward declarations
120 //*****************************************************************************
121 
122 static void create_msg(char *buf, size_t buflen, bool add_thread_id,
123  const char *tag, const char *fmt, va_list_box* box);
124 
125 //*****************************************************************************
126 // interface operations
127 //*****************************************************************************
128 
129 void
130 hpcrun_emsg_valist(const char *fmt, va_list_box* box)
131 {
132  hpcrun_write_msg_to_log(false, false, NULL, fmt, box);
133 }
134 
135 
136 void
137 hpcrun_emsg(const char *fmt,...)
138 {
139  va_list_box box;
140  va_list_box_start(box, fmt);
141  hpcrun_write_msg_to_log(false, true, NULL, fmt, &box);
142 }
143 
144 void
145 hpcrun_pmsg(const char *tag, const char *fmt, ...)
146 {
147 #ifdef SINGLE_THREAD_LOGGING
148  if ( getenv("OT") && (TD_GET(core_profile_trace_data.id) != THE_THREAD)) {
149  return;
150  }
151 #endif // SINGLE_THREAD_LOGGING
152  va_list_box box;
153  va_list_box_start(box, fmt);
154  hpcrun_write_msg_to_log(false, true, tag, fmt, &box);
155 }
156 
157 
158 // like pmsg, except echo message to stderr when flag is set
159 void
160 hpcrun_pmsg_stderr(bool echo_stderr, pmsg_category flag, const char *tag,
161  const char *fmt ,...)
162 {
163  if (debug_flag_get(flag) == 0){
164  return;
165  }
166  va_list_box box;
167  va_list_box_start(box, fmt);
168  hpcrun_write_msg_to_log(echo_stderr, true, tag, fmt, &box);
169 }
170 
171 
172 // like nmsg, except echo message to stderr when flag is set
173 void
174 hpcrun_nmsg_stderr(bool echo_stderr, pmsg_category flag, const char *tag,
175  const char *fmt ,...)
176 {
177  if (debug_flag_get(flag) == 0){
178  return;
179  }
180  va_list_box box;
181  va_list_box_start(box, fmt);
182  hpcrun_write_msg_to_log(echo_stderr, false, tag, fmt, &box);
183 }
184 
185 
186 void
187 hpcrun_nmsg(pmsg_category flag, const char* tag, const char* fmt, ...)
188 {
189  if (debug_flag_get(flag) == 0){
190  return;
191  }
192  va_list_box box;
193  va_list_box_start(box, fmt);
194  hpcrun_write_msg_to_log(false, false, tag, fmt, &box);
195 }
196 
197 
198 void
199 hpcrun_amsg(const char *fmt,...)
200 {
201  va_list_box box;
202  va_list_box_start(box, fmt);
203  bool save = check_limit;
204  check_limit = false;
205  hpcrun_write_msg_to_log(false, false, NULL, fmt, &box);
206  check_limit = save;
207 }
208 
209 
210 
211 //*****************************************************************************
212 // interface operations (within message subsystem)
213 //*****************************************************************************
214 
215 void
216 hpcrun_write_msg_to_log(bool echo_stderr, bool add_thread_id,
217  const char *tag,
218  const char *fmt, va_list_box* box)
219 {
220  char buf[MSG_BUF_SIZE];
221 
222  if ((hpcrun_get_disabled() && (! echo_stderr))
223  || (! hpcrun_sample_prob_active())) {
224  return;
225  }
226 
227  create_msg(&buf[0], sizeof(buf), add_thread_id, tag, fmt, box);
228  va_list_boxp_end(box);
229 
230  if (echo_stderr){
231  write(2, buf, strlen(buf));
232  }
233 
234  if (check_limit && (msgs_out > msg_limit)) return;
235 
236  if (hpcrun_get_disabled()) return;
237 
238  spinlock_lock(&pmsg_lock);
239 
240  // use write to logfile file descriptor, instead of fprintf stuff
241  //
242  write(messages_logfile_fd(), buf, strlen(buf));
243  msgs_out++;
244 
245  spinlock_unlock(&pmsg_lock);
246 }
247 
248 
249 //*****************************************************************************
250 // private operations
251 //*****************************************************************************
252 
253 static char*
254 safely_get_tid_str(char* buf, size_t len)
255 {
256 #ifndef USE_GCC_THREAD
258  if (td) {
259  hpcrun_msg_ns(buf, len, "%d", (td->core_profile_trace_data).id);
260  }
261  else {
262  strncpy(buf, "??", len);
263  }
264 #else // USE_GCC_THREAD
265  extern __thread monitor_tid;
266  if (monitor_tid != -1) {
267  hpcrun_msg_ns(buf, len, "%d", monitor_tid);
268  }
269  else {
270  strncpy(buf, "??", len);
271  }
272 #endif // USE_GCC_THREAD
273  return buf;
274 }
275 
276 static void
277 create_msg(char *buf, size_t buflen, bool add_thread_id, const char *tag,
278  const char *fmt, va_list_box* box)
279 {
280  char fstr[MSG_BUF_SIZE];
281 
282  fstr[0] = '\0';
283 
284  if (add_thread_id) {
285  if (hpcrun_using_threads_p()) {
286  // tmp_id = TD_GET(core_profile_trace_data.id);
287  char tmp[6] = {};
288  hpcrun_msg_ns(fstr, sizeof(fstr), "[%d, %s]: ", getpid(), safely_get_tid_str(tmp, sizeof(tmp)));
289  }
290  else {
291  hpcrun_msg_ns(fstr, sizeof(fstr), "[%d, N]: ", getpid());
292  }
293  }
294 #if 0
295  if (ENABLED(PID)) {
296  hpcrun_msg_ns(fstr, sizeof(fstr), "[%d]: ", getpid());
297  }
298 #endif
299  if (tag) {
300  char* fstr_end = fstr + strlen(fstr);
301  hpcrun_msg_ns(fstr_end, sizeof(fstr) - strlen(fstr), "%-5s: ", tag);
302  }
303 
304  strncat(fstr, fmt, MSG_BUF_SIZE - strlen(fstr) - 5);
305  strcat(fstr,"\n");
306 
307  hpcrun_msg_vns(buf, buflen - 2, fstr, box);
308 }
309 
310 void
312 {
313  check_limit = false;
314 }
315 void
317 {
318  check_limit = true;
319 }
void hpcrun_emsg_valist(const char *fmt, va_list_box *box)
ssize_t MONITOR_EXT_WRAP_NAME() write(int fd, const void *buf, size_t count)
Definition: io-over.c:189
thread_data_t * hpcrun_safe_get_td(void)
Definition: thread_data.c:140
void limit_msgs(void)
#define va_list_boxp_end(box)
Definition: fmt.h:59
static char * tmp
Definition: tokenize.c:63
int hpcrun_msg_vns(char *buf, size_t len, const char *fmt, va_list_box *box)
Definition: fmt.c:477
bool hpcrun_using_threads_p(void)
Definition: thread_use.c:81
void hpcrun_amsg(const char *fmt,...)
static void spinlock_unlock(spinlock_t *l)
Definition: spinlock.h:96
pmsg_category
Definition: debug-flag.h:89
static void create_msg(char *buf, size_t buflen, bool add_thread_id, const char *tag, const char *fmt, va_list_box *box)
int messages_logfile_fd(void)
#define va_list_box_start(box, arg)
Definition: fmt.h:56
Definition: fmt.c:108
static char * safely_get_tid_str(char *buf, size_t len)
int hpcrun_sample_prob_active(void)
Definition: sample_prob.c:193
int hpcrun_msg_ns(char *buf, size_t len, const char *fmt,...)
Definition: fmt.c:466
void hpcrun_nmsg(pmsg_category flag, const char *tag, const char *fmt,...)
static char buf[32]
Definition: StrUtil.cpp:240
static bool check_limit
core_profile_trace_data_t core_profile_trace_data
Definition: thread_data.h:168
#define TD_GET(field)
Definition: thread_data.h:256
static void spinlock_lock(spinlock_t *l)
Definition: spinlock.h:111
int debug_flag_get(pmsg_category flag)
Definition: debug-flag.c:216
void hpcrun_pmsg(const char *tag, const char *fmt,...)
void hpcrun_pmsg_stderr(bool echo_stderr, pmsg_category flag, const char *tag, const char *fmt,...)
void hpcrun_write_msg_to_log(bool echo_stderr, bool add_thread_id, const char *tag, const char *fmt, va_list_box *box)
#define NULL
Definition: ElfHelper.cpp:85
void unlimit_msgs(void)
bool hpcrun_get_disabled(void)
Definition: disabled.c:80
void hpcrun_emsg(const char *fmt,...)
spinlock_t pmsg_lock
void hpcrun_nmsg_stderr(bool echo_stderr, pmsg_category flag, const char *tag, const char *fmt,...)
static const unsigned int msg_limit
#define SPINLOCK_UNLOCKED
Definition: spinlock.h:84
static unsigned int msgs_out
#define ENABLED(f)
Definition: debug-flag.h:76