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