// // Dis VM // File: disvm.h // Author: arr // #ifndef _DISVM_SRC_INCLUDE_DISVM_H_ #define _DISVM_SRC_INCLUDE_DISVM_H_ #include #include #include #include #include #include #include "runtime.h" #include "exceptions.h" namespace disvm { // Read in a module from the supplied stream std::unique_ptr read_module(std::istream &data); template using create_vm_interface_callback_t = std::unique_ptr(*)(vm_t &); // VM version structure // Adheres to the semantic versioning scheme found at http://semver.org/ struct vm_version_t final { const uint32_t major; const uint32_t minor; const uint32_t patch; const char * const label; // Optional }; // Loaded module reference class loaded_vm_module_t final { public: runtime::module_id_t vm_id; // Origin of module std::unique_ptr origin; // Weak reference to a loaded module std::weak_ptr module; }; // Callback for enumerating loaded modules - return 'false' to stop enumeration, otherwise 'true' using loaded_vm_module_callback_t = std::function; // Configuration for the created VM class vm_config_t final { public: vm_config_t(); vm_config_t(vm_config_t &&); // Settings for the default scheduler. Only used if create_scheduler is not set. // Both of these values are initialized to valid default values on construction. uint32_t sys_thread_pool_size; uint32_t thread_quanta; create_vm_interface_callback_t create_scheduler; create_vm_interface_callback_t create_gc; // Prefix paths used by the default module resolver if the path supplied by // the user isn't found. Note these will be concatenated with the supplied // path, not other manipulation will be performed. std::vector probing_paths; std::vector> additional_resolvers; }; // Virtual machine class vm_t final { public: // static static const uint32_t root_vm_thread_id; public: explicit vm_t(); explicit vm_t(vm_config_t config); ~vm_t(); public: // Get the VM version. // All fields on the output structure will be set. vm_version_t get_version() const; // Begin execution of the module at the supplied path and return the ID of // the executing thread. uint32_t exec(const char *path); // Begin execution of the supplied module and return the ID of the executing thread. uint32_t exec(std::unique_ptr entry_module); // Begin execution of a child thread in the supplied module at the indicated // program counter and return the ID of the executing thread. uint32_t fork( const uint32_t parent_tid, runtime::vm_module_ref_t &module_ref, const runtime::vm_frame_t &initial_frame, runtime::vm_pc_t initial_pc); // Load the module at the supplied path into the virtual machine. std::shared_ptr load_module(const char *path); // Enumerate all loaded modules - this can include references to modules that // have been unloaded due to no longer being used. If the module instance is null, the // module is no longer loaded. // Note this will only enumerate modules that have been loaded via a path. void enum_loaded_modules(loaded_vm_module_callback_t callback) const; // Access the scheduler control for this VM. runtime::vm_scheduler_control_t &get_scheduler_control() const; // Access the garbage collector for this VM. runtime::vm_garbage_collector_t &get_garbage_collector() const; // Spin and sleep until the VM is idle, then return. // Idle is defined as no vm threads executing, scheduled to be executed, or blocked. void spin_sleep_till_idle(std::chrono::milliseconds sleep_interval) const; // Loads a tool into the VM std::size_t load_tool(std::shared_ptr tool); // Unloads the tool associated with the supplied ID void unload_tool(std::size_t tool_id); private: void schedule_thread(std::unique_ptr thread); using loaded_modules_t = std::forward_list; mutable std::mutex _modules_lock; loaded_modules_t _modules; std::vector> _module_resolvers; std::unique_ptr _scheduler; std::unique_ptr _gc; std::unique_ptr _tool_dispatch; std::mutex _tool_dispatch_lock; std::atomic_flag _last_syscall_error_message_lock; std::array _last_syscall_error_message; friend void disvm::runtime::push_syscall_error_message(disvm::vm_t &, const char *) noexcept; friend std::string disvm::runtime::pop_syscall_error_message(disvm::vm_t &); }; } #endif // _DISVM_SRC_INCLUDE_DISVM_H_