reactor-c
C Runtime for Lingua Franca
Loading...
Searching...
No Matches
reactor_common.c File Reference

Runtime infrastructure common to the threaded and single-threaded versions of the C runtime. More...

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "low_level_platform.h"
#include "api/schedule.h"
#include "port.h"
#include "pqueue.h"
#include "reactor.h"
#include "tracepoint.h"
#include "util.h"
#include "vector.h"
#include "lf_core_version.h"
#include "hashset/hashset.h"
#include "hashset/hashset_itr.h"
#include "environment.h"
#include "reactor_common.h"
#include "watchdog.h"

Functions

voidlf_allocate (size_t count, size_t size, struct allocation_record_t **head)
 Allocate memory and record on the specified allocation record (a self struct).
 
self_base_tlf_new_reactor (size_t size)
 Allocate memory for a new runtime instance of a reactor.
 
void lf_free (struct allocation_record_t **head)
 Free memory on the specified allocation record (a self struct).
 
void lf_free_reactor (self_base_t *self)
 Free the specified reactor.
 
void lf_free_all_reactors (void)
 Free all the reactors that are allocated with lf_new_reactor(size_t).
 
void lf_set_stop_tag (environment_t *env, tag_t tag)
 Set the stop tag if it is less than the stop tag of the specified environment.
 
void _lf_start_time_step (environment_t *env)
 Perform whatever is needed to start a time step.
 
bool lf_is_tag_after_stop_tag (environment_t *env, tag_t tag)
 Return true if the provided tag is after stop tag.
 
void _lf_pop_events (environment_t *env)
 Pop all events from event_q with tag equal to current tag.
 
event_tlf_get_new_event (environment_t *env)
 
void _lf_initialize_timer (environment_t *env, trigger_t *timer)
 Initialize the given timer. If this timer has a zero offset, enqueue the reactions it triggers. If this timer is to trigger reactions at a future tag as well, schedule it accordingly.
 
void _lf_initialize_timers (environment_t *env)
 Initialize all the timers in the environment.
 
void _lf_trigger_startup_reactions (environment_t *env)
 Trigger all the startup reactions in the specified environment.
 
void _lf_trigger_shutdown_reactions (environment_t *env)
 Trigger all the shutdown reactions in the specified environment.
 
void lf_recycle_event (environment_t *env, event_t *e)
 Recycle the given event.
 
event_t_lf_create_dummy_events (environment_t *env, tag_t tag)
 Create a dummy event with the specified tag.
 
void lf_replace_token (event_t *event, lf_token_t *token)
 
trigger_handle_t _lf_schedule_at_tag (environment_t *env, trigger_t *trigger, tag_t tag, lf_token_t *token)
 Schedule an event at a specific tag (time, microstep).
 
trigger_handle_t _lf_insert_reactions_for_trigger (environment_t *env, trigger_t *trigger, lf_token_t *token)
 Insert reactions triggered by trigger to the reaction queue.
 
void _lf_advance_tag (environment_t *env, tag_t next_tag)
 
void _lf_invoke_reaction (environment_t *env, reaction_t *reaction, int worker)
 
void schedule_output_reactions (environment_t *env, reaction_t *reaction, int worker)
 
void usage (int argc, const char *argv[])
 
int process_args (int argc, const char *argv[])
 
void initialize_global (void)
 Check that the provided version information is consistent with the core runtime.
 
void termination (void)
 Perform final wrap-up on exit.
 
index_t lf_combine_deadline_and_level (interval_t deadline, int level)
 Combine a deadline and a level into a single index for sorting in the reaction queue.
 

Variables

instant_t start_time
 
int _lf_count_payload_allocations
 
bool fast = false
 
unsigned int _lf_number_of_workers = 0u
 
instant_t duration = -1LL
 
bool keepalive_specified = false
 
struct allocation_record_t_lf_reactors_to_free = NULL
 
int default_argc = 0
 
const char ** default_argv = NULL
 
bool _lf_termination_executed = false
 
bool _lf_normal_termination = false
 

Detailed Description

Runtime infrastructure common to the threaded and single-threaded versions of the C runtime.

Author
Edward A. Lee
Marten Lohstroh
Soroush Bateni
Mehrdad Niknami
Alexander Schulz-Rosengarten
Erling Rennemo Jellum

Function Documentation

◆ _lf_advance_tag()

void _lf_advance_tag ( environment_t * env,
tag_t next_tag )

Advance from the current tag to the next. If the given next_time is equal to the current time, then increase the microstep. Otherwise, update the current time and set the microstep to zero.

Parameters
envThe environment in which we are executing
next_tagThe tag step to advance to.

◆ _lf_create_dummy_events()

event_t * _lf_create_dummy_events ( environment_t * env,
tag_t tag )

Create a dummy event with the specified tag.

A dummy event is an event with no triggers that can be put on the event queue to trigger a tag advance to the specified tag.

Parameters
envEnvironment in which we are executing.
tagThe tag of that event.
Returns
A pointer to the dummy event.

◆ _lf_initialize_timer()

void _lf_initialize_timer ( environment_t * env,
trigger_t * timer )

Initialize the given timer. If this timer has a zero offset, enqueue the reactions it triggers. If this timer is to trigger reactions at a future tag as well, schedule it accordingly.

Parameters
envEnvironment in which we are executing.
timerThe timer to initialize.

◆ _lf_initialize_timers()

void _lf_initialize_timers ( environment_t * env)

Initialize all the timers in the environment.

Parameters
envEnvironment in which we are executing.

◆ _lf_insert_reactions_for_trigger()

trigger_handle_t _lf_insert_reactions_for_trigger ( environment_t * env,
trigger_t * trigger,
lf_token_t * token )

Insert reactions triggered by trigger to the reaction queue.

Parameters
envEnvironment in which we are executing.
triggerThe trigger.
tokenThe token wrapping the payload or NULL for no payload.
Returns
1 if successful, or 0 if no new reaction was scheduled because the function was called incorrectly.

◆ _lf_invoke_reaction()

void _lf_invoke_reaction ( environment_t * env,
reaction_t * reaction,
int worker )

Invoke the given reaction

Parameters
envEnvironment in which we are executing.
reactionThe reaction that has just executed.
workerThe thread number of the worker thread or 0 for single-threaded execution (for tracing).

◆ _lf_pop_events()

void _lf_pop_events ( environment_t * env)

Pop all events from event_q with tag equal to current tag.

This will extract all the reactions triggered by these events and stick them onto the reaction queue.

Parameters
envThe environment in which we are executing

◆ _lf_schedule_at_tag()

trigger_handle_t _lf_schedule_at_tag ( environment_t * env,
trigger_t * trigger,
tag_t tag,
lf_token_t * token )

Schedule an event at a specific tag (time, microstep).

If there is an event found at the requested tag, the payload is replaced and 0 is returned.

Note that this function is an internal API that must be called with a tag that is in the future relative to the current tag (or the environment has not started executing). Also, it must be called with tags that are in order for a given trigger. This means that the following order is illegal:

return address
Definition hashmap.h:74
trigger_handle_t _lf_schedule_at_tag(environment_t *env, trigger_t *trigger, tag_t tag, lf_token_t *token)
Schedule an event at a specific tag (time, microstep).
Definition reactor_common.c:473

where bigger_tag > smaller_tag. This function is primarily used for network communication (which is assumed to be in order).

This function assumes the caller holds the mutex lock.

Parameters
envEnvironment in which we are executing.
triggerThe trigger to be invoked at a later logical time.
tagLogical tag of the event
tokenThe token wrapping the payload or NULL for no payload.
Returns
A positive trigger handle for success, 0 if no new event was scheduled (instead, the payload was updated), or -1 for error (the tag is equal to or less than the current tag).

◆ _lf_start_time_step()

void _lf_start_time_step ( environment_t * env)

Perform whatever is needed to start a time step.

For example, this function resets outputs to be absent at the start of a new time step.

Parameters
envThe environment in which we are executing

◆ _lf_trigger_shutdown_reactions()

void _lf_trigger_shutdown_reactions ( environment_t * env)

Trigger all the shutdown reactions in the specified environment.

Parameters
envEnvironment in which we are executing.

◆ _lf_trigger_startup_reactions()

void _lf_trigger_startup_reactions ( environment_t * env)

Trigger all the startup reactions in the specified environment.

Parameters
envEnvironment in which we are executing.

◆ initialize_global()

void initialize_global ( void )

Check that the provided version information is consistent with the core runtime.

Initialize global variables and start tracing before calling the _lf_initialize_trigger_objects function.

◆ lf_allocate()

void * lf_allocate ( size_t count,
size_t size,
struct allocation_record_t ** head )

Allocate memory and record on the specified allocation record (a self struct).

This will allocate memory using calloc (so the allocated memory is zeroed out) and record the allocated memory on the specified self struct so that it will be freed when calling free_reactor(self_base_t).

Parameters
countThe number of items of size 'size' to accomodate.
sizeThe size of each item.
headPointer to the head of a list on which to record the allocation, or NULL to not record it (an allocation_record_t**),
Returns
A pointer to the allocated memory.

◆ lf_combine_deadline_and_level()

index_t lf_combine_deadline_and_level ( interval_t deadline,
int level )

Combine a deadline and a level into a single index for sorting in the reaction queue.

This shifts the deadline right by 16 bits and inserts the level in the low-order 16 bits. If the deadline is larger than ULLONG_MAX >> 16, then it is treated as the largest possible deadline. @oaran deadline THe deadline.

Parameters
levelThe level in the reaction graph.

◆ lf_free()

void lf_free ( struct allocation_record_t ** head)

Free memory on the specified allocation record (a self struct).

This will mark the allocation record empty by setting *head to NULL. If the argument is NULL, do nothing.

Parameters
headPointer to the head of a list on which allocations are recorded.

◆ lf_free_all_reactors()

void lf_free_all_reactors ( void )

Free all the reactors that are allocated with lf_new_reactor(size_t).

◆ lf_free_reactor()

void lf_free_reactor ( self_base_t * self)

Free the specified reactor.

This will free the memory recorded on the allocations list of the specified reactor and then free the specified self struct.

Parameters
selfThe self struct of the reactor.

◆ lf_get_new_event()

event_t * lf_get_new_event ( environment_t * env)

Get a new event. If there is a recycled event available, use that. If not, allocate a new one. In either case, all fields will be zero'ed out.

Parameters
envEnvironment in which we are executing.

◆ lf_is_tag_after_stop_tag()

bool lf_is_tag_after_stop_tag ( environment_t * env,
tag_t tag )

Return true if the provided tag is after stop tag.

Parameters
envEnvironment in which we are executing.
tagThe tag to check against stop tag

◆ lf_new_reactor()

self_base_t * lf_new_reactor ( size_t size)

Allocate memory for a new runtime instance of a reactor.

This records the reactor on the list of reactors to be freed at termination of the program. If you plan to free the reactor before termination of the program, use lf_allocate(size_t, size_t, allocation_record_t**) with a null last argument instead.

Parameters
sizeThe size of the self struct, obtained with sizeof().

◆ lf_recycle_event()

void lf_recycle_event ( environment_t * env,
event_t * e )

Recycle the given event.

This will zero out the event and push it onto the recycle queue.

Parameters
envEnvironment in which we are executing.
eThe event to recycle.

◆ lf_replace_token()

void lf_replace_token ( event_t * event,
lf_token_t * token )

Replace the token on the specified event with the specified token and free the old token.

Parameters
eventThe event.
tokenThe token.

◆ lf_set_stop_tag()

void lf_set_stop_tag ( environment_t * env,
tag_t tag )

Set the stop tag if it is less than the stop tag of the specified environment.

Note
In threaded programs, the environment's mutex must be locked before calling this function.

◆ process_args()

int process_args ( int argc,
const char * argv[] )

Process the command-line arguments. If the command line arguments are not understood, then print a usage message and return 0. Otherwise, return 1.

Returns
1 if the arguments processed successfully, 0 otherwise. TODO: Not necessary for NO_TTY

◆ schedule_output_reactions()

void schedule_output_reactions ( environment_t * env,
reaction_t * reaction,
int worker )

For the specified reaction, if it has produced outputs, insert the resulting triggered reactions into the reaction queue. This procedure assumes the mutex lock is NOT held and grabs the lock only when it actually inserts something onto the reaction queue.

Parameters
envEnvironment in which we are executing.
reactionThe reaction that has just executed.
workerThe thread number of the worker thread or 0 for single-threaded execution (for tracing).

◆ termination()

void termination ( void )

Perform final wrap-up on exit.

Report elapsed logical and physical times and report if any memory allocated for tokens has not been freed.

◆ usage()

void usage ( int argc,
const char * argv[] )

Print a usage message. TODO: This is not necessary for NO_TTY

Variable Documentation

◆ _lf_count_payload_allocations

int _lf_count_payload_allocations
extern

Counter used to issue a warning if memory is allocated for message payloads and never freed.

◆ _lf_normal_termination

bool _lf_normal_termination = false

Flag used to disable cleanup operations on abnormal termination.

◆ _lf_number_of_workers

unsigned int _lf_number_of_workers = 0u

The number of worker threads for threaded execution. By default, execution is not threaded and this variable will have value 0.

If the execution is threaded, a value of 0 indicates that the runtime should decide on the number of workers (which will be decided based on the number of available cores on the host machine).

◆ _lf_reactors_to_free

struct allocation_record_t* _lf_reactors_to_free = NULL

Head of a list of pointers to dynamically generated reactor self structs to be freed in terminate().

◆ _lf_termination_executed

bool _lf_termination_executed = false

Flag to prevent termination function from executing twice and to signal to background threads to terminate.

◆ default_argc

int default_argc = 0

◆ default_argv

const char** default_argv = NULL

◆ duration

instant_t duration = -1LL

The logical time to elapse during execution, or -1 if no timeout time has been given. When the logical equal to start_time + duration has been reached, execution will terminate.

◆ fast

bool fast = false

Indicator of whether to wait for physical time to match logical time. By default, execution will wait. The command-line argument -fast will eliminate the wait and allow logical time to exceed physical time.

◆ keepalive_specified

bool keepalive_specified = false

Indicator of whether the keepalive command-line option was given.

◆ start_time

instant_t start_time
extern

The start time read from the trace file.