ssm
Runtime Library for the Sparse Synchronous Model
ssm.h
Go to the documentation of this file.
1 #ifndef _SSM_H
2 #define _SSM_H
3 
43 #include <stdint.h> /* For uint16_t, UINT64_MAX etc. */
44 #include <stdbool.h> /* For bool, true, false */
45 #include <stdlib.h> /* For size_t */
46 #include <assert.h>
47 #include <stddef.h> /* For offsetof */
48 
54 #ifndef SSM_ACT_MALLOC
55 
59 #define SSM_ACT_MALLOC(size) malloc(size)
60 #endif
61 
62 #ifndef SSM_ACT_FREE
63 
68 #define SSM_ACT_FREE(ptr, size) free(ptr)
69 #endif
70 
71 #ifndef SSM_RESOURCES_EXHAUSTED
72 
77 #define SSM_RESOURCES_EXHAUSTED(string) exit(1)
78 #endif
79 
80 #ifndef SSM_SECOND
81 
85 #define SSM_SECOND 1000000000L
86 #endif
87 
89 #define SSM_NANOSECOND (SSM_SECOND/1000000000L)
90 
91 #define SSM_MICROSECOND (SSM_SECOND/1000000L)
92 
93 #define SSM_MILLISECOND (SSM_SECOND/1000L)
94 
95 #define SSM_MINUTE (SSM_SECOND*60L)
96 
97 #define SSM_HOUR (SSM_SECOND*3600L)
98 
100 typedef uint64_t ssm_time_t;
101 
106 #define SSM_NEVER UINT64_MAX
107 
112 typedef uint32_t ssm_priority_t;
113 
115 #define SSM_ROOT_PRIORITY 0
116 
121 typedef uint8_t ssm_depth_t;
122 
124 #define SSM_ROOT_DEPTH (sizeof(ssm_priority_t) * 8)
125 
126 struct ssm_sv;
127 struct ssm_trigger;
128 struct ssm_act;
129 
131 typedef void ssm_stepf_t(struct ssm_act *);
132 
139 typedef struct ssm_act {
141  struct ssm_act *caller;
142  uint16_t pc;
143  uint16_t children;
146  bool scheduled;
147 } ssm_act_t;
148 
163 #define SSM_ACT_FIELDS \
164  ssm_stepf_t *step; \
165  ssm_act_t *caller; \
166  uint16_t pc; \
167  uint16_t children; \
168  ssm_priority_t priority; \
169  ssm_depth_t depth; \
170  bool scheduled
171 
178 typedef struct ssm_trigger {
179  struct ssm_trigger *next;
182 } ssm_trigger_t;
183 
184 
206 typedef struct ssm_sv {
207  void (*update)(struct ssm_sv *);
211 } ssm_sv_t;
212 
213 
224 extern void ssm_sensitize(ssm_sv_t *, ssm_trigger_t *);
225 
231 extern void ssm_desensitize(ssm_trigger_t *);
232 
242 extern void ssm_activate(ssm_act_t *);
243 
247 static inline void ssm_call(ssm_act_t *act) { (*(act->step))(act); }
248 
258 static inline ssm_act_t *ssm_enter(size_t bytes,
259  ssm_stepf_t *step,
260  ssm_act_t *parent,
263  ) {
264  assert(bytes > 0);
265  assert(step);
266  assert(parent);
267  ++parent->children;
268  ssm_act_t *act = (ssm_act_t *)SSM_ACT_MALLOC(bytes);
269  if (!act) SSM_RESOURCES_EXHAUSTED("ssm_enter");
270  *act = (ssm_act_t){
271  .step = step,
272  .caller = parent,
273  .pc = 0,
274  .children = 0,
275  .priority = priority,
276  .depth = depth,
277  .scheduled = false,
278  };
279  return act;
280 }
281 
285 static inline void ssm_leave(ssm_act_t *act, size_t bytes) {
286  assert(act);
287  assert(act->caller);
288  assert(act->caller->step);
289  ssm_act_t *caller = act->caller;
290  SSM_ACT_FREE(act, bytes); /* Free the whole activation record, not just the start */
291  if ((--caller->children) == 0)
292  ssm_call(caller); /* If we were the last child, run our parent */
293 }
294 
297 bool ssm_event_on(ssm_sv_t *var );
298 
304 void ssm_initialize(ssm_sv_t *var,
305  void (*update)(ssm_sv_t *));
306 
312 void ssm_schedule(ssm_sv_t *var,
313  ssm_time_t later);
315 
322 void ssm_unschedule(ssm_sv_t *var);
323 
333 void ssm_trigger(ssm_sv_t *var,
336  );
337 
343 
345 ssm_time_t ssm_now(void);
346 
361 void ssm_tick();
362 
369 void ssm_reset();
370 
392 
393 
398 #ifdef __GNUC__
399 #define member_type(type, member) __typeof__(((type *)0)->member)
400 #else
401 #define member_type(type, member) const void
402 #endif
403 #define container_of(ptr, type, member) \
404  ((type *)((char *)(member_type(type, member) *){ptr} - \
405  offsetof(type, member)))
406 
408 #define ssm_later_event(var, then) ssm_schedule((var), (then))
409 extern void ssm_assign_event(ssm_event_t *var, ssm_priority_t prio);
410 extern void ssm_initialize_event(ssm_event_t *);
411 
412 
413 #define SSM_DECLARE_SV_SCALAR(payload_t) \
414  typedef struct { \
415  ssm_sv_t sv; \
416  payload_t value; /* Current value */ \
417  payload_t later_value; /* Buffered value */ \
418  } ssm_##payload_t##_t; \
419  void ssm_assign_##payload_t(ssm_##payload_t##_t *sv, ssm_priority_t prio, \
420  const payload_t value); \
421  void ssm_later_##payload_t(ssm_##payload_t##_t *sv, ssm_time_t then, \
422  const payload_t value); \
423  void ssm_initialize_##payload_t(ssm_##payload_t##_t *v);
424 
425 #define SSM_DEFINE_SV_SCALAR(payload_t) \
426  static void ssm_update_##payload_t(ssm_sv_t *sv) { \
427  ssm_##payload_t##_t *v = container_of(sv, ssm_##payload_t##_t, sv); \
428  v->value = v->later_value; \
429  } \
430  void ssm_assign_##payload_t(ssm_##payload_t##_t *v, ssm_priority_t prio, \
431  const payload_t value) { \
432  v->value = value; \
433  v->sv.last_updated = ssm_now(); \
434  ssm_trigger(&v->sv, prio); \
435  } \
436  void ssm_later_##payload_t(ssm_##payload_t##_t *v, ssm_time_t then, \
437  const payload_t value) { \
438  v->later_value = value; \
439  ssm_schedule(&v->sv, then); \
440  } \
441  void ssm_initialize_##payload_t(ssm_##payload_t##_t *v) { \
442  ssm_initialize(&v->sv, ssm_update_##payload_t); \
443  }
444 
445 typedef int8_t i8;
446 typedef int16_t i16;
447 typedef int32_t i32;
448 typedef int64_t i64;
449 typedef uint8_t u8;
450 typedef uint16_t u16;
451 typedef uint32_t u32;
452 typedef uint64_t u64;
482 
486 // FIXME!
487 #include "ssm-debug.h"
488 
489 #endif
490 
uint8_t ssm_depth_t
Index of least significant bit in a group of priorities.
Definition: ssm.h:121
ssm_depth_t depth
Index of the LSB in our priority.
Definition: ssm.h:145
#define SSM_ACT_MALLOC(size)
Allocation function for activation records.
Definition: ssm.h:59
uint64_t ssm_time_t
Absolute time; never to overflow.
Definition: ssm.h:100
uint32_t u32
32-bit Unsigned Integer
Definition: ssm.h:451
struct ssm_act * caller
Activation record of caller.
Definition: ssm.h:141
bool scheduled
True when in the schedule queue.
Definition: ssm.h:146
#define SSM_ACT_FREE(ptr, size)
Free function for activation records.
Definition: ssm.h:68
A variable that may have scheduled updates and triggers.
Definition: ssm.h:206
ssm_time_t ssm_next_event_time(void)
Return the time of the next event in the queue or SSM_NEVER.
Definition: ssm-scheduler.c:177
static ssm_act_t * ssm_enter(size_t bytes, ssm_stepf_t *step, ssm_act_t *parent, ssm_priority_t priority, ssm_depth_t depth)
Enter a routine.
Definition: ssm.h:258
int64_t i64
64-bit Signed Integer
Definition: ssm.h:448
void ssm_trigger(ssm_sv_t *var, ssm_priority_t priority)
Activate routines triggered by a variable.
Definition: ssm-scheduler.c:105
ssm_time_t later_time
When the variable should be next updated.
Definition: ssm.h:209
#define SSM_RESOURCES_EXHAUSTED(string)
Invoked when limited resources are exhausted, e.g., unable to allocate memory, no more queue space...
Definition: ssm.h:77
struct ssm_act ssm_act_t
Activation record for an SSM routine.
void ssm_unschedule(ssm_sv_t *var)
Unschedule any pending event on a variable.
Definition: ssm-scheduler.c:292
ssm_sv_t ssm_event_t
Definition: ssm.h:407
ssm_time_t last_updated
When the variable was last updated.
Definition: ssm.h:210
static void ssm_leave(ssm_act_t *act, size_t bytes)
Deallocate an activation record; return to caller if we were the last child.
Definition: ssm.h:285
void ssm_sensitize(ssm_sv_t *, ssm_trigger_t *)
Indicate writing to a variable should trigger a routine.
Definition: ssm-scheduler.c:73
ssm_act_t * act
Routine triggered by this channel variable.
Definition: ssm.h:181
struct ssm_trigger * next
Next sensitive trigger, if any.
Definition: ssm.h:179
bool ssm_event_on(ssm_sv_t *var)
Return true if there is an event on the given variable in the current instant.
Definition: ssm-scheduler.c:67
Indicates a routine should run when a scheduled variable is written.
Definition: ssm.h:178
struct ssm_trigger ** prev_ptr
Pointer to ourself in previous list element.
Definition: ssm.h:180
int16_t i16
16-bit Signed Integer
Definition: ssm.h:446
uint16_t u16
16-bit Unsigned Integer
Definition: ssm.h:450
uint64_t u64
64-bit Unsigned Integer
Definition: ssm.h:452
int8_t i8
8-bit Signed Integer
Definition: ssm.h:445
ssm_time_t ssm_now(void)
Return the current model time.
Definition: ssm-scheduler.c:182
int32_t i32
32-bit Signed Integer
Definition: ssm.h:447
uint32_t ssm_priority_t
Thread priority.
Definition: ssm.h:112
struct ssm_sv ssm_sv_t
A variable that may have scheduled updates and triggers.
void ssm_reset()
Reset the scheduler.
Definition: ssm-scheduler.c:60
void ssm_schedule(ssm_sv_t *var, ssm_time_t later)
Schedule a future update to a variable.
Definition: ssm-scheduler.c:264
ssm_priority_t priority
Execution priority; lower goes first.
Definition: ssm.h:144
void ssm_desensitize(ssm_trigger_t *)
Disable a sensitized routine.
Definition: ssm-scheduler.c:92
void ssm_initialize_event(ssm_event_t *)
Definition: ssm-event.c:14
ssm_stepf_t * step
C function for running this continuation.
Definition: ssm.h:140
ssm_trigger_t * triggers
List of sensitive continuations.
Definition: ssm.h:208
void(* update)(struct ssm_sv *)
Update "virtual method".
Definition: ssm.h:207
Activation record for an SSM routine.
Definition: ssm.h:139
uint16_t children
Number of running child threads.
Definition: ssm.h:143
void ssm_assign_event(ssm_event_t *var, ssm_priority_t prio)
Definition: ssm-event.c:3
#define SSM_DECLARE_SV_SCALAR(payload_t)
Definition: ssm.h:413
void ssm_activate(ssm_act_t *)
Schedule a routine to run in the current instant.
Definition: ssm-scheduler.c:164
struct ssm_trigger ssm_trigger_t
Indicates a routine should run when a scheduled variable is written.
uint8_t u8
8-bit Unsigned Integer
Definition: ssm.h:449
static void ssm_call(ssm_act_t *act)
Execute a routine immediately.
Definition: ssm.h:247
void ssm_tick()
Run the system for the next scheduled instant.
Definition: ssm-scheduler.c:307
void ssm_stepf_t(struct ssm_act *)
The function that does an instant&#39;s work for a routine.
Definition: ssm.h:131
uint16_t pc
Stored "program counter" for the function.
Definition: ssm.h:142
ssm_act_t ssm_top_parent
An activation record for the parent of the topmost routine.
Definition: ssm-top-act.c:5
void ssm_initialize(ssm_sv_t *var, void(*update)(ssm_sv_t *))
Initialize a scheduled variable.
Definition: ssm-scheduler.c:203