TEMU  4.0
The Terma Emulator
Events.h
Go to the documentation of this file.
1 //===-- temu-c/Events.h - Event Queue API -----------------------*- C++ -*-===//
2 //
3 // TEMU: The Terma Emulator
4 // (c) Terma 2015, 2016
5 // Authors: Mattias Holm <maho (at) terma.com>
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef TEMU_EVENTS_H
10 #define TEMU_EVENTS_H
11 
12 #include "temu-c/Support/Attributes.h"
13 #include "temu-c/Support/Objsys.h"
14 #include <stdint.h>
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 // Synchronisation events
20 typedef enum {
21  teSE_Cpu, // Trigger event when CPU reaches timer
22  teSE_Machine, // Synchronise event on machine
23 } temu_SyncEvent;
24 
25 typedef struct temu_EventQueue temu_EventQueue;
26 
30  temu_EventQueue *Queue;
31  int64_t Frequency;
32  int64_t Steps;
33  temu_SyncEvent Level;
34  int64_t NextEvent;
35  int64_t StartSteps;
36  int64_t TargetSteps;
37  uint16_t InstructionsPerCycle; // Fixed point storage of IPC factor
38  uint16_t CyclesPerInstruction; // Fixed point storage of CPI factor
39 };
40 
41 typedef struct temu_Event {
42  int64_t Steps; //!< Managed internally, do not touch
43  int64_t Time; //!< Managed internally, do not touch
44  int64_t EventId; //!< Managed internally, do not touch
45  uint32_t Flags; //!< Internal use, do not touch
46  int QueueIdx; //!< Managed internally, do not touch
47  temu_TimeSource *Queue; //!< Managed internally, do not touch
48  temu_Object *Obj; //!< Managed internally, only for reading
49  //! Event callback
50  void (*Func)(struct temu_Event *);
51  int64_t Period; //!< Managed: Period (cycles) for cyclic events
52  int64_t RTTime; //!< Managed: Time (monotonic ns) for RT exec
53  int64_t RTPeriod; //!< Managed: Period (ns) for RT events
54  int64_t TriggerCount; //!< Managed: Number of time event has been triggered
55 } temu_Event;
56 
57 //! Posting callback from other threads
58 typedef void (*temu_ThreadSafeCb)(void *);
59 
60 /*!
61  Publish a preallocated event object.
62 
63  The event objects can be embedded in your own class if needed.
64 
65  \param EvName Name of the event
66  \param Ev Pointer to the event struct
67  \param Obj The object associated with the event
68  \param Func The event callback function.
69  \result The event ID.
70  */
71 TEMU_API int64_t temu_eventPublishStruct(const char *EvName, temu_Event *Ev,
72  void *Obj, void (*Func)(temu_Event *));
73 
74 /*!
75  * It is possible to depublish events explicitly, but this is rarely
76  * needed as it is managed at termination time automatically.
77  *
78  * \param EvID Event ID
79  */
81 
82 /*!
83  Publish an event.
84 
85  The function will allocate an event structure in the global event
86  heap and return the event ID.
87 
88  A typical use is to call the function in the object constructor
89  and assign the event id to a field in the object. This field should not
90  be snapshotted (i.e. it will be reassigned in the constructor) when
91  restoring an object anyway.
92 
93  \note This function is non thread safe. Object construction is expected
94  to be done in a single thread (e.g. the main thread).
95 
96  \param EvName Name of the event
97  \param Obj The object associated with the event
98  \param Func The event callback function.
99  \result The event ID >= 0 in case of success. Negative values
100  indicate errors.
101  */
102 TEMU_API int64_t temu_eventPublish(const char *EvName, void *Obj,
103  void (*Func)(temu_Event *));
104 
105 /*!
106  * Post events with a relative trigger in steps
107  *
108  * Posting an event in steps is not effected by the IPC/CPI setting of the clock.
109  *
110  * \param TS The time source object (normally a CPU object)
111  * \param EvID The even ID returned by one of the event publish functions.
112  * \param Delta The number of CPU steps in the future to post the event.
113  * This should be > 0.
114  * \param Sync whether the event should be executed on the CPU queue or the
115  * machine queue.
116  */
119 /*!
120  * Post events with a relative time in cycles in the future
121  *
122  * Note that if posting a scheduled event, a warning will be printed
123  * and the event will be automatically descheduled before being
124  * inserted in the event queue.
125  *
126  * \param TS The time source object (normally a CPU object)
127  * \param EvID The even ID returned by one of the event publish functions.
128  * \param Delta The number of CPU clock cycles in the future to post the event.
129  * This should be > 0.
130  * \param Sync whether the event should be executed on the CPU queue or the
131  * machine queue.
132  */
135 /*!
136  * Post events with a relative time in nanoseconds in the future
137  * \param TS The time source object (normally a CPU object)
138  * \param EvID The even ID returned by one of the event publish functions.
139  * \param Delta The number of nanoseconds in the future to post the event.
140  * This should be > 0.
141  * \param Sync whether the event should be executed on the CPU queue or the
142  * machine queue.
143  */
144 
147 /*!
148  * Post events with a relative time in seconds in the future
149  * \param TS The time source object (normally a CPU object)
150  * \param EvID The even ID returned by one of the event publish functions.
151  * \param Delta The number of seconds in the future to post the event.
152  * This should be > 0.
153  * \param Sync whether the event should be executed on the CPU queue or the
154  * machine queue.
155  */
157  double Delta, temu_SyncEvent Sync);
158 
159 /*!
160  * Post events in the event queue stack
161  *
162  * Stacked events are executed either after the current instruction is
163  * finished or when the machine quanta expires in case of machine
164  * synchronised events.
165  *
166  * \param TS The time source object (normally a CPU object)
167  * \param EvID The even ID returned by one of the event publish functions.
168  * \param Sync whether the event should be executed on the CPU queue or the
169  * machine queue.
170  */
173 
174 
175 /*!
176  * Post events with an absolute time in cycles
177  * The function is only well defined for times >= current time.
178  * Timestamps < current time will have undefined behaviour.
179  * \param TS The time source object (normally a CPU object)
180  * \param EvID The even ID returned by one of the event publish functions.
181  * \param AbsTime The absolute time stamp to run the event at, this should be >
182  * current time.
183  * \param Sync whether the event should be executed on the CPU
184  * queue or the machine queue.
185  */
188 
189 /*!
190  * Post events with an absolute time in nanoseconds
191  * The function is only well defined for times >= current time.
192  * Timestamps < current time will have undefined behaviour.
193  * \param TS The time source object (normally a CPU object)
194  * \param EvID The even ID returned by one of the event publish functions.
195  * \param AbsTime The absolute time stamp to run the event at, this should be >
196  * current time.
197  * \param Sync whether the event should be executed on the CPU
198  * queue or the machine queue.
199  */
200 
203 
204 
205 /*!
206  * Reschedule event with relative time in cycles
207  *
208  * This function automatically deschedules the event before scheduling it again.
209  * The function ensures only one lock is taken for the pattern:
210  *
211  * - is scheduled?
212  * - de-schedule
213  * - post
214  *
215  * \param TS The time source object (normally a CPU object)
216  * \param EvID The even ID returned by one of the event publish functions.
217  * \param Delta The number of CPU clock cycles in the future to post the event.
218  * This should be > 0.
219  * \param Sync whether the event should be executed on the CPU queue or the
220  * machine queue.
221  */
222 
223 TEMU_API
226 /*!
227  * Check if event is scheduled
228  *
229  * \param EvID The event ID to check whether it is scheduled.
230  *
231  * \result Zero (0) in case the event is not scheduled, otherwise
232  * non-zero for scheduled events.
233  */
235 
236 /*!
237  * Deschedule event
238  *
239  * \param EvID The event ID of the event to deschedule.
240  */
242 
243 /*!
244  * Get delta time in cycles for the given event and queue
245  *
246  * \param TS The time source object (normally a CPU object)
247  * \param EvID the event to get the cycles for.
248  * \result Number of simulated cycles in the future the event will trigger
249  */
250 TEMU_API int64_t temu_eventGetCycles(temu_TimeSource *TS, int64_t EvID);
251 
252 /*!
253  * Get delta time in nanoseconds for the given event and queue
254  *
255  * \param TS The time source object (normally a CPU object)
256  * \param EvID the event to get the nanoseconds for.
257  * \result Number of simulated nanoseconds in the future when the event will
258  * trigger
259  */
260 TEMU_API int64_t temu_eventGetNanos(temu_TimeSource *TS, int64_t EvID);
261 
262 /*!
263  * Get delta time in seconds for the given event and queue
264  *
265  * \param TS The time source object (normally a CPU object)
266  * \param EvID the event to get the seconds for.
267  * \result Number of simulated seconds in the future when the event will trigger
268  */
270 
271 //======================== EXPERIMENTAL API ==================================//
272 /*! Flags for async functions below. */
273 #define TEMU_ASYNC_CYCLIC 1
274 #define TEMU_ASYNC_READ (1 << 1)
275 #define TEMU_ASYNC_WRITE (1 << 2)
276 
277 /*!
278  * Add asynchronously activated wall-clock timed events
279  *
280  * The callback function will be called synchronously by the emulator
281  * core associated with Q. That means that when CB is executing it is
282  * safe to do anything that can be done from a normal event or MMIO
283  * handler.
284  *
285  * Note that the event is only called when a CPU core or machine is
286  * running. When the timer has triggered, it is temporarily disabled
287  * and the CB is posted on the synchornous event queue as an async
288  * event. This will be executed when the next normal event expires
289  * (e.g. at the end of the current quanta). After the event has been
290  * called, depending on wether the timer is cyclic or not, it will be
291  * reactivated. This means that if the emulator is paused, at most one
292  * call to the event handler will be issued, and this will be done
293  * when the emulator is resumed.
294  *
295  * \param TS The time source object (normally a CPU object)
296  *
297  * \param T Delta seconds in the future for the first event to be posted.
298  *
299  * \param Flags Set to TEMU_ASYNC_CYCLIC if the event should be
300  * executed as a cyclic event.
301  * \param CB Call back function on when timer expires
302  * \param Data Context data to be passed to the callback function
303  *
304  * \result Returns a file descriptor or timer ID.
305  */
306 TEMU_API int temu_asyncTimerAdd(temu_TimeSource *TS, double T, unsigned Flags,
307  void (*CB)(void *), void *Data);
308 
309 /*!
310  * Remove an async timer
311  *
312  * \param Fd Timer ID to remove
313  */
315 
316 /*!
317  * Add asynchronous event triggered by file descriptor changes
318  *
319  * \param TS the synchronous queue or time source object (normally a CPU object)
320  *
321  * \param Sock File descriptor for the socket. This can also be a pipe
322  * FD. Note that the function is likely to be renamed.
323  * Note that in case you are intending to read from the socket,
324  * make sure it is non-blocking.
325  *
326  * \param Flags TEMU_ASYNC_READ in case you wish to be notified about
327  * data available to read.
328  *
329  * \result Returns the file descriptor (Sock)
330  * if successful, otherwise -1.
331  */
333  void (*CB)(void *), void *Data);
334 
335 /*!
336  * Remove an asynchronous event triggered by file descriptor changes
337  *
338  * \param Fd The ID of the socket to remove
339  * \param Flags The flags of removing
340  */
341 TEMU_API void temu_asyncSocketRemove(int Fd, unsigned Flags);
342 
343 /*!
344  * Post an event to an asynchronous queue
345  *
346  * \param TS the asynchronous queue or time source object (normally a CPU
347  * object) \param CB The callback function to call when the event happens \param
348  * Data The context data to be passed to the callback function \param Sync
349  * Execute on CPU or machine level.
350  */
352  void *Data, temu_SyncEvent Sync);
353 
354 /*!
355  * Mark an event as real-time.
356  *
357  * With a real-time event, it is meant that the event will execute at
358  * roughly real-time. In the case when the event is posted, it will
359  * compute a rough triggering time in wall clock. When the event is
360  * executed it will do two things:
361  *
362  * 1. Check if the event wall-clock time is before the current time,
363  * if so emit a "temu.realtime-slip" notification".
364  *
365  * 2. Check if the event is triggered in the future (with respect to
366  * wall clock), if so sleep until the wall-clock has caught
367  * up.
368  *
369  * Due to the behaviour, the real-time events are suitable only for
370  * relatively short event times, as long sleep times may make the
371  * emulator non responsive. Especially at present, this will block the
372  * execution of async events as the event queue is halted until the
373  * wall-clock catches up to the simulated time.
374  *
375  * Note that RT event support is primarily used to slow down the
376  * emulator artificially, this is accomplished by enabling real-time
377  * mode on the relevant model.
378  *
379  * This function should only be called on in-flight events.
380  *
381  * \param EvID Event ID to make real-time
382  * \result 0 On success.
383  */
385 
386 /*!
387  * Set the cycles property on an event.
388  *
389  * Periodic events have the advantage that they do not slip due to
390  * reposting of event with respect to the event triggering time and
391  * behaves as if the reposting is 1, automatic and 2, is relative to
392  * the event schedule time. which differ from the triggering time by
393  * possibly a few cycles. Note, calling this function does not
394  * reschedule the event.
395  *
396  * \param EvID Event ID
397  * \param Period Cycles to add as period.
398  */
400 
401 /*!
402  * Set the RT period (nanoseconds), this should be the same as the
403  * cycle period, but it should be in nanoseconds and tno cycles
404  *
405  * \param EvID Event ID
406  * \param Period Period in nanoseconds
407  */
409 
410 /*!
411  * Set the RT time (nanoseconds absoulute time computed from
412  * temu_timeGetMonotonicWct()). This time is used by events flagged
413  * with TEMU_EVENT_RT to delay the execution of the event handler
414  * function.
415  *
416  * \param EvID Event ID
417  * \param Time Absolute time to trigger event at in WCT
418  */
419 
421 
422 /*!
423  * Get the frequency in Hz of the given time source.
424  * \param TS Time source
425  */
426 TEMU_API uint64_t temu_eventQueueGetFreq(temu_TimeSource *TS);
427 
428 //================= END OF EXPERIMENTAL API ==================================//
429 
430 #ifdef __cplusplus
431 }
432 #endif
433 
434 #endif /* ! TEMU_EVENTS_H */
temu_EventQueue
struct temu_EventQueue temu_EventQueue
Definition: Events.h:25
temu_eventPostNanosAbsolute
TEMU_API void temu_eventPostNanosAbsolute(temu_TimeSource *TS, int64_t EvID, int64_t AbsTime, temu_SyncEvent Sync)
teSE_Cpu
@ teSE_Cpu
Definition: Events.h:21
temu_eventPostAsync
TEMU_API void temu_eventPostAsync(temu_TimeSource *TS, temu_ThreadSafeCb CB, void *Data, temu_SyncEvent Sync)
temu_asyncTimerAdd
TEMU_API int temu_asyncTimerAdd(temu_TimeSource *TS, double T, unsigned Flags, void(*CB)(void *), void *Data)
temu_Event::Period
int64_t Period
Managed: Period (cycles) for cyclic events.
Definition: Events.h:51
temu_TimeSource::Super
temu_Object Super
Definition: Events.h:28
temu_TimeSource::Queue
temu_EventQueue * Queue
Definition: Events.h:30
temu_eventSetRealTime
TEMU_API int temu_eventSetRealTime(int64_t EvID)
temu_TimeSource::InstructionsPerCycle
uint16_t InstructionsPerCycle
Definition: Events.h:37
temu_eventPostStack
TEMU_API void temu_eventPostStack(temu_TimeSource *TS, int64_t EvID, temu_SyncEvent Sync)
temu_eventIsScheduled
TEMU_API int temu_eventIsScheduled(int64_t EvID)
temu_eventDepublish
TEMU_API void temu_eventDepublish(int64_t EvID)
temu_Event::RTTime
int64_t RTTime
Managed: Time (monotonic ns) for RT exec.
Definition: Events.h:52
temu_eventGetSecs
TEMU_API double temu_eventGetSecs(temu_TimeSource *TS, int64_t EvID)
temu_eventPostSteps
TEMU_API void temu_eventPostSteps(temu_TimeSource *TS, int64_t EvID, int64_t Delta, temu_SyncEvent Sync)
temu_TimeSource::TargetSteps
int64_t TargetSteps
Definition: Events.h:36
temu_eventRescheduleCycles
TEMU_API void temu_eventRescheduleCycles(temu_TimeSource *TS, int64_t EvID, int64_t Delta, temu_SyncEvent Sync)
temu_Event::RTPeriod
int64_t RTPeriod
Managed: Period (ns) for RT events.
Definition: Events.h:53
temu_eventPostNanos
TEMU_API void temu_eventPostNanos(temu_TimeSource *TS, int64_t EvID, int64_t Delta, temu_SyncEvent Sync)
temu_Event::Queue
temu_TimeSource * Queue
Managed internally, do not touch.
Definition: Events.h:47
temu_Event::Flags
uint32_t Flags
Internal use, do not touch.
Definition: Events.h:45
temu_TimeSource::Level
temu_SyncEvent Level
Definition: Events.h:33
temu_TimeSource::Frequency
int64_t Frequency
Definition: Events.h:31
temu_Event::Func
void(* Func)(struct temu_Event *)
Event callback.
Definition: Events.h:50
temu_Event::Obj
temu_Object * Obj
Definition: Events.h:48
teSE_Machine
@ teSE_Machine
Definition: Events.h:22
temu_TimeSource::Steps
int64_t Steps
Definition: Events.h:32
temu_TimeSource::CyclesPerInstruction
uint16_t CyclesPerInstruction
Definition: Events.h:38
temu_eventPostSecs
TEMU_API void temu_eventPostSecs(temu_TimeSource *TS, int64_t EvID, double Delta, temu_SyncEvent Sync)
temu_TimeSource::ParentTimeSource
temu_TimeSource * ParentTimeSource
Definition: Events.h:29
temu_TimeSource::StartSteps
int64_t StartSteps
Definition: Events.h:35
temu_eventSetPeriodCycles
TEMU_API void temu_eventSetPeriodCycles(int64_t EvID, int64_t Period)
temu_TimeSource
struct temu_TimeSource temu_TimeSource
Definition: Scheduler.h:16
temu_eventPostCycles
TEMU_API void temu_eventPostCycles(temu_TimeSource *TS, int64_t EvID, int64_t Delta, temu_SyncEvent Sync)
temu_Event
Definition: Events.h:41
temu_Event::TriggerCount
int64_t TriggerCount
Managed: Number of time event has been triggered.
Definition: Events.h:54
temu_Event::Time
int64_t Time
Managed internally, do not touch.
Definition: Events.h:43
temu_asyncSocketRemove
TEMU_API void temu_asyncSocketRemove(int Fd, unsigned Flags)
temu_eventDeschedule
TEMU_API void temu_eventDeschedule(int64_t EvID)
temu_TimeSource::NextEvent
int64_t NextEvent
Definition: Events.h:34
temu_Event::EventId
int64_t EventId
Managed internally, do not touch.
Definition: Events.h:44
temu_eventPostCyclesAbsolute
TEMU_API void temu_eventPostCyclesAbsolute(temu_TimeSource *TS, int64_t EvID, int64_t AbsTime, temu_SyncEvent Sync)
temu_Event::QueueIdx
int QueueIdx
Managed internally, do not touch.
Definition: Events.h:46
temu_eventSetRTPeriodNanos
TEMU_API void temu_eventSetRTPeriodNanos(int64_t EvID, int64_t Period)
temu_Event::Steps
int64_t Steps
Managed internally, do not touch.
Definition: Events.h:42
temu_ThreadSafeCb
void(* temu_ThreadSafeCb)(void *)
Posting callback from other threads.
Definition: Events.h:58
temu_asyncTimerRemove
TEMU_API void temu_asyncTimerRemove(int Fd)
temu_asyncSocketAdd
TEMU_API int temu_asyncSocketAdd(temu_TimeSource *TS, int Sock, unsigned Flags, void(*CB)(void *), void *Data)
temu_eventSetRTTime
TEMU_API void temu_eventSetRTTime(int64_t EvID, int64_t Time)