3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-16 01:16:39 +00:00
z3/src/util/rlimit.cpp
Nikolaj Bjorner 71bad7159b #7418 - circumvent use of timer threads to make WASM integration of z3 easier
The scoped_timer uses a std::therad. Spawning this thread fails in cases of WASM.
Instead of adapting builds and using async features at the level of WASM and the client, we expose a specialized version of z3 that doesn't use threads at all, neither for solvers nor for timers.
The tradeoff is that the periodic poll that checks for timeout directly queries the global clock each time.
We characterize it as based on polling.
2024-11-21 11:20:05 -08:00

167 lines
No EOL
3.1 KiB
C++

/*++
Copyright (c) 2015 Microsoft Corporation
Module Name:
rlimit.cpp
Abstract:
Resource limit container.
Author:
Nikolaj Bjorner (nbjorner) 2015-09-28
Revision History:
--*/
#include "util/rlimit.h"
#include "util/common_msgs.h"
#include "util/mutex.h"
static DECLARE_MUTEX(g_rlimit_mux);
void initialize_rlimit() {
ALLOC_MUTEX(g_rlimit_mux);
}
void finalize_rlimit() {
DEALLOC_MUTEX(g_rlimit_mux);
}
reslimit::reslimit() {
}
uint64_t reslimit::count() const {
return m_count;
}
bool reslimit::inc() {
++m_count;
return not_canceled();
}
bool reslimit::inc(unsigned offset) {
m_count += offset;
return not_canceled();
}
void reslimit::push(unsigned delta_limit) {
uint64_t new_limit = delta_limit ? delta_limit + m_count : std::numeric_limits<uint64_t>::max();
if (new_limit <= m_count) {
new_limit = std::numeric_limits<uint64_t>::max();
}
m_limits.push_back(m_limit);
m_limit = std::min(new_limit, m_limit);
m_cancel = 0;
}
void reslimit::pop() {
if (m_count > m_limit) {
m_count = m_limit;
}
m_limit = m_limits.back();
m_limits.pop_back();
m_cancel = 0;
}
char const* reslimit::get_cancel_msg() const {
if (m_cancel > 0) {
return Z3_CANCELED_MSG;
}
else {
return Z3_MAX_RESOURCE_MSG;
}
}
void reslimit::push_child(reslimit* r) {
lock_guard lock(*g_rlimit_mux);
m_children.push_back(r);
}
void reslimit::pop_child() {
lock_guard lock(*g_rlimit_mux);
m_count += m_children.back()->m_count;
m_children.back()->m_count = 0;
m_children.pop_back();
}
void reslimit::pop_child(reslimit* r) {
lock_guard lock(*g_rlimit_mux);
for (unsigned i = 0; i < m_children.size(); ++i) {
if (m_children[i] == r) {
m_count += r->m_count;
r->m_count = 0;
m_children.erase(m_children.begin() + i);
return;
}
}
}
void reslimit::cancel() {
lock_guard lock(*g_rlimit_mux);
set_cancel(m_cancel+1);
}
void reslimit::reset_cancel() {
lock_guard lock(*g_rlimit_mux);
set_cancel(0);
}
void reslimit::inc_cancel() {
lock_guard lock(*g_rlimit_mux);
set_cancel(m_cancel + 1);
}
void reslimit::dec_cancel() {
lock_guard lock(*g_rlimit_mux);
if (m_cancel > 0) {
set_cancel(m_cancel-1);
}
}
void reslimit::set_cancel(unsigned f) {
m_cancel = f;
for (unsigned i = 0; i < m_children.size(); ++i) {
m_children[i]->set_cancel(f);
}
}
#ifdef POLLING_TIMER
void reslimit::push_timeout(unsigned ms) {
m_num_timers++;
if (m_cancel > 0) {
++m_cancel;
return;
}
if (m_timeout_ms != 0) {
double ms_taken = 1000 * m_timer.get_seconds();
if (ms_taken > m_timeout_ms)
return;
if (m_timeout_ms - ms_taken < ms)
return;
}
m_timer = timer();
m_timeout_ms = ms;
}
void reslimit::inc_cancel(unsigned k) {
lock_guard lock(*g_rlimit_mux);
set_cancel(m_cancel + k);
}
void reslimit::auto_cancel() {
--m_num_timers;
dec_cancel();
}
#else
void reslimit::auto_cancel() {
UNREACHABLE();
}
#endif