3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00

logging cleanup

move everything out-of-line as common path doesn't log
fix some race conditions on file ptr vs enable_logging vars
This commit is contained in:
Nuno Lopes 2021-08-29 12:24:19 +01:00
parent 1f4a7c5101
commit 9b5ec6d004
5 changed files with 106 additions and 76 deletions

View file

@ -1719,14 +1719,12 @@ def write_log_h_preamble(log_h):
log_h.write('#define _Z3_UNUSED\n') log_h.write('#define _Z3_UNUSED\n')
log_h.write('#endif\n') log_h.write('#endif\n')
# #
log_h.write('#include<iostream>\n') log_h.write('#include "util/mutex.h"\n')
log_h.write('#include<atomic>\n') log_h.write('extern atomic<bool> g_z3_log_enabled;\n')
log_h.write('extern std::ostream * g_z3_log;\n') log_h.write('void ctx_enable_logging();\n')
log_h.write('extern std::atomic<bool> g_z3_log_enabled;\n') log_h.write('class z3_log_ctx { bool m_prev; public: z3_log_ctx() { ATOMIC_EXCHANGE(m_prev, g_z3_log_enabled, false); } ~z3_log_ctx() { if (m_prev) g_z3_log_enabled = true; } bool enabled() const { return m_prev; } };\n')
log_h.write('class z3_log_ctx { bool m_prev; public: z3_log_ctx() { m_prev = g_z3_log && g_z3_log_enabled.exchange(false); } ~z3_log_ctx() { if (g_z3_log) g_z3_log_enabled = m_prev; } bool enabled() const { return m_prev; } };\n') log_h.write('void SetR(void * obj);\nvoid SetO(void * obj, unsigned pos);\nvoid SetAO(void * obj, unsigned pos, unsigned idx);\n')
log_h.write('inline void SetR(void * obj) { *g_z3_log << "= " << obj << "\\n"; }\ninline void SetO(void * obj, unsigned pos) { *g_z3_log << "* " << obj << " " << pos << "\\n"; } \ninline void SetAO(void * obj, unsigned pos, unsigned idx) { *g_z3_log << "@ " << obj << " " << pos << " " << idx << "\\n"; }\n')
log_h.write('#define RETURN_Z3(Z3RES) do { auto tmp_ret = Z3RES; if (_LOG_CTX.enabled()) { SetR(tmp_ret); } return tmp_ret; } while (0)\n') log_h.write('#define RETURN_Z3(Z3RES) do { auto tmp_ret = Z3RES; if (_LOG_CTX.enabled()) { SetR(tmp_ret); } return tmp_ret; } while (0)\n')
log_h.write('void _Z3_append_log(char const * msg);\n')
def write_log_c_preamble(log_c): def write_log_c_preamble(log_c):

View file

@ -270,10 +270,8 @@ namespace api {
void context::invoke_error_handler(Z3_error_code c) { void context::invoke_error_handler(Z3_error_code c) {
if (m_error_handler) { if (m_error_handler) {
if (g_z3_log) {
// error handler can do crazy stuff such as longjmp // error handler can do crazy stuff such as longjmp
g_z3_log_enabled = true; ctx_enable_logging();
}
m_error_handler(reinterpret_cast<Z3_context>(this), c); m_error_handler(reinterpret_cast<Z3_context>(this), c);
} }
} }

View file

@ -18,12 +18,13 @@ Revision History:
#include<fstream> #include<fstream>
#include "api/z3.h" #include "api/z3.h"
#include "api/api_log_macros.h" #include "api/api_log_macros.h"
#include "api/z3_logger.h"
#include "util/util.h" #include "util/util.h"
#include "util/z3_version.h" #include "util/z3_version.h"
#include "util/mutex.h" #include "util/mutex.h"
std::ostream * g_z3_log = nullptr; static std::ostream * g_z3_log = nullptr;
std::atomic<bool> g_z3_log_enabled; atomic<bool> g_z3_log_enabled;
#ifdef Z3_LOG_SYNC #ifdef Z3_LOG_SYNC
static mutex g_log_mux; static mutex g_log_mux;
@ -32,6 +33,78 @@ static mutex g_log_mux;
#define SCOPED_LOCK() {} #define SCOPED_LOCK() {}
#endif #endif
// functions called from api_log_macros.*
void SetR(void * obj) {
*g_z3_log << "= " << obj << '\n';
}
void SetO(void * obj, unsigned pos) {
*g_z3_log << "* " << obj << ' ' << pos << '\n';
}
void SetAO(void * obj, unsigned pos, unsigned idx) {
*g_z3_log << "@ " << obj << ' ' << pos << ' ' << idx << '\n';
}
namespace {
struct ll_escaped { char const * m_str; };
std::ostream & operator<<(std::ostream & out, ll_escaped const & d) {
char const * s = d.m_str;
while (*s) {
unsigned char c = *s;
if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
c == '~' || c == '!' || c == '@' || c == '#' || c == '$' || c == '%' || c == '^' || c == '&' ||
c == '*' || c == '-' || c == '_' || c == '+' || c == '.' || c == '?' || c == '/' || c == ' ' ||
c == '<' || c == '>') {
out << c;
}
else {
unsigned char str[4] = {'0', '0', '0', 0};
str[2] = '0' + (c % 10);
c /= 10;
str[1] = '0' + (c % 10);
c /= 10;
str[0] = '0' + c;
out << '\\' << str;
}
s++;
}
return out;
}
}
void R() { *g_z3_log << 'R' << std::endl; }
void P(void * obj) { *g_z3_log << "P " << obj <<std::endl; }
void I(int64_t i) { *g_z3_log << "I " << i << std::endl; }
void U(uint64_t u) { *g_z3_log << "U " << u << std::endl; }
void D(double d) { *g_z3_log << "D " << d << std::endl; }
void S(Z3_string str) { *g_z3_log << "S \"" << ll_escaped{str} << '"' << std::endl; }
void Sy(Z3_symbol sym) {
symbol s = symbol::c_api_ext2symbol(sym);
if (s.is_null()) {
*g_z3_log << 'N';
}
else if (s.is_numerical()) {
*g_z3_log << "# " << s.get_num();
}
else {
*g_z3_log << "$ |" << ll_escaped{s.bare_str()} << '|';
}
*g_z3_log << std::endl;
}
void Ap(unsigned sz) { *g_z3_log << "p " << sz << std::endl; }
void Au(unsigned sz) { *g_z3_log << "u " << sz << std::endl; }
void Ai(unsigned sz) { *g_z3_log << "i " << sz << std::endl; }
void Asy(unsigned sz) { *g_z3_log << "s " << sz << std::endl; }
void C(unsigned id) { *g_z3_log << "C " << id << std::endl; }
static void _Z3_append_log(char const * msg) { *g_z3_log << "M \"" << ll_escaped{msg} << '"' << std::endl; }
void ctx_enable_logging() {
SCOPED_LOCK();
if (g_z3_log != nullptr)
g_z3_log_enabled = true;
}
static void Z3_close_log_unsafe(void) { static void Z3_close_log_unsafe(void) {
if (g_z3_log != nullptr) { if (g_z3_log != nullptr) {
g_z3_log_enabled = false; g_z3_log_enabled = false;
@ -42,11 +115,11 @@ static void Z3_close_log_unsafe(void) {
extern "C" { extern "C" {
bool Z3_API Z3_open_log(Z3_string filename) { bool Z3_API Z3_open_log(Z3_string filename) {
bool res = true; bool res;
SCOPED_LOCK(); SCOPED_LOCK();
if (g_z3_log != nullptr)
Z3_close_log_unsafe(); Z3_close_log_unsafe();
g_z3_log = alloc(std::ofstream, filename); g_z3_log = alloc(std::ofstream, filename);
if (g_z3_log->bad() || g_z3_log->fail()) { if (g_z3_log->bad() || g_z3_log->fail()) {
dealloc(g_z3_log); dealloc(g_z3_log);
@ -54,16 +127,16 @@ extern "C" {
res = false; res = false;
} }
else { else {
*g_z3_log << "V \"" << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER << "." << Z3_REVISION_NUMBER << "\"\n"; *g_z3_log << "V \"" << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER << "." << Z3_REVISION_NUMBER << '"' << std::endl;
g_z3_log->flush(); res = true;
g_z3_log_enabled = true;
} }
g_z3_log_enabled = res;
return res; return res;
} }
void Z3_API Z3_append_log(Z3_string str) { void Z3_API Z3_append_log(Z3_string str) {
if (g_z3_log == nullptr) if (!g_z3_log_enabled)
return; return;
SCOPED_LOCK(); SCOPED_LOCK();
if (g_z3_log != nullptr) if (g_z3_log != nullptr)
@ -71,9 +144,7 @@ extern "C" {
} }
void Z3_API Z3_close_log(void) { void Z3_API Z3_close_log(void) {
if (g_z3_log != nullptr) {
SCOPED_LOCK(); SCOPED_LOCK();
Z3_close_log_unsafe(); Z3_close_log_unsafe();
} }
} }
}

View file

@ -16,57 +16,17 @@ Author:
Notes: Notes:
--*/ --*/
#include<iostream>
#include "util/symbol.h" #include "util/symbol.h"
struct ll_escaped { char const * m_str; ll_escaped(char const * str):m_str(str) {} };
static std::ostream & operator<<(std::ostream & out, ll_escaped const & d);
static void __declspec(noinline) R() { *g_z3_log << "R\n"; g_z3_log->flush(); } void R();
static void __declspec(noinline) P(void * obj) { *g_z3_log << "P " << obj << "\n"; g_z3_log->flush(); } void P(void * obj);
static void __declspec(noinline) I(int64_t i) { *g_z3_log << "I " << i << "\n"; g_z3_log->flush(); } void I(int64_t i);
static void __declspec(noinline) U(uint64_t u) { *g_z3_log << "U " << u << "\n"; g_z3_log->flush(); } void U(uint64_t u);
static void __declspec(noinline) D(double d) { *g_z3_log << "D " << d << "\n"; g_z3_log->flush(); } void D(double d);
static void __declspec(noinline) S(Z3_string str) { *g_z3_log << "S \"" << ll_escaped(str) << "\"\n"; g_z3_log->flush(); } void S(Z3_string str);
static void __declspec(noinline) Sy(Z3_symbol sym) { void Sy(Z3_symbol sym);
symbol s = symbol::c_api_ext2symbol(sym); void Ap(unsigned sz);
if (s.is_null()) { void Au(unsigned sz);
*g_z3_log << "N\n"; void Ai(unsigned sz);
} void Asy(unsigned sz);
else if (s.is_numerical()) { void C(unsigned id);
*g_z3_log << "# " << s.get_num() << "\n";
}
else {
*g_z3_log << "$ |" << ll_escaped(s.bare_str()) << "|\n";
}
g_z3_log->flush();
}
static void __declspec(noinline) Ap(unsigned sz) { *g_z3_log << "p " << sz << "\n"; g_z3_log->flush(); }
static void __declspec(noinline) Au(unsigned sz) { *g_z3_log << "u " << sz << "\n"; g_z3_log->flush(); }
static void __declspec(noinline) Ai(unsigned sz) { *g_z3_log << "i " << sz << "\n"; g_z3_log->flush(); }
static void __declspec(noinline) Asy(unsigned sz) { *g_z3_log << "s " << sz << "\n"; g_z3_log->flush(); }
static void __declspec(noinline) C(unsigned id) { *g_z3_log << "C " << id << "\n"; g_z3_log->flush(); }
void __declspec(noinline) _Z3_append_log(char const * msg) { *g_z3_log << "M \"" << ll_escaped(msg) << "\"\n"; g_z3_log->flush(); }
static std::ostream & operator<<(std::ostream & out, ll_escaped const & d) {
char const * s = d.m_str;
while (*s) {
unsigned char c = *s;
if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
c == '~' || c == '!' || c == '@' || c == '#' || c == '$' || c == '%' || c == '^' || c == '&' ||
c == '*' || c == '-' || c == '_' || c == '+' || c == '.' || c == '?' || c == '/' || c == ' ' ||
c == '<' || c == '>') {
out << c;
}
else {
unsigned char str[4] = {'0', '0', '0', 0};
str[2] = '0' + (c % 10);
c /= 10;
str[1] = '0' + (c % 10);
c /= 10;
str[0] = '0' + c;
out << '\\' << str;
}
s++;
}
return out;
}

View file

@ -16,6 +16,8 @@ Abstract:
template<typename T> using atomic = T; template<typename T> using atomic = T;
#define ATOMIC_EXCHANGE(ret, var, val) ret = var; var = val
struct mutex { struct mutex {
void lock() {} void lock() {}
void unlock() {} void unlock() {}
@ -38,6 +40,7 @@ template<typename T> using atomic = std::atomic<T>;
typedef std::mutex mutex; typedef std::mutex mutex;
typedef std::lock_guard<std::mutex> lock_guard; typedef std::lock_guard<std::mutex> lock_guard;
#define ATOMIC_EXCHANGE(ret, var, val) ret = var.exchange(val)
#define DECLARE_MUTEX(name) mutex *name = nullptr #define DECLARE_MUTEX(name) mutex *name = nullptr
#define DECLARE_INIT_MUTEX(name) mutex *name = new mutex #define DECLARE_INIT_MUTEX(name) mutex *name = new mutex
#define ALLOC_MUTEX(name) name = alloc(mutex) #define ALLOC_MUTEX(name) name = alloc(mutex)