SIM_cancel_realtime_event — cancel callback in host time
#include <simics/simulator-api.h> // in C
import "simics/simulator-api.dml"; // in DML
int
SIM_cancel_realtime_event(int64 id);
import simics
simics.SIM_cancel_realtime_event(...)
Cancel a callback registered by SIM_realtime_event, whose return value is specified as id.
Returns 0 if the callback existed and was cancelled, or -1 if no callback with that identifier existed. (No exception is raised.)
Cell Context
SIM_notify_on_socket, SIM_notify_on_object, SIM_notify_on_descriptor, notify_mode_t — register notification on host I/O events
#include <simics/simulator-api.h> // in C
import "simics/simulator-api.dml"; // in DML
void
SIM_notify_on_socket(socket_t sock, notify_mode_t mode, int run_in_thread,
void (*callback)(lang_void *data), lang_void *data);
void
SIM_notify_on_descriptor(int fd, notify_mode_t mode, int run_in_thread,
void (*callback)(lang_void *data),
lang_void *data);
typedef enum {
Sim_NM_Read, /* when ready for reading/accept, or closed */
Sim_NM_Write /* when ready for writing/connect */
} notify_mode_t;
// other items
void
SIM_notify_on_object(HANDLE obj, int run_in_thread,
void (*callback)(lang_void *data), lang_void *data);
import simics
simics.SIM_notify_on_socket(...)
simics.SIM_notify_on_descriptor(...)
simics.Sim_NM_Write
simics.Sim_NM_Read
These functions allow the function callback to be called with argument data whenever a specific I/O event occurs on the host machine. If callback is a null function pointer, a previously installed notification is removed.
If run_in_thread is 1, the callback function may be run in a thread where it cannot access or call anything in Simics except for these functions and SIM_thread_safe_callback. If run_in_thread is zero, the callback function is always run in Global Context. This may incur a small penalty in latency (time between the occurrence of the host event and execution of callback).
Values other than 0 and 1 for run_in_thread are reserved.
Notification on a specific event will be blocked during the execution of its callback function.
SIM_notify_on_socket will call a registered callback depending on mode:
mode | condition |
|---|---|
Sim_NM_Read | Socket is readable, closed, or incoming connection accepted |
Sim_NM_Write | Socket is writeable, or outgoing connection has completed |
Socket notifiers of the mode Sim_NM_Write are not guaranteed to be called again unless a previous attempt to send data to the socket failed for flow control reasons (that is, it would have blocked).
This means that notifiers of that mode should only be enabled for waiting on the completion of a nonblocking outgoing connection or for a previously “full” socket to accept data again.
Linux only: SIM_notify_on_descriptor will call a registered callback depending on mode for a given file descriptor in a way similar to SIM_notify_on_socket.
Windows only: SIM_notify_on_object will call a registered callback when object (which must be a waitable object) is in signalled state. The signalling object is modified in the same way as the Windows wait functions (WaitForMultipleObjects etc).
A notification should be removed before its socket or descriptor is closed.
On Windows, sockets registered for notification become nonblocking and must remain so for as long as they are registered. This is a limitation of the underlying Win32 API.
Cell Context (call); Threaded Context (callback with nonzero run_in_thread); Global Context (callback otherwise)
SIM_realtime_event — schedule callback in host time
#include <simics/simulator-api.h> // in C
import "simics/simulator-api.dml"; // in DML
int64
SIM_realtime_event(unsigned delay, void (*NOTNULL callback)(lang_void *data),
lang_void *data, int run_in_thread, const char *desc);
import simics
simics.SIM_realtime_event(...)
Register callback to be run in delay ms, with argument data. The delay is in real time (on the host machine), and the actual delay may be somewhat larger because of host scheduling.
If run_in_thread is 1, the callback may be run in a thread where it cannot access or call anything in Simics except for SIM_thread_safe_callback. If run_in_thread is zero, the callback function is always run in Global Context, with the simulation temporarily suspended and the entire Simics API available. This may cause the call to occur slightly later than requested, depending on what Simics is doing at the time.
Values other than 0 and 1 for run_in_thread are reserved.
The desc parameter is only present for debugging and has no other effect; it should be a static string describing the callback but may also be left nullptr if desired.
The callback is only called once.
The return value is a non-zero identifier that can be used to cancel the callback using SIM_cancel_realtime_event.
Cell Context. The callback is called in Threaded Context if run_in_thread is nonzero, in Global Context otherwise.
SIM_register_work, SIM_thread_safe_callback, SIM_run_alone — register function to be called in Global Context
#include <simics/simulator-api.h> // in C
import "simics/simulator-api.dml"; // in DML
void
SIM_register_work(void (*NOTNULL f)(lang_void *data), lang_void *data);
void
SIM_thread_safe_callback(void (*NOTNULL f)(lang_void *data), lang_void *data);
void
SIM_run_alone(void (*NOTNULL f)(lang_void *data), lang_void *data);
import simics
simics.SIM_register_work(...)
simics.SIM_thread_safe_callback(...)
simics.SIM_run_alone(...)
SIM_register_work and SIM_thread_safe_callback register work to be done in Global Context as soon as possible, (but not during the call to SIM_register_work or SIM_thread_safe_callback itself).
SIM_run_alone also registers work to be done in Global Context and if called from Cell Context the callback is executed before the next instruction is dispatched in the cell. If this isn’t used the cell may execute several instructions before the callback is executed. If SIM_run_alone is used while an instruction is being emulated then the callback will be invoked when the current instruction has completed and before the next instruction is dispatched.
No other execution threads are running when the callback is invoked, but their exact position in simulated time may vary between runs. If the callback accesses objects in cells other than the one that SIM_run_alone was called from, then care must be taken to preserve determinism.
When the callback is run, it is executed in Global Context, which means that it is safe to call any API functions from it. Another thread in the module may at this time also call API functions, if it synchronizes correctly with the callback function. For example, the callback function might just signal to the foreign thread to do its Simics API calls, wait for the thread to signal that it has finished, and then return.
Threaded context (call); Global Context (callback)
SIM_run_async_work — launch asynchronous work in a separate thread
#include <simics/simulator-api.h> // in C
import "simics/simulator-api.dml"; // in DML
void
SIM_run_async_work(lang_void *(*NOTNULL async_call)(lang_void *arg),
void (*async_ready)(lang_void *async_ret, lang_void *arg),
lang_void *arg);
import simics
simics.SIM_run_async_work(...)
SIM_run_async_work creates a new thread, running in parallel with the Simics main thread, where the async_call function will be called. Since the function runs in Threaded Context, most Simics API functions are not available. Once the async_call function has run, its return value is passed to async_ready, if supplied, that will be called in Global Context, i.e. in the Simics main thread.
The user supplied arg parameter is passed unmodified to both callback functions.
SIM_run_async_work is typically used when calling functions that would block the main thread for a long time while obtaining their result.
If the result of SIM_run_async_work is used in the simulation, it should be sent through a recorder to make sure that the session can be replayed. See the recorder module and the recorder_v2 interface for more information.
import socket
def async_call(arg):
# runs in separate thread without blocking Simics
return socket.gethostbyname(arg)
def async_ready(ret, arg):
# runs in Simics main thread with access to the full Simics API
print("Host %s has IP address %s" % (arg, ret))
simics.SIM_run_async_work(async_call, async_ready, "www.intel.com")
Cell Context (call); Threaded Context (async_call callback); Global Context (async_ready callback)
SIM_notify_on_descriptor, SIM_notify_on_object, SIM_notify_on_socket, SIM_thread_safe_callback, SIM_run_alone, SIM_run_unrestricted
SIM_run_in_thread — run function in a separate thread
#include <simics/simulator-api.h> // in C
import "simics/simulator-api.dml"; // in DML
void
SIM_run_in_thread(void (*NOTNULL f)(lang_void *arg), lang_void *arg);
import simics
simics.SIM_run_in_thread(...)
SIM_run_in_thread schedules the callback f to run on a separate thread. The callback will run in Threaded Context and must observe the associated restrictions.
Simics maintains a pool of worker threads used by this function, and hence the callback can typically be started quickly.
The callback is allowed to block or otherwise run for a long time.
The user supplied arg parameter is passed unmodified to the callback.
Any thread context (call);
Threaded Context (callback);