Skip to content

Commit c69a2d2

Browse files
authored
Improve and reduce critical sections (#276)
* Add get_lag() and improve docs * Remove platform.h from doxy * Reduce and improve the critical sections * Smaller fixes * First iteration of moving to a mutex type * Add mutex to queues * Format * Add locks to the payload pools * Remove critical sections * Port over Zephyr, RIOT and Pico * Format * Fix aducm355 * aducm355 fixes * Fix aducm355, flexpret and pico * Formatting * Remove unused field of ClockSynchronization * Fix platform implementations * Small fixes * Formatting * Trigger CI
1 parent 528b804 commit c69a2d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+655
-570
lines changed

examples/flexpret/buildAll.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# set -e
2-
# ${REACTOR_UC_PATH}/lfc/bin/lfc-dev src/Smoke.lf
3-
# cmake -Bbuild
4-
# make -C build
5-
# bin/fp-smoke
1+
set -e
2+
${REACTOR_UC_PATH}/lfc/bin/lfc-dev src/Smoke.lf
3+
cmake -Bbuild
4+
make -C build
5+
bin/fp-smoke

examples/zephyr/basic_federated/federated_sender/src/sender.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ typedef struct {
2222
char msg[32];
2323
} msg_t;
2424

25-
LF_DEFINE_ACTION_STRUCT(Sender, act, PHYSICAL_ACTION, 1, 0, 0, 10, bool);
26-
LF_DEFINE_ACTION_CTOR(Sender, act, PHYSICAL_ACTION, 1, 0, 0, 10, bool);
25+
LF_DEFINE_ACTION_STRUCT(Sender, act, PhysicalAction, 1, 0, 0, 10, bool);
26+
LF_DEFINE_ACTION_CTOR(Sender, act, PhysicalAction, 1, 0, 0, 10, bool);
2727
LF_DEFINE_REACTION_STRUCT(Sender, r, 1);
2828
LF_DEFINE_REACTION_CTOR(Sender, r, 0, NULL, NULL);
2929

include/reactor-uc/action.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
#include "reactor-uc/error.h"
55
#include "reactor-uc/reaction.h"
66
#include "reactor-uc/trigger.h"
7+
#include "reactor-uc/platform.h"
78

89
typedef struct Action Action;
9-
typedef struct LogicalAction LogicalAction;
1010
typedef struct PhysicalAction PhysicalAction;
11+
typedef struct LogicalAction LogicalAction;
1112

1213
typedef enum { LOGICAL_ACTION, PHYSICAL_ACTION } ActionType;
1314

@@ -40,4 +41,22 @@ void Action_ctor(Action *self, ActionType type, interval_t min_offset, interval_
4041
size_t observers_size, void *value_ptr, size_t value_size, void *payload_buf, bool *payload_used_buf,
4142
size_t event_bound);
4243

44+
struct LogicalAction {
45+
Action super;
46+
};
47+
48+
void LogicalAction_ctor(LogicalAction *self, interval_t min_offset, interval_t min_spacing, Reactor *parent,
49+
Reaction **sources, size_t sources_size, Reaction **effects, size_t effects_size,
50+
Reaction **observers, size_t observers_size, void *value_ptr, size_t value_size,
51+
void *payload_buf, bool *payload_used_buf, size_t event_bound);
52+
53+
struct PhysicalAction {
54+
Action super;
55+
MUTEX_T mutex;
56+
};
57+
58+
void PhysicalAction_ctor(PhysicalAction *self, interval_t min_offset, interval_t min_spacing, Reactor *parent,
59+
Reaction **sources, size_t sources_size, Reaction **effects, size_t effects_size,
60+
Reaction **observers, size_t observers_size, void *value_ptr, size_t value_size,
61+
void *payload_buf, bool *payload_used_buf, size_t event_bound);
4362
#endif

include/reactor-uc/clock_synchronization.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ struct ClockSynchronization {
5555
interval_t period; // The period between sync request messages are sent to the neighbor master.
5656
ClockSyncTimestamps timestamps; // The timestamps used to compute clock offset.
5757
ClockServo servo; // The PID controller
58-
// TODO: Is this message here needed? Why cant we use the one on the bundle?
59-
FederateMessage msg; // A FederateMessage used for transmitting sync request and follow-up messages.
6058
void (*handle_message_callback)(ClockSynchronization *self, const ClockSyncMessage *msg, size_t bundle_idx);
6159
};
6260

include/reactor-uc/environment.h

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@
1010

1111
#include "reactor-uc/builtin_triggers.h"
1212
#include "reactor-uc/error.h"
13-
#include "reactor-uc/platform.h"
1413
#include "reactor-uc/reactor.h"
1514
#include "reactor-uc/scheduler.h"
1615
#include "reactor-uc/queues.h"
1716

17+
typedef struct Platform Platform;
1818
typedef struct Environment Environment;
1919
extern Environment *_lf_environment; // NOLINT
2020

2121
struct Environment {
22-
Reactor *main; // The top-level reactor of the program.
23-
Scheduler *scheduler; // The scheduler in charge of executing the reactions.
24-
Platform *platform; // The platform that provides the physical time and sleep functions.
22+
Reactor *main; // The top-level reactor of the program.
23+
Scheduler *scheduler; // The scheduler in charge of executing the reactions.
24+
Platform *platform;
2525
bool has_async_events; // Whether the program has multiple execution contexts and can receive async events and thus
2626
// need critical sections.
2727
bool fast_mode; // Whether the program is executing in fast mode where we do not wait for physical time to elapse
@@ -50,7 +50,7 @@ struct Environment {
5050
* This function must be called from a critical section.
5151
*
5252
*/
53-
lf_ret_t (*wait_until_locked)(Environment *self, instant_t wakeup_time);
53+
lf_ret_t (*wait_until)(Environment *self, instant_t wakeup_time);
5454

5555
/**
5656
* @brief Sleep for a duration.
@@ -113,18 +113,6 @@ struct Environment {
113113
*/
114114
interval_t (*get_lag)(Environment *self);
115115

116-
/**
117-
* @private
118-
* @brief Enter a critical section. Either by disabling interrupts, using a mutex or both.
119-
*/
120-
void (*enter_critical_section)(Environment *self);
121-
122-
/**
123-
* @private
124-
* @brief Leave a critical section. Either by enabling interrupts, releasing a mutex or both.
125-
*/
126-
void (*leave_critical_section)(Environment *self);
127-
128116
/**
129117
* @brief Request the termination of the program.
130118
* @param self The environment.

include/reactor-uc/event.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "reactor-uc/error.h"
55
#include "reactor-uc/tag.h"
6+
#include "reactor-uc/platform.h"
67
#include <stdbool.h>
78

89
#define EVENT_INIT(Tag, Trigger, Payload) \
@@ -55,6 +56,8 @@ struct EventPayloadPool {
5556
/** Number of payloads reserved to be allocated through `allocate_reserved` */
5657
size_t reserved;
5758

59+
MUTEX_T mutex;
60+
5861
/** Allocate a payload from the pool. */
5962
lf_ret_t (*allocate)(EventPayloadPool *self, void **payload);
6063
lf_ret_t (*allocate_reserved)(EventPayloadPool *self, void **payload);

include/reactor-uc/federated.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ void FederatedOutputConnection_ctor(FederatedOutputConnection *self, Reactor *pa
9494
*/
9595
struct FederatedInputConnection {
9696
Connection super;
97+
MUTEX_T mutex;
9798
interval_t delay; // The amount of delay on this connection
9899
ConnectionType type; // Whether this is a logical or physical connection
99100
tag_t last_known_tag; // The latest tag this input is known at.

include/reactor-uc/macros_internal.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@
282282
#define LF_DEFINE_ACTION_STRUCT(ReactorName, ActionName, ActionType, EffectSize, SourceSize, ObserverSize, \
283283
MaxPendingEvents, BufferType) \
284284
typedef struct { \
285-
Action super; \
285+
ActionType super; \
286286
BufferType value; \
287287
BufferType payload_buf[(MaxPendingEvents)]; \
288288
bool payload_used_buf[(MaxPendingEvents)]; \
@@ -294,7 +294,7 @@
294294
#define LF_DEFINE_ACTION_STRUCT_ARRAY(ReactorName, ActionName, ActionType, EffectSize, SourceSize, ObserverSize, \
295295
MaxPendingEvents, BufferType, ArrayLength) \
296296
typedef struct { \
297-
Action super; \
297+
ActionType super; \
298298
BufferType value[(ArrayLength)]; \
299299
BufferType payload_buf[(ArrayLength)][(MaxPendingEvents)]; \
300300
bool payload_used_buf[(MaxPendingEvents)]; \
@@ -306,7 +306,7 @@
306306
#define LF_DEFINE_ACTION_STRUCT_VOID(ReactorName, ActionName, ActionType, EffectSize, SourceSize, ObserverSize, \
307307
MaxPendingEvents) \
308308
typedef struct { \
309-
Action super; \
309+
ActionType super; \
310310
Reaction *sources[(SourceSize)]; \
311311
Reaction *effects[(EffectSize)]; \
312312
Reaction *observers[(ObserverSize)]; \
@@ -316,17 +316,17 @@
316316
MaxPendingEvents, BufferType) \
317317
void ReactorName##_##ActionName##_ctor(ReactorName##_##ActionName *self, Reactor *parent, interval_t min_delay, \
318318
interval_t min_spacing) { \
319-
Action_ctor(&self->super, ActionType, min_delay, min_spacing, parent, self->sources, (SourceSize), self->effects, \
320-
(EffectSize), self->observers, ObserverSize, &self->value, sizeof(self->value), \
321-
(void *)&self->payload_buf, self->payload_used_buf, (MaxPendingEvents)); \
319+
ActionType##_ctor(&self->super, min_delay, min_spacing, parent, self->sources, (SourceSize), self->effects, \
320+
(EffectSize), self->observers, ObserverSize, &self->value, sizeof(self->value), \
321+
(void *)&self->payload_buf, self->payload_used_buf, (MaxPendingEvents)); \
322322
}
323323

324324
#define LF_DEFINE_ACTION_CTOR_VOID(ReactorName, ActionName, ActionType, EffectSize, SourceSize, ObserverSize, \
325325
MaxPendingEvents) \
326326
void ReactorName##_##ActionName##_ctor(ReactorName##_##ActionName *self, Reactor *parent, interval_t min_delay, \
327327
interval_t min_spacing) { \
328-
Action_ctor(&self->super, ActionType, min_delay, min_spacing, parent, self->sources, (SourceSize), self->effects, \
329-
(EffectSize), self->observers, ObserverSize, NULL, 0, NULL, NULL, (MaxPendingEvents)); \
328+
ActionType##_ctor(&self->super, min_delay, min_spacing, parent, self->sources, (SourceSize), self->effects, \
329+
(EffectSize), self->observers, ObserverSize, NULL, 0, NULL, NULL, (MaxPendingEvents)); \
330330
}
331331

332332
#define LF_ACTION_INSTANCE(ReactorName, ActionName) ReactorName##_##ActionName ActionName

include/reactor-uc/physical_clock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef REACTOR_UC_PHYSICAL_CLOCK_H
22
#define REACTOR_UC_PHYSICAL_CLOCK_H
33

4+
#include "reactor-uc/platform.h"
45
#include "reactor-uc/tag.h"
56
#include "reactor-uc/error.h"
67
#include <stdbool.h>
@@ -10,6 +11,7 @@ typedef struct Environment Environment;
1011

1112
struct PhysicalClock {
1213
Environment *env;
14+
MUTEX_T mutex;
1315
interval_t offset; // Constant offset applied to each reading of the HW clock
1416
instant_t adjustment_epoch_hw; // The time at which the frequency adjustment should by applied from.
1517
double adjustment; // The frequency adjustment factor.

include/reactor-uc/platform.h

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,24 @@
66
#include <stdarg.h>
77

88
typedef struct Platform Platform;
9+
typedef struct Mutex Mutex;
10+
11+
/**
12+
* @brief Each supported platform must provide a mutex, this is used by the runtime
13+
* to protect shared data structures.
14+
*
15+
* The mutex can be implemented using the underlying OS, or just disabling/enabling interrupts.
16+
*
17+
*/
18+
struct Mutex {
19+
void (*lock)(Mutex *super);
20+
void (*unlock)(Mutex *super);
21+
};
22+
23+
/** Construct a Mutex*/
24+
void Mutex_ctor(Mutex *super);
925

1026
struct Platform {
11-
/**
12-
* @brief Perform any platform initialization such as initializing semaphores,
13-
* configuring clocks, etc. Called once after construction.
14-
* @param super The platform
15-
*/
16-
lf_ret_t (*initialize)(Platform *super);
1727
/**
1828
* @brief Return the current physical time in nanoseconds.
1929
*/
@@ -32,30 +42,43 @@ struct Platform {
3242
* @brief Put the system to sleep until the wakeup time or until an
3343
* asynchronous event occurs. Must be called from a critical section.
3444
*/
35-
lf_ret_t (*wait_until_interruptible_locked)(Platform *super, instant_t wakeup_time);
45+
lf_ret_t (*wait_until_interruptible)(Platform *super, instant_t wakeup_time);
3646

3747
/**
3848
* @brief Signal the occurrence of an asynchronous event. This should wake
3949
* up the platform if it is sleeping on `wait_until_interruptible_locked`.
4050
*/
41-
void (*new_async_event)(Platform *super);
42-
43-
/**
44-
* @brief Enter and leave a critical section. This must support nested critical sections. Critical sections
45-
* can be implemented by disabling interrupts or acquiring a mutex.
46-
*/
47-
void (*enter_critical_section)(Platform *super);
48-
void (*leave_critical_section)(Platform *super);
51+
void (*notify)(Platform *super);
4952
};
5053

51-
// Return a pointer to a Platform object. Must be implemented for each
52-
// target platform.
53-
Platform *Platform_new(void);
54-
5554
// Construct a Platform object. Must be implemented for each target platform.
5655
void Platform_ctor(Platform *super);
5756

57+
// Returns a pointer to the platform.P
58+
Platform *Platform_new();
59+
5860
// Allow each platform to provide its own implementation for printing.
5961
void Platform_vprintf(const char *fmt, va_list args);
6062

63+
#if defined(PLATFORM_POSIX)
64+
#include "reactor-uc/platform/posix/posix.h"
65+
#elif defined(PLATFORM_RIOT)
66+
#include "reactor-uc/platform/riot/riot.h"
67+
#elif defined(PLATFORM_ZEPHYR)
68+
#include "reactor-uc/platform/zephyr/zephyr.h"
69+
#elif defined(PLATFORM_FLEXPRET)
70+
#include "reactor-uc/platform/flexpret/flexpret.h"
71+
#elif defined(PLATFORM_PICO)
72+
#include "reactor-uc/platform/pico/pico.h"
73+
#elif defined(PLATFORM_PATMOS)
74+
#include "reactor-uc/platform/patmos/patmos.h"
75+
#elif defined(PLATFORM_ADUCM355)
76+
#include "reactor-uc/platform/aducm355/aducm355.h"
77+
#else
78+
#error "NO PLATFORM SPECIFIED"
79+
#endif
80+
81+
#define MUTEX_LOCK(Mutex) (Mutex).super.lock(&(Mutex).super)
82+
#define MUTEX_UNLOCK(Mutex) (Mutex).super.unlock(&(Mutex).super)
83+
6184
#endif

0 commit comments

Comments
 (0)