-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Static scheduler #241
base: main
Are you sure you want to change the base?
Static scheduler #241
Changes from all commits
7de874e
48d5bbf
0a76f87
66b22cc
2015f09
05622fd
4616369
f3e3ba0
5d79291
bf504df
bfe021d
3e4bd00
995a014
edcae4f
a6e08b3
42cad35
e497088
6aab8ed
d2f5c9a
176b74a
f2cc481
321e17c
aafa8c7
402d1da
fbdb4ac
e606e51
f669991
26bb4af
26439fc
e7eac8a
2387ae6
0ffbcc4
fc5fb2b
185a0ae
2d3c89c
ccedcab
890c54e
7bea24f
740d5cc
ac59cfa
838ad16
031412e
e9edc18
d3d39e9
bb5ae6d
4d32a5c
90e8c8b
e49225a
d4a1127
ce03252
8971b1f
3e498c8
ce9d422
0f30f05
2512f0c
4118922
31428ab
2fe28a6
7fd9ba0
ebbdb7c
ccf50e5
cac23fb
a47356b
261cb8b
55bb599
57fffe1
3dbb4a1
2d27f14
3635412
40b45dd
4c57e17
e27fcd9
f783227
e89f09a
ca533a9
ec0f645
d4af904
732b13a
4ad2cdf
05fcd4c
0969328
884386e
bd0b5a2
c7b7285
0e1e61b
3a37b15
2e0f2ff
b230663
cd5a633
44313a2
5f1c224
11dc8de
7ab1111
6188090
4c8f3fd
d76e82e
08e2506
5874882
700835b
998f555
e8975a9
51e63f6
1082131
1837c6c
75df70f
9b4b818
e8f0d54
6538c34
c63e804
75b9a50
1a97ab5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,93 @@ | ||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||
* @file circular_buffer.c | ||||||||||||||||||||||||||||||||||||
* @brief A circular buffer implementation from stack overflow | ||||||||||||||||||||||||||||||||||||
* (https://stackoverflow.com/questions/827691/how-do-you-implement-a-circular-buffer-in-c) | ||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||
* @copyright Copyright (c) 2024 | ||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
#include "util.h" | ||||||||||||||||||||||||||||||||||||
#include "circular_buffer.h" | ||||||||||||||||||||||||||||||||||||
#include "lf_types.h" | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
void cb_init(circular_buffer *cb, size_t capacity, size_t sz) | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
cb->buffer = malloc(capacity * sz); | ||||||||||||||||||||||||||||||||||||
if(cb->buffer == NULL) { | ||||||||||||||||||||||||||||||||||||
// handle error | ||||||||||||||||||||||||||||||||||||
lf_print("ERROR: Fail to allocate memory to circular buffer."); | ||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
cb->buffer_end = (char *)cb->buffer + capacity * sz; | ||||||||||||||||||||||||||||||||||||
cb->capacity = capacity; | ||||||||||||||||||||||||||||||||||||
cb->count = 0; | ||||||||||||||||||||||||||||||||||||
cb->sz = sz; | ||||||||||||||||||||||||||||||||||||
cb->head = cb->buffer; | ||||||||||||||||||||||||||||||||||||
cb->tail = cb->buffer; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
void cb_free(circular_buffer *cb) | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
free(cb->buffer); | ||||||||||||||||||||||||||||||||||||
// clear out other fields too, just to be safe | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
Comment on lines
+30
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reset circular buffer attributes in To prevent potential use-after-free errors, reset other attributes of the circular buffer after freeing the memory. void cb_free(circular_buffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
+ cb->buffer = NULL;
+ cb->buffer_end = NULL;
+ cb->capacity = 0;
+ cb->count = 0;
+ cb->sz = 0;
+ cb->head = NULL;
+ cb->tail = NULL;
} Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
void cb_push_back(circular_buffer *cb, const void *item) | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
if(cb->count == cb->capacity){ | ||||||||||||||||||||||||||||||||||||
lf_print("ERROR: Buffer is full. Some in-flight events will be overwritten!"); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
memcpy(cb->head, item, cb->sz); | ||||||||||||||||||||||||||||||||||||
cb->head = (char*)cb->head + cb->sz; | ||||||||||||||||||||||||||||||||||||
if(cb->head == cb->buffer_end) | ||||||||||||||||||||||||||||||||||||
cb->head = cb->buffer; | ||||||||||||||||||||||||||||||||||||
cb->count++; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
void cb_pop_front(circular_buffer *cb, void *item) | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
if(cb->count == 0){ | ||||||||||||||||||||||||||||||||||||
// handle error | ||||||||||||||||||||||||||||||||||||
lf_print("ERROR: Popping from an empty buffer!"); | ||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
memcpy(item, cb->tail, cb->sz); | ||||||||||||||||||||||||||||||||||||
cb->tail = (char*)cb->tail + cb->sz; | ||||||||||||||||||||||||||||||||||||
if(cb->tail == cb->buffer_end) | ||||||||||||||||||||||||||||||||||||
cb->tail = cb->buffer; | ||||||||||||||||||||||||||||||||||||
cb->count--; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
void cb_remove_front(circular_buffer *cb) | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
if(cb->count == 0){ | ||||||||||||||||||||||||||||||||||||
// handle error | ||||||||||||||||||||||||||||||||||||
lf_print("ERROR: Removing from an empty buffer!"); | ||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
cb->tail = (char*)cb->tail + cb->sz; | ||||||||||||||||||||||||||||||||||||
if(cb->tail == cb->buffer_end) | ||||||||||||||||||||||||||||||||||||
cb->tail = cb->buffer; | ||||||||||||||||||||||||||||||||||||
cb->count--; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
void* cb_peek(circular_buffer *cb) | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
if(cb->count == 0) | ||||||||||||||||||||||||||||||||||||
return NULL; | ||||||||||||||||||||||||||||||||||||
return cb->tail; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
void cb_dump_events(circular_buffer *cb) | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
lf_print("*** Dumping Events ***"); | ||||||||||||||||||||||||||||||||||||
void *p = cb->tail; | ||||||||||||||||||||||||||||||||||||
while (p != cb->head) { | ||||||||||||||||||||||||||||||||||||
event_t* e = (event_t*)p; | ||||||||||||||||||||||||||||||||||||
lf_print("Event @ %lld w/ token %p", e->base.tag.time, e->token); | ||||||||||||||||||||||||||||||||||||
p += cb->sz; | ||||||||||||||||||||||||||||||||||||
if (p == cb->buffer_end) p = cb->buffer; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
lf_print("**********************"); | ||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,76 @@ | ||||||||||||||
/** | ||||||||||||||
* @brief Format of the instruction set | ||||||||||||||
*/ | ||||||||||||||
#ifndef SCHEDULER_INSTRUCTIONS_H | ||||||||||||||
#define SCHEDULER_INSTRUCTIONS_H | ||||||||||||||
|
||||||||||||||
typedef enum { | ||||||||||||||
ADD, | ||||||||||||||
ADDI, | ||||||||||||||
ADV, | ||||||||||||||
ADVI, | ||||||||||||||
BEQ, | ||||||||||||||
BGE, | ||||||||||||||
BLT, | ||||||||||||||
BNE, | ||||||||||||||
DU, | ||||||||||||||
EXE, | ||||||||||||||
JAL, | ||||||||||||||
JALR, | ||||||||||||||
STP, | ||||||||||||||
WLT, | ||||||||||||||
WU, | ||||||||||||||
} opcode_t; | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
* @brief Convenient typedefs for the data types used by the C implementation of | ||||||||||||||
* PRET VM. A register is 64bits and an immediate is 64bits. This avoids any | ||||||||||||||
* issue with time and overflow. Arguably it is worth it even for smaller | ||||||||||||||
* platforms. | ||||||||||||||
* | ||||||||||||||
*/ | ||||||||||||||
typedef volatile uint64_t reg_t; | ||||||||||||||
typedef uint64_t imm_t; | ||||||||||||||
Comment on lines
+33
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure proper type safety and usage. Ensure that the typedefs for +typedef volatile uint64_t reg_t;
+typedef uint64_t imm_t;
+// Ensure proper type safety
+static_assert(sizeof(reg_t) == sizeof(imm_t), "reg_t and imm_t must be the same size"); Committable suggestion
Suggested change
|
||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
* @brief An union representing a single operand for the PRET VM. A union | ||||||||||||||
* means that we have one piece of memory, which is big enough to fit either | ||||||||||||||
* one of the two members of the union. | ||||||||||||||
* | ||||||||||||||
*/ | ||||||||||||||
typedef union { | ||||||||||||||
reg_t* reg; | ||||||||||||||
imm_t imm; | ||||||||||||||
} operand_t; | ||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
* @brief Virtual instruction function pointer | ||||||||||||||
*/ | ||||||||||||||
typedef void (*function_virtual_instruction_t)( | ||||||||||||||
lf_scheduler_t* scheduler, | ||||||||||||||
size_t worker_number, | ||||||||||||||
operand_t op1, | ||||||||||||||
operand_t op2, | ||||||||||||||
operand_t op3, | ||||||||||||||
bool debug, | ||||||||||||||
size_t* pc, | ||||||||||||||
reaction_t** returned_reaction, | ||||||||||||||
bool* exit_loop); | ||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
* @brief This struct represents a PRET VM instruction for C platforms. | ||||||||||||||
* There is an opcode and three operands. The operands are unions so they | ||||||||||||||
* can be either a pointer or an immediate | ||||||||||||||
* | ||||||||||||||
*/ | ||||||||||||||
typedef struct inst_t { | ||||||||||||||
function_virtual_instruction_t func; | ||||||||||||||
opcode_t opcode; | ||||||||||||||
operand_t op1; | ||||||||||||||
operand_t op2; | ||||||||||||||
operand_t op3; | ||||||||||||||
bool debug; | ||||||||||||||
} inst_t; | ||||||||||||||
|
||||||||||||||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#ifndef SCHEDULER_STATIC_FUNCTION_H | ||
#define SCHEDULER_STATIC_FUNCTION_H | ||
|
||
/** | ||
* @brief Function type with a void* argument. To make this type represent a | ||
* generic function, one can write a wrapper function around the target function | ||
* and use the first argument as a pointer to a struct of input arguments | ||
* and return values. | ||
*/ | ||
typedef void(*function_generic_t)(void*); | ||
|
||
/** | ||
* @brief Wrapper function for peeking a priority queue. | ||
*/ | ||
void push_pop_peek_pqueue(void* self); | ||
|
||
void execute_inst_ADD(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_ADDI(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_ADV(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_ADVI(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_BEQ(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_BGE(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_BLT(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_BNE(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_DU(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_EXE(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_WLT(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_WU(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_JAL(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_JALR(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
void execute_inst_STP(lf_scheduler_t* scheduler, size_t worker_number, operand_t op1, operand_t op2, operand_t op3, bool debug, size_t* pc, | ||
reaction_t** returned_reaction, bool* exit_loop); | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,26 @@ | ||||||||||||||||||||||||||||||||||
#ifndef CIRCULAR_BUFFER_H | ||||||||||||||||||||||||||||||||||
#define CIRCULAR_BUFFER_H | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
#include <stdlib.h> | ||||||||||||||||||||||||||||||||||
#include <string.h> | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
typedef struct circular_buffer | ||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||
void *buffer; // data buffer | ||||||||||||||||||||||||||||||||||
void *buffer_end; // end of data buffer | ||||||||||||||||||||||||||||||||||
size_t capacity; // maximum number of items in the buffer | ||||||||||||||||||||||||||||||||||
size_t count; // number of items in the buffer | ||||||||||||||||||||||||||||||||||
size_t sz; // size of each item in the buffer | ||||||||||||||||||||||||||||||||||
void *head; // pointer to head | ||||||||||||||||||||||||||||||||||
void *tail; // pointer to tail | ||||||||||||||||||||||||||||||||||
Comment on lines
+9
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure proper memory alignment and handling. Ensure that the buffer memory is properly aligned and handled to avoid potential issues. + void *buffer; // data buffer
+ void *buffer_end; // end of data buffer
+ size_t capacity; // maximum number of items in the buffer
+ size_t count; // number of items in the buffer
+ size_t sz; // size of each item in the buffer
+ void *head; // pointer to head
+ void *tail; // pointer to tail
+ // Ensure proper memory alignment
+ alignas(alignof(max_align_t)) char data[]; Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
} circular_buffer; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
void cb_init(circular_buffer *cb, size_t capacity, size_t sz); | ||||||||||||||||||||||||||||||||||
void cb_free(circular_buffer *cb); | ||||||||||||||||||||||||||||||||||
void cb_push_back(circular_buffer *cb, const void *item); | ||||||||||||||||||||||||||||||||||
void cb_pop_front(circular_buffer *cb, void *item); | ||||||||||||||||||||||||||||||||||
void cb_remove_front(circular_buffer *cb); | ||||||||||||||||||||||||||||||||||
void* cb_peek(circular_buffer *cb); | ||||||||||||||||||||||||||||||||||
void cb_dump_events(circular_buffer *cb); | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
add_library(test-lib SCHED_STATIC src_gen_stub.c rand_utils.c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve error handling in
cb_init
.If memory allocation fails, the function should free any partially allocated resources and return an error code.
Committable suggestion