From cd46620adc6ad3a609feab59fadf6817018817ed Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Tue, 19 Nov 2024 16:55:36 +0100 Subject: [PATCH] Fix race conditions in froot and Solver::timeExceeded Static variables should have been declared thread-local, but haven't. * Fixes race conditions in froot, which could have resulted in incorrect simulation results for models with events/heavisides/piecewise, for multi-threaded simulations. * Fixes race conditions for the max-time check, which could have resulted in incorrect termination of simulations in case of multi-threaded simulations in combination with a time limit. --- src/solver.cpp | 2 +- src/solver_cvodes.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solver.cpp b/src/solver.cpp index 118af4c8d7..298caaf774 100644 --- a/src/solver.cpp +++ b/src/solver.cpp @@ -1035,7 +1035,7 @@ void Solver::setMaxTime(double maxtime) { void Solver::startTimer() const { simulation_timer_.reset(); } bool Solver::timeExceeded(int interval) const { - static int eval_counter = 0; + thread_local static int eval_counter = 0; // 0 means infinite time if (maxtime_.count() == 0) diff --git a/src/solver_cvodes.cpp b/src/solver_cvodes.cpp index 0b60304c55..efe50eb8a9 100644 --- a/src/solver_cvodes.cpp +++ b/src/solver_cvodes.cpp @@ -1126,7 +1126,8 @@ static int froot(realtype t, N_Vector x, realtype* root, void* user_data) { if (model->ne != model->ne_solver) { // temporary buffer to store all root function values, not only the ones // tracked by the solver - static std::vector root_buffer(model->ne, 0.0); + thread_local static std::vector root_buffer(model->ne, 0.0); + root_buffer.resize(model->ne); model->froot(t, x, root_buffer); std::copy_n(root_buffer.begin(), model->ne_solver, root); } else {