Showing the changes to src/vm/thread.cpp (1 of 9 files). Show all
Unified · Split
| @@ -111,6 +111,7 @@ vm_thread_t::vm_thread_t( · 110 unmodified lines | ||
| 111 | 111 | vm_module_ref_t &entry, |
| 112 | 112 | uint32_t parent_thread_id) |
| 113 | 113 | : vm_alloc_t(vm_thread_t::type_desc()) |
| 114 | + , _error_message{ nullptr } | |
| 114 | 115 | , _parent_thread_id{ parent_thread_id } |
| 115 | 116 | , _registers{ *this, entry } |
| 116 | 117 | , _thread_id{ get_unique_thread_id() } |
| @@ -135,6 +136,7 @@ vm_thread_t::vm_thread_t( · 18 unmodified lines | ||
| 135 | 136 | const vm_frame_t &initial_frame, |
| 136 | 137 | vm_pc_t start_pc) |
| 137 | 138 | : vm_alloc_t(vm_thread_t::type_desc()) |
| 139 | + , _error_message{ nullptr } | |
| 138 | 140 | , _parent_thread_id{ parent_thread_id } |
| 139 | 141 | , _registers{ *this, entry } |
| 140 | 142 | , _thread_id{ get_unique_thread_id() } |
| @@ -162,6 +164,9 @@ vm_thread_t::~vm_thread_t() · 21 unmodified lines | ||
| 162 | 164 | { |
| 163 | 165 | if (debug::is_component_tracing_enabled<debug::component_trace_t::thread>()) |
| 164 | 166 | debug::log_msg(debug::component_trace_t::thread, debug::log_level_t::debug, "destroy: vm thread: %d %d\n", _thread_id, _parent_thread_id); |
| 167 | + | |
| 168 | + free_memory(_error_message); | |
| 169 | + debug::assign_debug_pointer(&_error_message); | |
| 165 | 170 | } |
| 166 | 171 | |
| 167 | 172 | namespace |
| @@ -214,6 +219,7 @@ namespace · 46 unmodified lines | ||
| 214 | 219 | |
| 215 | 220 | vm_thread_state_t vm_thread_t::execute(vm_t &vm, const uint32_t quanta) |
| 216 | 221 | { |
| 222 | + const auto max_error_message = std::size_t{ 1024 }; | |
| 217 | 223 | _registers.current_thread_state = vm_thread_state_t::running; |
| 218 | 224 | _registers.current_thread_quanta = quanta; |
| 219 | 225 | assert(_registers.pc != runtime_constants::invalid_program_counter); |
| @@ -226,27 +232,27 @@ vm_thread_state_t vm_thread_t::execute(vm_t &vm, const uint32_t quanta) · 6 unmodified lines | ||
| 226 | 232 | else |
| 227 | 233 | execute_impl<execute_with_tool_t>(_registers, vm); |
| 228 | 234 | } |
| 235 | + catch (const vm_term_request &) | |
| 236 | + { | |
| 237 | + throw; | |
| 238 | + } | |
| 229 | 239 | catch (const unhandled_user_exception &uue) |
| 230 | 240 | { |
| 231 | − // [TODO] Store the exception | |
| 232 | − std::fprintf(stderr, "%s - '%s' in %s at instruction %d\n", uue.what(), uue.exception_id, uue.module_name, uue.program_counter); | |
| 241 | + _error_message = calloc_memory<char>(max_error_message); | |
| 242 | + std::snprintf(_error_message, max_error_message, "%s - '%s' in %s at instruction %d", uue.what(), uue.exception_id, uue.module_name, uue.program_counter); | |
| 233 | 243 | _registers.current_thread_state = vm_thread_state_t::broken; |
| 234 | − if (tool_dispatch != nullptr) | |
| 235 | − tool_dispatch->on_thread_broken(*this); | |
| 236 | 244 | } |
| 237 | 245 | catch (const index_out_of_range_memory &ioor) |
| 238 | 246 | { |
| 239 | − std::fprintf(stderr, "%s - %d [%d,%d]\n", ioor.what(), ioor.invalid_value, ioor.valid_min, ioor.valid_max); | |
| 247 | + _error_message = calloc_memory<char>(max_error_message); | |
| 248 | + std::snprintf(_error_message, max_error_message, "%s - %d [%d,%d]", ioor.what(), ioor.invalid_value, ioor.valid_min, ioor.valid_max); | |
| 240 | 249 | _registers.current_thread_state = vm_thread_state_t::broken; |
| 241 | − if (tool_dispatch != nullptr) | |
| 242 | − tool_dispatch->on_thread_broken(*this); | |
| 243 | 250 | } |
| 244 | 251 | catch (const vm_user_exception &ue) |
| 245 | 252 | { |
| 246 | − std::fprintf(stderr, "%s\n", ue.what()); | |
| 253 | + _error_message = calloc_memory<char>(max_error_message); | |
| 254 | + std::snprintf(_error_message, max_error_message, "%s", ue.what()); | |
| 247 | 255 | _registers.current_thread_state = vm_thread_state_t::broken; |
| 248 | − if (tool_dispatch != nullptr) | |
| 249 | − tool_dispatch->on_thread_broken(*this); | |
| 250 | 256 | } |
| 251 | 257 | |
| 252 | 258 | // Log the execution result |
| @@ -262,16 +268,22 @@ vm_thread_state_t vm_thread_t::execute(vm_t &vm, const uint32_t quanta) · 9 unmodified lines | ||
| 262 | 268 | _registers.current_thread_state); |
| 263 | 269 | } |
| 264 | 270 | |
| 265 | − // If the thread is still in the running state transition it back to its entry state. | |
| 266 | − if (_registers.current_thread_state == vm_thread_state_t::running) | |
| 271 | + switch (_registers.current_thread_state) | |
| 267 | 272 | { |
| 273 | + case vm_thread_state_t::running: | |
| 268 | 274 | _registers.current_thread_state = (tool_dispatch == nullptr) ? vm_thread_state_t::ready : vm_thread_state_t::debug; |
| 269 | − } | |
| 270 | − else if (vm_thread_state_t::exiting == _registers.current_thread_state | |
| 271 | − || vm_thread_state_t::empty_stack == _registers.current_thread_state) | |
| 272 | − { | |
| 275 | + break; | |
| 276 | + | |
| 277 | + case vm_thread_state_t::empty_stack: | |
| 278 | + case vm_thread_state_t::exiting: | |
| 273 | 279 | if (tool_dispatch != nullptr) |
| 274 | 280 | tool_dispatch->on_thread_end(*this); |
| 281 | + break; | |
| 282 | + | |
| 283 | + case vm_thread_state_t::broken: | |
| 284 | + if (tool_dispatch != nullptr) | |
| 285 | + tool_dispatch->on_thread_broken(*this); | |
| 286 | + break; | |
| 275 | 287 | } |
| 276 | 288 | |
| 277 | 289 | return _registers.current_thread_state; |
| @@ -288,6 +300,11 @@ vm_thread_state_t vm_thread_t::get_state() const · 10 unmodified lines | ||
| 288 | 300 | return _registers.current_thread_state; |
| 289 | 301 | } |
| 290 | 302 | |
| 303 | +const char *vm_thread_t::get_error_message() const | |
| 304 | +{ | |
| 305 | + return _error_message; | |
| 306 | +} | |
| 307 | + | |
| 291 | 308 | uint32_t vm_thread_t::get_thread_id() const |
| 292 | 309 | { |
| 293 | 310 | return _thread_id; |