1/*****************************************************************************
2
3Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/*****************************************************************//**
21@file include/ut0dbg.h
22Debug utilities for Innobase
23
24Created 1/30/1994 Heikki Tuuri
25**********************************************************************/
26
27#ifndef ut0dbg_h
28#define ut0dbg_h
29
30#ifdef UNIV_INNOCHECKSUM
31#define ut_a assert
32#define ut_ad assert
33#define ut_error assert(0)
34#else /* !UNIV_INNOCHECKSUM */
35
36/* Do not include univ.i because univ.i includes this. */
37
38#include "os0thread.h"
39
40/*************************************************************//**
41Report a failed assertion. */
42ATTRIBUTE_NORETURN ATTRIBUTE_COLD __attribute__((nonnull(2)))
43void
44ut_dbg_assertion_failed(
45/*====================*/
46 const char* expr, /*!< in: the failed assertion */
47 const char* file, /*!< in: source file containing the assertion */
48 unsigned line); /*!< in: line number of the assertion */
49
50/** Abort execution if EXPR does not evaluate to nonzero.
51@param EXPR assertion expression that should hold */
52#define ut_a(EXPR) do { \
53 if (UNIV_UNLIKELY(!(ulint) (EXPR))) { \
54 ut_dbg_assertion_failed(#EXPR, \
55 __FILE__, __LINE__); \
56 } \
57} while (0)
58
59/** Abort execution. */
60#define ut_error \
61 ut_dbg_assertion_failed(0, __FILE__, __LINE__)
62
63/** Debug assertion */
64#define ut_ad DBUG_SLOW_ASSERT
65#if defined(UNIV_DEBUG) || !defined(DBUG_OFF)
66/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
67#define ut_d(EXPR) EXPR
68#else
69/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
70#define ut_d(EXPR)
71#endif
72
73/** Silence warnings about an unused variable by doing a null assignment.
74@param A the unused variable */
75#define UT_NOT_USED(A) A = A
76
77#if defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_RESOURCE_H)
78
79#define HAVE_UT_CHRONO_T
80
81#include <sys/types.h>
82#include <sys/time.h>
83#include <sys/resource.h>
84
85/** A "chronometer" used to clock snippets of code.
86Example usage:
87 ut_chrono_t ch("this loop");
88 for (;;) { ... }
89 ch.show();
90would print the timings of the for() loop, prefixed with "this loop:" */
91class ut_chrono_t {
92public:
93 /** Constructor.
94 @param[in] name chrono's name, used when showing the values */
95 ut_chrono_t(
96 const char* name)
97 :
98 m_name(name),
99 m_show_from_destructor(true)
100 {
101 reset();
102 }
103
104 /** Resets the chrono (records the current time in it). */
105 void
106 reset()
107 {
108 gettimeofday(&m_tv, NULL);
109
110 getrusage(RUSAGE_SELF, &m_ru);
111 }
112
113 /** Shows the time elapsed and usage statistics since the last reset. */
114 void
115 show()
116 {
117 struct rusage ru_now;
118 struct timeval tv_now;
119 struct timeval tv_diff;
120
121 getrusage(RUSAGE_SELF, &ru_now);
122
123 gettimeofday(&tv_now, NULL);
124
125#ifndef timersub
126#define timersub(a, b, r) \
127 do { \
128 (r)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
129 (r)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
130 if ((r)->tv_usec < 0) { \
131 (r)->tv_sec--; \
132 (r)->tv_usec += 1000000; \
133 } \
134 } while (0)
135#endif /* timersub */
136
137#define CHRONO_PRINT(type, tvp) \
138 fprintf(stderr, "%s: %s% 5ld.%06ld sec\n", \
139 m_name, type, \
140 static_cast<long>((tvp)->tv_sec), \
141 static_cast<long>((tvp)->tv_usec))
142
143 timersub(&tv_now, &m_tv, &tv_diff);
144 CHRONO_PRINT("real", &tv_diff);
145
146 timersub(&ru_now.ru_utime, &m_ru.ru_utime, &tv_diff);
147 CHRONO_PRINT("user", &tv_diff);
148
149 timersub(&ru_now.ru_stime, &m_ru.ru_stime, &tv_diff);
150 CHRONO_PRINT("sys ", &tv_diff);
151 }
152
153 /** Cause the timings not to be printed from the destructor. */
154 void end()
155 {
156 m_show_from_destructor = false;
157 }
158
159 /** Destructor. */
160 ~ut_chrono_t()
161 {
162 if (m_show_from_destructor) {
163 show();
164 }
165 }
166
167private:
168 /** Name of this chronometer. */
169 const char* m_name;
170
171 /** True if the current timings should be printed by the destructor. */
172 bool m_show_from_destructor;
173
174 /** getrusage() result as of the last reset(). */
175 struct rusage m_ru;
176
177 /** gettimeofday() result as of the last reset(). */
178 struct timeval m_tv;
179};
180
181#endif /* HAVE_SYS_TIME_H && HAVE_SYS_RESOURCE_H */
182
183#endif /* !UNIV_INNOCHECKSUM */
184
185#endif
186