From 1f09867cf885737a2081019adc4953f862898b45 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Mon, 26 May 2025 22:44:31 +0200 Subject: [PATCH 01/15] Replace pre-C11 __thread with _Thread_local We still had some __thread storage class specifier in the code base. Change it to the standard _Thread_local. Signed-off-by: Alessandro Pellegrini --- src/core/core.c | 2 +- src/core/core.h | 2 +- src/core/sync.c | 2 +- src/datatypes/msg_queue.c | 2 +- src/gvt/fossil.c | 4 ++-- src/gvt/fossil.h | 2 +- src/gvt/gvt.c | 14 +++++++------- src/gvt/gvt.h | 6 +++--- src/gvt/termination.c | 4 ++-- src/log/stats.c | 2 +- src/lp/lp.c | 6 +++--- src/lp/lp.h | 6 +++--- src/lp/process.c | 4 ++-- src/mm/auto_ckpt.c | 2 +- src/mm/msg_allocator.c | 4 ++-- test/old_tests/gvt/gvt_test.c | 2 +- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/core/core.c b/src/core/core.c index 585ff90a..b0cea504 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -10,7 +10,7 @@ */ #include -__thread rid_t rid; +_Thread_local rid_t rid; nid_t n_nodes = 1; nid_t nid; diff --git a/src/core/core.h b/src/core/core.h index c3a664c6..939eb391 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -69,7 +69,7 @@ typedef int nid_t; /// The total number of LPs hosted in the node extern lp_id_t n_lps_node; /// The identifier of the thread -extern __thread rid_t rid; +extern _Thread_local rid_t rid; /// The total number of MPI nodes in the simulation extern nid_t n_nodes; diff --git a/src/core/sync.c b/src/core/sync.c index 34d4f96a..c4ba0cdb 100644 --- a/src/core/sync.c +++ b/src/core/sync.c @@ -21,7 +21,7 @@ bool sync_thread_barrier(void) bool l; unsigned r; - static __thread unsigned phase; + static _Thread_local unsigned phase; static atomic_uint cs[2]; // FIXME: this makes this barrier stateful with respect to the threads used atomic_uint *c = cs + (phase & 1U); diff --git a/src/datatypes/msg_queue.c b/src/datatypes/msg_queue.c index f8a2934f..33dbdd3a 100644 --- a/src/datatypes/msg_queue.c +++ b/src/datatypes/msg_queue.c @@ -42,7 +42,7 @@ struct msg_buffer { /// The buffers vector static struct msg_buffer *queues; /// The private thread queue -static __thread heap_declare(struct q_elem) mqp; +static _Thread_local heap_declare(struct q_elem) mqp; /** * @brief Initializes the message queue at the node level diff --git a/src/gvt/fossil.c b/src/gvt/fossil.c index 0a2cfdbe..cf4de9e6 100644 --- a/src/gvt/fossil.c +++ b/src/gvt/fossil.c @@ -11,9 +11,9 @@ #include -__thread unsigned fossil_epoch_current; +_Thread_local unsigned fossil_epoch_current; /// The value of the last GVT, kept here for easier fossil collection operations -static __thread simtime_t fossil_gvt_current; +static _Thread_local simtime_t fossil_gvt_current; /** * @brief Perform fossil collection operations at a given GVT diff --git a/src/gvt/fossil.h b/src/gvt/fossil.h index b7f64e12..57958db4 100644 --- a/src/gvt/fossil.h +++ b/src/gvt/fossil.h @@ -22,7 +22,7 @@ #define fossil_is_needed(lp) ((lp)->fossil_epoch != fossil_epoch_current) /// The current fossil collection epoch -extern __thread unsigned fossil_epoch_current; +extern _Thread_local unsigned fossil_epoch_current; extern void fossil_on_gvt(simtime_t current_gvt); extern void fossil_lp_collect(struct lp_ctx *lp); diff --git a/src/gvt/gvt.c b/src/gvt/gvt.c index 24f7291b..577ad1f7 100644 --- a/src/gvt/gvt.c +++ b/src/gvt/gvt.c @@ -63,14 +63,14 @@ enum node_phase { }; /// The current phase of the node-local GVT algorithm for the current thread -static __thread enum thread_phase thread_phase = thread_phase_idle; +static _Thread_local enum thread_phase thread_phase = thread_phase_idle; /// The timer used to plan the execution of the next GVT algorithm static timer_uint gvt_timer; /// Helper array for the reduction of the node-local GVT static simtime_t reducing_p[MAX_THREADS]; /// This keeps the minimum timestamp of messages extracted by the current thread /** A sort of thread local GVT value used for further reductions */ -static __thread simtime_t gvt_accumulator; +static _Thread_local simtime_t gvt_accumulator; /// A counter used to synchronize threads during the node-local GVT algorithm /** This value is also used to detect the end of the node-local GVT computation */ static _Atomic rid_t c_a = 0; @@ -82,13 +82,13 @@ static _Atomic rid_t c_b = 0; static _Atomic nid_t gvt_nodes; /// The "color" of the current GVT phase /** Colors are red if false, yellow if true ;) */ -__thread _Bool gvt_phase; +_Thread_local _Bool gvt_phase; /// The sequence number for remote messages generated by the current thread towards the nth node /** We handle separately red and yellow messages */ -__thread uint32_t remote_msg_seq[2][MAX_NODES]; +_Thread_local uint32_t remote_msg_seq[2][MAX_NODES]; /// The count of remote messages received by the current thread /** We handle separately red and yellow messages */ -__thread uint32_t remote_msg_received[2]; +_Thread_local uint32_t remote_msg_received[2]; /** * @brief Initializes the gvt module in the node @@ -178,8 +178,8 @@ static bool gvt_thread_phase_run(void) static bool gvt_node_phase_run(void) { - static __thread enum node_phase node_phase = node_phase_redux_first; - static __thread uint32_t last_seq[2][MAX_NODES]; + static _Thread_local enum node_phase node_phase = node_phase_redux_first; + static _Thread_local uint32_t last_seq[2][MAX_NODES]; static _Atomic(uint32_t) total_sent[MAX_NODES]; static _Atomic(int32_t) total_msg_received; static uint32_t remote_msg_to_receive; diff --git a/src/gvt/gvt.h b/src/gvt/gvt.h index 0d356849..9caae862 100644 --- a/src/gvt/gvt.h +++ b/src/gvt/gvt.h @@ -15,9 +15,9 @@ extern void gvt_global_init(void); extern simtime_t gvt_phase_run(void); extern void gvt_on_msg_extraction(simtime_t msg_t); -extern __thread _Bool gvt_phase; -extern __thread uint32_t remote_msg_seq[2][MAX_NODES]; -extern __thread uint32_t remote_msg_received[2]; +extern _Thread_local _Bool gvt_phase; +extern _Thread_local uint32_t remote_msg_seq[2][MAX_NODES]; +extern _Thread_local uint32_t remote_msg_received[2]; extern void gvt_start_processing(void); extern void gvt_on_done_ctrl_msg(void); diff --git a/src/gvt/termination.c b/src/gvt/termination.c index e4a6ed9b..9f765b31 100644 --- a/src/gvt/termination.c +++ b/src/gvt/termination.c @@ -16,10 +16,10 @@ _Atomic nid_t nodes_to_end; /// The number of local threads that still need to continue running the simulation static _Atomic rid_t thr_to_end; /// The number of thread-locally bounded LPs that still need to continue running the simulation -static __thread uint64_t lps_to_end; +static _Thread_local uint64_t lps_to_end; /// The maximum speculative time at which a thread-local LP declared its intention to terminate /** FIXME: a wrong high termination time during a speculative trajectory forces the simulation to uselessly continue */ -static __thread simtime_t max_t; +static _Thread_local simtime_t max_t; /** * @brief Initialize the termination detection module node-wide diff --git a/src/log/stats.c b/src/log/stats.c index 70fd4c2e..6073c4a0 100644 --- a/src/log/stats.c +++ b/src/log/stats.c @@ -81,7 +81,7 @@ static FILE *stats_node_tmp; /// An array of pointers to the temporary files used to save #stats_thread structs produced by threads during simulation static FILE **stats_tmps; /// The current values of thread statistics for this logical time period (from the previous GVT to the next one) -static __thread struct stats_thread stats_cur; +static _Thread_local struct stats_thread stats_cur; /** * @brief Take a lifetime event time value diff --git a/src/lp/lp.c b/src/lp/lp.c index e692a2f3..865c2460 100644 --- a/src/lp/lp.c +++ b/src/lp/lp.c @@ -17,11 +17,11 @@ /// The lowest LP id between the ones hosted on this node uint64_t lid_node_first; /// The lowest LP id between the ones hosted on this thread -__thread uint64_t lid_thread_first; +_Thread_local uint64_t lid_thread_first; /// One plus the highest LP id between the ones hosted on this thread -__thread uint64_t lid_thread_end; +_Thread_local uint64_t lid_thread_end; /// A pointer to the currently processed LP context -__thread struct lp_ctx *current_lp; +_Thread_local struct lp_ctx *current_lp; /// A pointer to the LP contexts array /** Valid entries are contained between #lid_node_first and #lid_node_first + #n_lps_node - 1, limits included */ struct lp_ctx *lps; diff --git a/src/lp/lp.h b/src/lp/lp.h index 728f20da..7b4d4ac1 100644 --- a/src/lp/lp.h +++ b/src/lp/lp.h @@ -50,10 +50,10 @@ struct lp_ctx { #define lid_to_rid(lp_id) ((rid_t)(((lp_id) - lid_node_first) * global_config.n_threads / n_lps_node)) extern uint64_t lid_node_first; -extern __thread uint64_t lid_thread_first; -extern __thread uint64_t lid_thread_end; +extern _Thread_local uint64_t lid_thread_first; +extern _Thread_local uint64_t lid_thread_end; -extern __thread struct lp_ctx *current_lp; +extern _Thread_local struct lp_ctx *current_lp; extern struct lp_ctx *lps; #ifndef NDEBUG diff --git a/src/lp/process.c b/src/lp/process.c index 0d059127..9be6894d 100644 --- a/src/lp/process.c +++ b/src/lp/process.c @@ -23,11 +23,11 @@ #include /// The flag used in ScheduleNewEvent() to keep track of silent execution -static __thread bool silent_processing = false; +static _Thread_local bool silent_processing = false; #ifndef NDEBUG /// The currently processed message /** This is not necessary for normal operation, but it's useful in debug */ -static __thread struct lp_msg *current_msg; +static _Thread_local struct lp_msg *current_msg; #endif #define mark_msg_remote(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) | 2U)) diff --git a/src/mm/auto_ckpt.c b/src/mm/auto_ckpt.c index 7ac11a7d..39500f60 100644 --- a/src/mm/auto_ckpt.c +++ b/src/mm/auto_ckpt.c @@ -29,7 +29,7 @@ o *(((f)-1.0) / (f)) + s *(1.0 / (f)); \ }) -static __thread struct { +static _Thread_local struct { double ckpt_avg_cost; double inv_sil_avg_cost; } ackpt; diff --git a/src/mm/msg_allocator.c b/src/mm/msg_allocator.c index 170bcc9d..4273e690 100644 --- a/src/mm/msg_allocator.c +++ b/src/mm/msg_allocator.c @@ -14,8 +14,8 @@ #include #include -static __thread dyn_array(struct lp_msg *) free_list = {0}; -static __thread dyn_array(struct lp_msg *) at_gvt_list = {0}; +static _Thread_local dyn_array(struct lp_msg *) free_list = {0}; +static _Thread_local dyn_array(struct lp_msg *) at_gvt_list = {0}; /** * @brief Initialize the message allocator thread-local data structures diff --git a/test/old_tests/gvt/gvt_test.c b/test/old_tests/gvt/gvt_test.c index 7d01d97c..651ec224 100644 --- a/test/old_tests/gvt/gvt_test.c +++ b/test/old_tests/gvt/gvt_test.c @@ -18,7 +18,7 @@ static simtime_t bound_values[N_THREADS][6] = { {2.0, 3.4, 6.5, 6.5, 9.6, 11.0}, {1.2, 3.5, 6.4, 6.3, 9.7, 10.5}, }; -static __thread unsigned b_i = 0; +static _Thread_local unsigned b_i = 0; simtime_t msg_queue_time_peek(void) { From 63e68b4318a1df56b457ab1099a9d541b6d7130f Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 00:47:05 +0200 Subject: [PATCH 02/15] Add some const They are not improving any performance though. Signed-off-by: Alessandro Pellegrini --- src/ROOT-Sim.h | 73 +++++++++++----------- src/arch/io.c | 4 +- src/arch/thread.c | 6 +- src/core/sync.c | 2 +- src/datatypes/msg_queue.c | 4 +- src/distributed/control_msg.c | 2 +- src/distributed/mpi.c | 12 ++-- src/gvt/fossil.c | 2 +- src/gvt/gvt.c | 8 +-- src/gvt/termination.c | 14 ++--- src/log/file.c | 4 +- src/log/log.c | 2 +- src/log/stats.c | 12 ++-- src/lp/process.c | 56 ++++++++--------- src/mm/auto_ckpt.c | 10 +-- src/mm/buddy/buddy.c | 21 +++---- src/mm/buddy/buddy.h | 4 +- src/mm/buddy/multi.c | 24 +++---- src/mm/model_allocator.h | 4 +- src/mm/msg_allocator.c | 4 +- src/parallel/parallel.c | 4 +- src/serial/serial.c | 6 +- test/datatypes/bitmap.c | 16 +++-- test/gvt/termination.c | 4 +- test/integration/correctness/application.c | 12 ++-- test/integration/correctness/functions.c | 8 +-- test/integration/phold.c | 12 ++-- test/log/stats.c | 8 +-- test/mm/buddy.c | 8 +-- test/mm/buddy_hard.c | 26 ++++---- test/mm/parallel.c | 16 ++--- 31 files changed, 198 insertions(+), 190 deletions(-) diff --git a/src/ROOT-Sim.h b/src/ROOT-Sim.h index 821ce46a..681282f6 100644 --- a/src/ROOT-Sim.h +++ b/src/ROOT-Sim.h @@ -15,9 +15,7 @@ */ #pragma once -#include #include -#include #include #include #include @@ -68,7 +66,7 @@ typedef void (*ProcessEvent_t)(lp_id_t me, simtime_t now, unsigned event_type, c */ typedef bool (*CanEnd_t)(lp_id_t me, const void *snapshot); -enum rootsim_event {LP_INIT = 65534, LP_FINI}; +enum rootsim_event { LP_INIT = 65534, LP_FINI }; /** * @brief API to inject a new event in the simulation @@ -84,53 +82,58 @@ enum rootsim_event {LP_INIT = 65534, LP_FINI}; * @param event_size The size (in bytes) of the event content */ extern void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *event_content, - unsigned event_size); + unsigned event_size); extern void SetState(void *new_state); extern void *rs_malloc(size_t req_size); + extern void *rs_calloc(size_t nmemb, size_t size); + extern void rs_free(void *ptr); + extern void *rs_realloc(void *ptr, size_t req_size); enum log_level { - LOG_TRACE, //!< The logging level reserved to very low priority messages - LOG_DEBUG, //!< The logging level reserved to useful debug messages - LOG_INFO, //!< The logging level reserved to useful runtime messages - LOG_WARN, //!< The logging level reserved to unexpected, non deal breaking conditions - LOG_ERROR, //!< The logging level reserved to unexpected, problematic conditions - LOG_FATAL, //!< The logging level reserved to unexpected, fatal conditions - LOG_SILENT //!< Emit no message during the simulation + LOG_TRACE, //!< The logging level reserved to very low priority messages + LOG_DEBUG, //!< The logging level reserved to useful debug messages + LOG_INFO, //!< The logging level reserved to useful runtime messages + LOG_WARN, //!< The logging level reserved to unexpected, non deal breaking conditions + LOG_ERROR, //!< The logging level reserved to unexpected, problematic conditions + LOG_FATAL, //!< The logging level reserved to unexpected, fatal conditions + LOG_SILENT //!< Emit no message during the simulation }; /// A set of configurable values used by other modules struct simulation_configuration { - /// The number of LPs to be used in the simulation - lp_id_t lps; - /// The number of threads to be used in the simulation. If zero, it defaults to the amount of available cores - unsigned n_threads; - /// The target termination logical time. Setting this value to zero means that LVT-based termination is disabled - simtime_t termination_time; - /// The gvt period expressed in microseconds - unsigned gvt_period; - /// The logger verbosity level - enum log_level log_level; - /// File where to write logged information: if not NULL, output is redirected to this file - FILE *logfile; - /// Path to the statistics file. If NULL, no statistics are produced. - const char *stats_file; - /// The checkpointing interval - unsigned ckpt_interval; - /// If set, worker threads are bound to physical cores - bool core_binding; - /// If set, the simulation will run on the serial runtime - bool serial; - /// Function pointer to the dispatching function - ProcessEvent_t dispatcher; - /// Function pointer to the termination detection function - CanEnd_t committed; + /// The number of LPs to be used in the simulation + lp_id_t lps; + /// The number of threads to be used in the simulation. If zero, it defaults to the amount of available cores + unsigned n_threads; + /// The target termination logical time. Setting this value to zero means that LVT-based termination is disabled + simtime_t termination_time; + /// The gvt period expressed in microseconds + unsigned gvt_period; + /// The logger verbosity level + enum log_level log_level; + /// File where to write logged information: if not NULL, output is redirected to this file + FILE *logfile; + /// Path to the statistics file. If NULL, no statistics are produced. + const char *stats_file; + /// The checkpointing interval + unsigned ckpt_interval; + /// If set, worker threads are bound to physical cores + bool core_binding; + /// If set, the simulation will run on the serial runtime + bool serial; + /// Function pointer to the dispatching function + ProcessEvent_t dispatcher; + /// Function pointer to the termination detection function + CanEnd_t committed; }; extern int RootsimInit(const struct simulation_configuration *conf); + extern int RootsimRun(void); + extern void RootsimStop(void); diff --git a/src/arch/io.c b/src/arch/io.c index f9204d5d..e46249ba 100644 --- a/src/arch/io.c +++ b/src/arch/io.c @@ -31,8 +31,8 @@ void io_local_time_get(char res[IO_TIME_BUFFER_LEN]) { - time_t t = time(NULL); - struct tm *loc_t = localtime(&t); + const time_t t = time(NULL); + const struct tm *loc_t = localtime(&t); strftime(res, IO_TIME_BUFFER_LEN, "%H:%M:%S", loc_t); } diff --git a/src/arch/thread.c b/src/arch/thread.c index 2d6fe675..789bf498 100644 --- a/src/arch/thread.c +++ b/src/arch/thread.c @@ -99,7 +99,7 @@ enum thread_affinity_error thread_affinity_self_set(unsigned core) CPU_ZERO(&cpuset); CPU_SET(i, &cpuset); - pthread_t self = pthread_self(); + const pthread_t self = pthread_self(); switch(pthread_setaffinity_np(self, sizeof(cpuset), &cpuset)) { case 0: return THREAD_AFFINITY_SUCCESS; @@ -128,12 +128,12 @@ unsigned thread_cores_count(void) #endif -int thread_start(thr_id_t *thr_p, thr_run_fnc t_fnc, void *t_fnc_arg) +int thread_start(thr_id_t *thr_p, const thr_run_fnc t_fnc, void *t_fnc_arg) { return -(pthread_create(thr_p, NULL, t_fnc, t_fnc_arg) != 0); } -int thread_wait(thr_id_t thr, thrd_ret_t *ret) +int thread_wait(const thr_id_t thr, thrd_ret_t *ret) { return -(pthread_join(thr, ret) != 0); } diff --git a/src/core/sync.c b/src/core/sync.c index c4ba0cdb..468ef676 100644 --- a/src/core/sync.c +++ b/src/core/sync.c @@ -32,7 +32,7 @@ bool sync_thread_barrier(void) } while(r); } else { l = !atomic_fetch_add_explicit(c, 1, memory_order_acq_rel); - rid_t thr_cnt = global_config.n_threads; + const rid_t thr_cnt = global_config.n_threads; do { r = atomic_load_explicit(c, memory_order_relaxed); } while(r != thr_cnt); diff --git a/src/datatypes/msg_queue.c b/src/datatypes/msg_queue.c index 33dbdd3a..3f7ae227 100644 --- a/src/datatypes/msg_queue.c +++ b/src/datatypes/msg_queue.c @@ -94,7 +94,7 @@ static inline void msg_queue_insert_queued(void) { struct lp_msg *m = atomic_exchange_explicit(&queues[rid].list, NULL, memory_order_acquire); while(m != NULL) { - struct q_elem qe = {.t = m->dest_t, .m = m}; + const struct q_elem qe = {.t = m->dest_t, .m = m}; heap_insert(mqp, q_elem_is_before, qe); m = m->next; } @@ -133,6 +133,6 @@ void msg_queue_insert(struct lp_msg *msg) void msg_queue_insert_self(struct lp_msg *msg) { assert(lid_to_rid(msg->dest) == rid); - struct q_elem qe = {.t = msg->dest_t, .m = msg}; + const struct q_elem qe = {.t = msg->dest_t, .m = msg}; heap_insert(mqp, q_elem_is_before, qe); } diff --git a/src/distributed/control_msg.c b/src/distributed/control_msg.c index 225cca1b..f5cf7b58 100644 --- a/src/distributed/control_msg.c +++ b/src/distributed/control_msg.c @@ -14,7 +14,7 @@ * @brief Handle a received control message * @param ctrl the tag of the received control message */ -void control_msg_process(enum msg_ctrl_code ctrl) +void control_msg_process(const enum msg_ctrl_code ctrl) { switch(ctrl) { case MSG_CTRL_GVT_START: diff --git a/src/distributed/mpi.c b/src/distributed/mpi.c index e0151c22..107acb69 100644 --- a/src/distributed/mpi.c +++ b/src/distributed/mpi.c @@ -108,7 +108,7 @@ void mpi_global_fini(void) * for sending completion: the platform, during the fossil collection, leverages the gvt to make sure the message has * been indeed sent and processed before freeing it. */ -void mpi_remote_msg_send(struct lp_msg *msg, nid_t dest_nid) +void mpi_remote_msg_send(struct lp_msg *msg, const nid_t dest_nid) { gvt_remote_msg_send(msg, dest_nid); @@ -127,7 +127,7 @@ void mpi_remote_msg_send(struct lp_msg *msg, nid_t dest_nid) * for sending completion: the platform, during the fossil collection, leverages the gvt to make sure the message has * been indeed sent and processed before freeing it. */ -void mpi_remote_anti_msg_send(struct lp_msg *msg, nid_t dest_nid) +void mpi_remote_anti_msg_send(struct lp_msg *msg, const nid_t dest_nid) { gvt_remote_anti_msg_send(msg, dest_nid); @@ -140,7 +140,7 @@ void mpi_remote_anti_msg_send(struct lp_msg *msg, nid_t dest_nid) * @brief Sends a platform control message to all the nodes, including self * @param ctrl the control message to send */ -void mpi_control_msg_broadcast(enum msg_ctrl_code ctrl) +void mpi_control_msg_broadcast(const enum msg_ctrl_code ctrl) { nid_t i = n_nodes; while(i--) { @@ -153,7 +153,7 @@ void mpi_control_msg_broadcast(enum msg_ctrl_code ctrl) * @param ctrl the control message to send * @param dest the id of the destination node */ -void mpi_control_msg_send_to(enum msg_ctrl_code ctrl, nid_t dest) +void mpi_control_msg_send_to(const enum msg_ctrl_code ctrl, const nid_t dest) { MPI_Request req; MPI_Isend(&ctrl_msgs[ctrl], sizeof(*ctrl_msgs), MPI_BYTE, dest, RS_MSG_TAG, MPI_COMM_WORLD, &req); @@ -320,7 +320,7 @@ void mpi_node_barrier(void) * This operation blocks the execution flow until the destination node receives * the data with mpi_raw_data_blocking_rcv(). */ -void mpi_blocking_data_send(const void *data, int data_size, nid_t dest) +void mpi_blocking_data_send(const void *data, const int data_size, const nid_t dest) { MPI_Send(data, data_size, MPI_BYTE, dest, RS_DATA_TAG, MPI_COMM_WORLD); } @@ -333,7 +333,7 @@ void mpi_blocking_data_send(const void *data, int data_size, nid_t dest) * * This operation blocks the execution until the sender node actually sends the data with mpi_raw_data_blocking_send(). */ -void *mpi_blocking_data_rcv(int *data_size_p, nid_t src) +void *mpi_blocking_data_rcv(int *data_size_p, const nid_t src) { MPI_Status status; MPI_Message mpi_msg; diff --git a/src/gvt/fossil.c b/src/gvt/fossil.c index cf4de9e6..06b89120 100644 --- a/src/gvt/fossil.c +++ b/src/gvt/fossil.c @@ -37,7 +37,7 @@ void fossil_lp_collect(struct lp_ctx *lp) if(past_i == 0) return; - simtime_t gvt = fossil_gvt_current; + const simtime_t gvt = fossil_gvt_current; for(const struct lp_msg *msg = array_get_at(proc_p->p_msgs, --past_i); msg->dest_t >= gvt;) { do { if(!past_i) diff --git a/src/gvt/gvt.c b/src/gvt/gvt.c index 577ad1f7..886ce316 100644 --- a/src/gvt/gvt.c +++ b/src/gvt/gvt.c @@ -126,7 +126,7 @@ void gvt_on_done_ctrl_msg(void) * * Called by the process layer when processing a new message; used in the actual GVT calculation */ -void gvt_on_msg_extraction(simtime_t msg_t) +void gvt_on_msg_extraction(const simtime_t msg_t) { if(unlikely(gvt_accumulator > msg_t)) gvt_accumulator = msg_t; @@ -223,12 +223,12 @@ static bool gvt_node_phase_run(void) break; case node_sent_wait: { - int32_t r = atomic_fetch_add_explicit(&total_msg_received, + const int32_t r = atomic_fetch_add_explicit(&total_msg_received, remote_msg_received[!gvt_phase], memory_order_relaxed); remote_msg_received[!gvt_phase] = 0; if(r) break; - uint32_t q = n_nodes / global_config.n_threads + 1; + const uint32_t q = n_nodes / global_config.n_threads + 1; memset(total_sent + rid * q, 0, q * sizeof(*total_sent)); node_phase = node_phase_redux_second; break; @@ -283,7 +283,7 @@ simtime_t gvt_phase_run(void) gvt_start_processing(); if(unlikely(!rid && !nid)) { - timer_uint t = timer_new(); + const timer_uint t = timer_new(); if(unlikely(global_config.gvt_period < t - gvt_timer && !atomic_load_explicit(&gvt_nodes, memory_order_relaxed))) { gvt_timer = t; diff --git a/src/gvt/termination.c b/src/gvt/termination.c index 9f765b31..c8ab63f9 100644 --- a/src/gvt/termination.c +++ b/src/gvt/termination.c @@ -35,7 +35,7 @@ void termination_global_init(void) */ void termination_lp_init(struct lp_ctx *lp) { - bool term = global_config.committed(lp - lps, lp->state_pointer); + const bool term = global_config.committed(lp - lps, lp->state_pointer); lps_to_end += !term; lp->termination_t = term * SIMTIME_MAX; } @@ -49,7 +49,7 @@ void termination_on_msg_process(struct lp_ctx *lp, simtime_t msg_time) if(lp->termination_t) return; - bool term = global_config.committed(lp - lps, lp->state_pointer); + const bool term = global_config.committed(lp - lps, lp->state_pointer); max_t = term ? max(msg_time, max_t) : max_t; lp->termination_t = term * msg_time; lps_to_end -= term; @@ -70,12 +70,12 @@ void termination_on_ctrl_msg(void) * other processing threads on the node are willing to end the simulation, a termination control message is broadcast to * the other nodes. */ -void termination_on_gvt(simtime_t current_gvt) +void termination_on_gvt(const simtime_t current_gvt) { if(likely((lps_to_end || max_t >= current_gvt) && current_gvt < global_config.termination_time)) return; max_t = SIMTIME_MAX; - unsigned t = atomic_fetch_sub_explicit(&thr_to_end, 1U, memory_order_relaxed); + const unsigned t = atomic_fetch_sub_explicit(&thr_to_end, 1U, memory_order_relaxed); if(t == 1) mpi_control_msg_broadcast(MSG_CTRL_TERMINATION); } @@ -99,10 +99,10 @@ void RootsimStop(void) * @brief Compute termination operations after a LP has been rollbacked * @param msg_time the timestamp of the straggler or anti message which caused the rollback */ -void termination_on_lp_rollback(struct lp_ctx *lp, simtime_t msg_time) +void termination_on_lp_rollback(struct lp_ctx *lp, const simtime_t msg_time) { - simtime_t old_t = lp->termination_t; - bool keep = old_t < msg_time || old_t == SIMTIME_MAX; + const simtime_t old_t = lp->termination_t; + const bool keep = old_t < msg_time || old_t == SIMTIME_MAX; lp->termination_t = keep * old_t; lps_to_end += !keep; } diff --git a/src/log/file.c b/src/log/file.c index 3f187f35..c3fe58d5 100644 --- a/src/log/file.c +++ b/src/log/file.c @@ -24,7 +24,7 @@ void *file_memory_load(FILE *f, int64_t *f_size_p) { fseek(f, 0, SEEK_END); - long f_size = ftell(f); // FIXME: may fail horribly for files bigger than 2 GB + const long f_size = ftell(f); // FIXME: may fail horribly for files bigger than 2 GB fseek(f, 0, SEEK_SET); void *ret = mm_alloc(f_size); if(fread(ret, f_size, 1, f) != 1) { @@ -48,7 +48,7 @@ FILE *file_open(const char *open_type, const char *fmt, ...) va_start(args, fmt); va_copy(args_cp, args); - size_t l = vsnprintf(NULL, 0, fmt, args_cp) + 1; + const size_t l = vsnprintf(NULL, 0, fmt, args_cp) + 1; va_end(args_cp); char *f_name = mm_alloc(l); diff --git a/src/log/log.c b/src/log/log.c index e921d4ff..93f9199f 100644 --- a/src/log/log.c +++ b/src/log/log.c @@ -40,7 +40,7 @@ static const struct { * @param fmt a printf-style format string for the message to logger * @param ... the list of arguments to fill in the format string @a fmt */ -void vlogger(enum log_level level, char *file, unsigned line, const char *fmt, ...) +void vlogger(const enum log_level level, char *file, const unsigned line, const char *fmt, ...) { va_list args; char time_string[IO_TIME_BUFFER_LEN]; diff --git a/src/log/stats.c b/src/log/stats.c index 6073c4a0..ff715663 100644 --- a/src/log/stats.c +++ b/src/log/stats.c @@ -87,7 +87,7 @@ static _Thread_local struct stats_thread stats_cur; * @brief Take a lifetime event time value * @param this_stat The type of event just occurred */ -void stats_global_time_take(enum stats_global_type this_stat) +void stats_global_time_take(const enum stats_global_type this_stat) { stats_glob_cur.timestamps[this_stat] = timer_value(sim_start_ts); } @@ -149,7 +149,7 @@ static void stats_files_receive(FILE *out_f) struct stats_global *sg_p = mpi_blocking_data_rcv(&buf_size, j); if(likely(out_f != NULL)) file_write_chunk(out_f, sg_p, buf_size); - uint64_t iters = sg_p->threads_count + 1; // +1 for node stats + const uint64_t iters = sg_p->threads_count + 1; // +1 for node stats mm_free(sg_p); for(uint64_t i = 0; i < iters; ++i) { @@ -251,7 +251,7 @@ static void stats_files_send(void) */ static void stats_file_final_write(FILE *out_f) { - uint16_t endian_check = 61455U; + const uint16_t endian_check = 61455U; file_write_chunk(out_f, &endian_check, sizeof(endian_check)); int64_t n = STATS_COUNT; @@ -325,7 +325,7 @@ void stats_global_fini(void) * @param this_stat the statistics type to add the sample to * @param c the sample to sum */ -void stats_take(enum stats_thread_type this_stat, uint_fast64_t c) +void stats_take(const enum stats_thread_type this_stat, const uint_fast64_t c) { stats_cur.s[this_stat] += c; } @@ -375,7 +375,7 @@ void stats_dump(void) puts(""); fflush(stdout); } - double t = (double)timer_value(sim_start_ts) / 1000000.0; + const double t = (double)timer_value(sim_start_ts) / 1000000.0; logger(LOG_INFO, "Simulation completed in %.3lf seconds", t); } } @@ -385,7 +385,7 @@ void stats_dump(void) * * This values are computed since the end of the last GVT. */ -uint64_t stats_retrieve(enum stats_thread_type this_stat) +uint64_t stats_retrieve(const enum stats_thread_type this_stat) { return stats_cur.s[this_stat]; } diff --git a/src/lp/process.c b/src/lp/process.c index 9be6894d..28a50106 100644 --- a/src/lp/process.c +++ b/src/lp/process.c @@ -35,7 +35,7 @@ static _Thread_local struct lp_msg *current_msg; #define unmark_msg_remote(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) - 2U)) #define unmark_msg_sent(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) - 1U)) -void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *payload, +void ScheduleNewEvent(const lp_id_t receiver, const simtime_t timestamp, const unsigned event_type, const void *payload, unsigned payload_size) { if(unlikely(global_config.serial)) { @@ -57,7 +57,7 @@ void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp, unsigned event_type msg->send_t = current_msg->dest_t; #endif - nid_t dest_nid = lid_to_nid(receiver); + const nid_t dest_nid = lid_to_nid(receiver); if(dest_nid != nid) { mpi_remote_msg_send(msg, dest_nid); array_push(current_lp->p.p_msgs, mark_msg_remote(msg)); @@ -76,7 +76,7 @@ void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp, unsigned event_type */ static inline void checkpoint_take(struct lp_ctx *lp) { - timer_uint t = timer_hr_new(); + const timer_uint t = timer_hr_new(); model_allocator_checkpoint_take(&lp->mm_state, array_count(lp->p.p_msgs)); stats_take(STATS_CKPT_SIZE, lp->mm_state.full_ckpt_size); stats_take(STATS_CKPT, 1); @@ -118,9 +118,9 @@ void process_lp_fini(struct lp_ctx *lp) if(is_msg_local_sent(msg)) continue; - bool remote = is_msg_remote(msg); + const bool remote = is_msg_remote(msg); msg = unmark_msg(msg); - uint32_t flags = atomic_load_explicit(&msg->flags, memory_order_relaxed); + const uint32_t flags = atomic_load_explicit(&msg->flags, memory_order_relaxed); if(remote || !(flags & MSG_FLAG_ANTI)) msg_allocator_free(msg); } @@ -129,18 +129,18 @@ void process_lp_fini(struct lp_ctx *lp) /** * @brief Perform silent execution of events - * @param proc_p the message processing data for the LP that has to coast forward + * @param lp the message processing data for the LP that has to coast forward * @param last_i the index in @a proc_p of the last processed message in the current LP state * @param past_i the target index in @a proc_p of the message to reach with the silent execution operation * * This function implements the coasting forward operation done after a checkpoint has been restored. */ -static inline void silent_execution(const struct lp_ctx *lp, array_count_t last_i, array_count_t past_i) +static inline void silent_execution(const struct lp_ctx *lp, array_count_t last_i, const array_count_t past_i) { if(unlikely(last_i >= past_i)) return; - timer_uint t = timer_hr_new(); + const timer_uint t = timer_hr_new(); silent_processing = true; void *state_p = lp->state_pointer; @@ -159,51 +159,51 @@ static inline void silent_execution(const struct lp_ctx *lp, array_count_t last_ /** * @brief Send anti-messages - * @param proc_p the message processing data for the LP that has to send anti-messages + * @param lp the message processing data for the LP that has to send anti-messages * @param past_i the index in @a proc_p of the last validly processed message */ -static inline void send_anti_messages(struct process_ctx *proc_p, array_count_t past_i) +static inline void send_anti_messages(struct process_ctx *lp, const array_count_t past_i) { - array_count_t p_cnt = array_count(proc_p->p_msgs); + const array_count_t p_cnt = array_count(lp->p_msgs); for(array_count_t i = past_i; i < p_cnt; ++i) { - struct lp_msg *msg = array_get_at(proc_p->p_msgs, i); + struct lp_msg *msg = array_get_at(lp->p_msgs, i); while(is_msg_sent(msg)) { if(is_msg_remote(msg)) { msg = unmark_msg_remote(msg); - nid_t dest_nid = lid_to_nid(msg->dest); + const nid_t dest_nid = lid_to_nid(msg->dest); mpi_remote_anti_msg_send(msg, dest_nid); msg_allocator_free_at_gvt(msg); } else { msg = unmark_msg_sent(msg); - uint32_t f = + const uint32_t f = atomic_fetch_add_explicit(&msg->flags, MSG_FLAG_ANTI, memory_order_relaxed); if(f & MSG_FLAG_PROCESSED) msg_queue_insert(msg); } stats_take(STATS_MSG_ANTI, 1); - msg = array_get_at(proc_p->p_msgs, ++i); + msg = array_get_at(lp->p_msgs, ++i); } - uint32_t f = atomic_fetch_add_explicit(&msg->flags, -MSG_FLAG_PROCESSED, memory_order_relaxed); + const uint32_t f = atomic_fetch_add_explicit(&msg->flags, -MSG_FLAG_PROCESSED, memory_order_relaxed); if(!(f & MSG_FLAG_ANTI)) msg_queue_insert_self(msg); stats_take(STATS_MSG_ROLLBACK, 1); } - array_count(proc_p->p_msgs) = past_i; + array_count(lp->p_msgs) = past_i; } /** * @brief Perform a rollback - * @param proc_p the message processing data for the LP that has to rollback + * @param lp the message processing data for the LP that has to rollback * @param past_i the index in @a proc_p of the last validly processed message */ -static void do_rollback(struct lp_ctx *lp, array_count_t past_i) +static void do_rollback(struct lp_ctx *lp, const array_count_t past_i) { - timer_uint t = timer_hr_new(); + const timer_uint t = timer_hr_new(); send_anti_messages(&lp->p, past_i); - array_count_t last_i = model_allocator_checkpoint_restore(&lp->mm_state, past_i); + const array_count_t last_i = model_allocator_checkpoint_restore(&lp->mm_state, past_i); stats_take(STATS_RECOVERY_TIME, timer_hr_value(t)); stats_take(STATS_ROLLBACK, 1); silent_execution(lp, last_i, past_i); @@ -258,7 +258,7 @@ static inline void handle_remote_anti_msg(struct lp_ctx *lp, struct lp_msg *a_ms // Simplifies flags-based matching, also useful in the early remote anti-messages matching a_msg->raw_flags -= MSG_FLAG_ANTI; - uint32_t m_id = a_msg->raw_flags, m_seq = a_msg->m_seq; + const uint32_t m_id = a_msg->raw_flags, m_seq = a_msg->m_seq; array_count_t i = array_count(lp->p.p_msgs); struct lp_msg *msg; do { @@ -294,7 +294,7 @@ static inline void handle_remote_anti_msg(struct lp_ctx *lp, struct lp_msg *a_ms */ static inline bool check_early_anti_messages(struct process_ctx *proc_p, struct lp_msg *msg) { - uint32_t m_id = msg->raw_flags, m_seq = msg->m_seq; + const uint32_t m_id = msg->raw_flags, m_seq = msg->m_seq; struct lp_msg **prev_p = &proc_p->early_antis; struct lp_msg *a_msg = *prev_p; do { @@ -316,14 +316,14 @@ static inline bool check_early_anti_messages(struct process_ctx *proc_p, struct * @param msg the received anti-message * @param last_flags the original value of the message flags before being modified by the current process_msg() call */ -static void handle_anti_msg(struct lp_ctx *lp, struct lp_msg *msg, uint32_t last_flags) +static void handle_anti_msg(struct lp_ctx *lp, struct lp_msg *msg, const uint32_t last_flags) { if(last_flags > (MSG_FLAG_ANTI | MSG_FLAG_PROCESSED)) { handle_remote_anti_msg(lp, msg); auto_ckpt_register_bad(&lp->auto_ckpt); return; } else if(last_flags == (MSG_FLAG_ANTI | MSG_FLAG_PROCESSED)) { - array_count_t past_i = match_anti_msg(&lp->p, msg); + const array_count_t past_i = match_anti_msg(&lp->p, msg); do_rollback(lp, past_i); termination_on_lp_rollback(lp, msg->dest_t); auto_ckpt_register_bad(&lp->auto_ckpt); @@ -336,9 +336,9 @@ static void handle_anti_msg(struct lp_ctx *lp, struct lp_msg *msg, uint32_t last * @param lp the processing context of the current LP * @param msg the received straggler message */ -static void handle_straggler_msg(struct lp_ctx *lp, struct lp_msg *msg) +static void handle_straggler_msg(struct lp_ctx *lp, const struct lp_msg *msg) { - array_count_t past_i = match_straggler_msg(&lp->p, msg); + const array_count_t past_i = match_straggler_msg(&lp->p, msg); do_rollback(lp, past_i); termination_on_lp_rollback(lp, msg->dest_t); auto_ckpt_register_bad(&lp->auto_ckpt); @@ -351,7 +351,7 @@ static void handle_straggler_msg(struct lp_ctx *lp, struct lp_msg *msg) */ void process_msg(void) { - timer_uint t = timer_hr_new(); + const timer_uint t = timer_hr_new(); struct lp_msg *msg = msg_queue_extract(); stats_take(STATS_MSG_EXTRACTION, timer_hr_value(t)); if(unlikely(!msg)) { diff --git a/src/mm/auto_ckpt.c b/src/mm/auto_ckpt.c index 39500f60..14eb2db5 100644 --- a/src/mm/auto_ckpt.c +++ b/src/mm/auto_ckpt.c @@ -54,10 +54,10 @@ void auto_ckpt_on_gvt(void) if(unlikely(global_config.ckpt_interval)) return; - uint64_t ckpt_cost = stats_retrieve(STATS_CKPT_TIME); - uint64_t ckpt_size = stats_retrieve(STATS_CKPT_SIZE); - uint64_t sil_count = stats_retrieve(STATS_MSG_SILENT); - uint64_t sil_cost = stats_retrieve(STATS_MSG_SILENT_TIME); + const uint64_t ckpt_cost = stats_retrieve(STATS_CKPT_TIME); + const uint64_t ckpt_size = stats_retrieve(STATS_CKPT_SIZE); + const uint64_t sil_count = stats_retrieve(STATS_MSG_SILENT); + const uint64_t sil_cost = stats_retrieve(STATS_MSG_SILENT_TIME); if(likely(sil_count)) ackpt.inv_sil_avg_cost = EXP_AVG(16.0, ackpt.inv_sil_avg_cost, (double)sil_count / (double)sil_cost); @@ -82,7 +82,7 @@ void auto_ckpt_lp_init(struct auto_ckpt *auto_ckpt) * @param auto_ckpt a pointer to the auto checkpoint context of the current LP * @param state_size the size in bytes of the checkpoint-able state of the current LP */ -void auto_ckpt_recompute(struct auto_ckpt *auto_ckpt, uint_fast32_t state_size) +void auto_ckpt_recompute(struct auto_ckpt *auto_ckpt, const uint_fast32_t state_size) { if(unlikely(!auto_ckpt->m_bad || global_config.ckpt_interval)) return; diff --git a/src/mm/buddy/buddy.c b/src/mm/buddy/buddy.c index 01b1771e..4392b2a7 100644 --- a/src/mm/buddy/buddy.c +++ b/src/mm/buddy/buddy.c @@ -21,7 +21,7 @@ void buddy_init(struct buddy_state *self) } } -void *buddy_malloc(struct buddy_state *self, uint_fast8_t req_blks_exp) +void *buddy_malloc(struct buddy_state *self, const uint_fast8_t req_blks_exp) { if(unlikely(self->longest[0] < req_blks_exp)) return NULL; @@ -43,7 +43,7 @@ void *buddy_malloc(struct buddy_state *self, uint_fast8_t req_blks_exp) bitmap_set(self->dirty, i >> B_BLOCK_EXP); #endif - uint_fast32_t offset = ((i + 1) << node_size) - (1 << B_TOTAL_EXP); + const uint_fast32_t offset = ((i + 1) << node_size) - (1 << B_TOTAL_EXP); while(i) { i = buddy_parent(i); @@ -66,7 +66,7 @@ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) ++node_size; self->longest[i] = node_size; - uint_fast32_t ret = (uint_fast32_t)1U << node_size; + const uint_fast32_t ret = (uint_fast32_t)1U << node_size; #ifdef ROOTSIM_INCREMENTAL bitmap_set(self->dirty, i >> B_BLOCK_EXP); @@ -97,18 +97,18 @@ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) return ret; } -struct buddy_realloc_res buddy_best_effort_realloc(struct buddy_state *self, void *ptr, size_t req_size) +struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *self, void *ptr, size_t req_size) { uint_fast8_t node_size = B_BLOCK_EXP; - uint_fast32_t o = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; + const uint_fast32_t o = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; uint_fast32_t i = o + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; for(; self->longest[i]; i = buddy_parent(i)) ++node_size; - uint_fast8_t req_blks_exp = buddy_allocation_block_compute(req_size); + const uint_fast8_t req_blks_exp = buddy_allocation_block_compute(req_size); - struct buddy_realloc_res ret; + struct buddy_realloc_res ret = {0}; if(node_size == req_blks_exp) { // todo: we can do much better than this @@ -125,11 +125,10 @@ struct buddy_realloc_res buddy_best_effort_realloc(struct buddy_state *self, voi return ret; } -void buddy_dirty_mark(struct buddy_state *self, const void *ptr, size_t s) +void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t s) { - // TODO: consider using ptrdiff_t here - uintptr_t diff = (uintptr_t)ptr - (uintptr_t)self->base_mem; - uint_fast32_t i = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); + const uintptr_t diff = ptr - (void *)self->base_mem; + const uint_fast32_t i = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); s += diff & ((1 << B_BLOCK_EXP) - 1); --s; diff --git a/src/mm/buddy/buddy.h b/src/mm/buddy/buddy.h index c3005a03..38bb2ad4 100644 --- a/src/mm/buddy/buddy.h +++ b/src/mm/buddy/buddy.h @@ -61,5 +61,5 @@ struct buddy_realloc_res { uint_fast32_t original; }; }; -extern struct buddy_realloc_res buddy_best_effort_realloc(struct buddy_state *self, void *ptr, size_t req_size); -extern void buddy_dirty_mark(struct buddy_state *self, const void *ptr, size_t s); +extern struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *self, void *ptr, size_t req_size); +extern void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t s); diff --git a/src/mm/buddy/multi.c b/src/mm/buddy/multi.c index 5aad56b7..c64ba95a 100644 --- a/src/mm/buddy/multi.c +++ b/src/mm/buddy/multi.c @@ -29,7 +29,7 @@ void model_allocator_lp_init(struct mm_state *self) self->full_ckpt_size = offsetof(struct mm_checkpoint, chkps) + sizeof(struct buddy_state *); } -void model_allocator_lp_fini(struct mm_state *self) +void model_allocator_lp_fini(const struct mm_state *self) { array_count_t i = array_count(self->logs); while(i--) @@ -49,7 +49,7 @@ void *rs_malloc(size_t req_size) if(unlikely(!req_size)) return NULL; - uint_fast8_t req_blks_exp = buddy_allocation_block_compute(req_size); + const uint_fast8_t req_blks_exp = buddy_allocation_block_compute(req_size); if(unlikely(req_blks_exp > B_TOTAL_EXP)) { errno = ENOMEM; logger(LOG_WARN, "LP %p requested a memory block bigger than %u!", current_lp, 1U << B_TOTAL_EXP); @@ -78,9 +78,9 @@ void *rs_malloc(size_t req_size) return buddy_malloc(new_buddy, req_blks_exp); } -void *rs_calloc(size_t nmemb, size_t size) +void *rs_calloc(const size_t nmemb, const size_t size) { - size_t tot = nmemb * size; + const size_t tot = nmemb * size; void *ret = rs_malloc(tot); if(likely(ret)) @@ -89,11 +89,11 @@ void *rs_calloc(size_t nmemb, size_t size) return ret; } -static inline struct buddy_state *buddy_find_by_address(struct mm_state *self, const void *ptr) +static inline struct buddy_state *buddy_find_by_address(const struct mm_state *self, const void *ptr) { array_count_t l = 0, h = array_count(self->buddies) - 1; while(1) { - array_count_t m = (l + h) / 2; + const array_count_t m = (l + h) / 2; struct buddy_state *b = array_get_at(self->buddies, m); if(ptr < (void *)b) h = m - 1; @@ -142,7 +142,7 @@ void *rs_realloc(void *ptr, size_t req_size) return new_buffer; } -void __write_mem(const void *ptr, size_t s) +void __write_mem(const void *ptr, const size_t s) { struct mm_state *self = ¤t_lp->mm_state; if(unlikely(!s || array_is_empty(self->buddies))) @@ -162,7 +162,7 @@ void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_i) struct mm_checkpoint *ckp = mm_alloc(self->full_ckpt_size); ckp->ckpt_size = self->full_ckpt_size; - struct mm_log mm_log = {.ref_i = ref_i, .c = ckp}; + const struct mm_log mm_log = {.ref_i = ref_i, .c = ckp}; array_push(self->logs, mm_log); struct buddy_checkpoint *buddy_ckp = (struct buddy_checkpoint *)ckp->chkps; @@ -172,19 +172,19 @@ void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_i) buddy_ckp->orig = NULL; } -void model_allocator_checkpoint_next_force_full(struct mm_state *self) +void model_allocator_checkpoint_next_force_full(const struct mm_state *self) { (void)self; // TODO: force full checkpointing when incremental state saving is enabled } -array_count_t model_allocator_checkpoint_restore(struct mm_state *self, array_count_t ref_i) +array_count_t model_allocator_checkpoint_restore(struct mm_state *self, const array_count_t ref_i) { array_count_t i = array_count(self->logs) - 1; while(array_get_at(self->logs, i).ref_i > ref_i) i--; - struct mm_checkpoint *ckp = array_get_at(self->logs, i).c; + const struct mm_checkpoint *ckp = array_get_at(self->logs, i).c; self->full_ckpt_size = ckp->ckpt_size; const struct buddy_checkpoint *buddy_ckp = (struct buddy_checkpoint *)ckp->chkps; @@ -207,7 +207,7 @@ array_count_t model_allocator_checkpoint_restore(struct mm_state *self, array_co return array_get_at(self->logs, i).ref_i; } -array_count_t model_allocator_fossil_lp_collect(struct mm_state *self, array_count_t tgt_ref_i) +array_count_t model_allocator_fossil_lp_collect(struct mm_state *self, const array_count_t tgt_ref_i) { array_count_t log_i = array_count(self->logs) - 1; array_count_t ref_i = array_get_at(self->logs, log_i).ref_i; diff --git a/src/mm/model_allocator.h b/src/mm/model_allocator.h index 3c698bca..9fb9a5f1 100644 --- a/src/mm/model_allocator.h +++ b/src/mm/model_allocator.h @@ -14,8 +14,8 @@ #include extern void model_allocator_lp_init(struct mm_state *self); -extern void model_allocator_lp_fini(struct mm_state *self); +extern void model_allocator_lp_fini(const struct mm_state *self); extern void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_i); -extern void model_allocator_checkpoint_next_force_full(struct mm_state *self); +extern void model_allocator_checkpoint_next_force_full(const struct mm_state *self); extern array_count_t model_allocator_checkpoint_restore(struct mm_state *self, array_count_t ref_i); extern array_count_t model_allocator_fossil_lp_collect(struct mm_state *self, array_count_t tgt_ref_i); diff --git a/src/mm/msg_allocator.c b/src/mm/msg_allocator.c index 4273e690..d2346320 100644 --- a/src/mm/msg_allocator.c +++ b/src/mm/msg_allocator.c @@ -48,7 +48,7 @@ void msg_allocator_fini(void) * Since this module relies on the member lp_msg.pl_size (see @a msg_allocator_free()), it has writing responsibility * on it. */ -struct lp_msg *msg_allocator_alloc(unsigned payload_size) +struct lp_msg *msg_allocator_alloc(const unsigned payload_size) { struct lp_msg *ret; if(unlikely(payload_size > MSG_PAYLOAD_BASE_SIZE)) { @@ -87,7 +87,7 @@ void msg_allocator_free_at_gvt(struct lp_msg *msg) * @brief Free the committed messages after a new GVT has been computed * @param current_gvt the latest value of the GVT */ -void msg_allocator_on_gvt(simtime_t current_gvt) +void msg_allocator_on_gvt(const simtime_t current_gvt) { for(array_count_t i = array_count(at_gvt_list); i-- > 0;) { struct lp_msg *msg = array_get_at(at_gvt_list, i); diff --git a/src/parallel/parallel.c b/src/parallel/parallel.c index 109e106f..e10e035f 100644 --- a/src/parallel/parallel.c +++ b/src/parallel/parallel.c @@ -47,7 +47,7 @@ static void worker_affinity_set(void) * @brief Initialize the worker thread data structures * @param this_rid The numerical identifier of the worker thread */ -static void worker_thread_init(rid_t this_rid) +static void worker_thread_init(const rid_t this_rid) { rid = this_rid; @@ -110,7 +110,7 @@ static thrd_ret_t THREAD_CALL_CONV parallel_thread_run(void *rid_arg) while(i--) process_msg(); - simtime_t current_gvt = gvt_phase_run(); + const simtime_t current_gvt = gvt_phase_run(); if(unlikely(current_gvt != 0.0)) { termination_on_gvt(current_gvt); auto_ckpt_on_gvt(); diff --git a/src/serial/serial.c b/src/serial/serial.c index cde1d0fb..54727553 100644 --- a/src/serial/serial.c +++ b/src/serial/serial.c @@ -105,7 +105,7 @@ static int serial_simulation_run(void) last_vt = timer_new(); } - timer_uint t = timer_hr_new(); + const timer_uint t = timer_hr_new(); struct lp_msg *to_free = heap_extract(queue, msg_is_before); stats_take(STATS_MSG_EXTRACTION, timer_hr_value(t)); msg_allocator_free(to_free); @@ -124,8 +124,8 @@ static int serial_simulation_run(void) * @param payload payload of the event * @param payload_size size of the payload */ -void ScheduleNewEvent_serial(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *payload, - unsigned payload_size) +void ScheduleNewEvent_serial(const lp_id_t receiver, const simtime_t timestamp, const unsigned event_type, + const void *payload, const unsigned payload_size) { struct lp_msg *msg = msg_allocator_pack(receiver, timestamp, event_type, payload, payload_size); diff --git a/test/datatypes/bitmap.c b/test/datatypes/bitmap.c index 1ebcfeab..29a7dc4e 100644 --- a/test/datatypes/bitmap.c +++ b/test/datatypes/bitmap.c @@ -20,7 +20,7 @@ static int bitmap_test(_unused void *_) { - size_t b_size = bitmap_required_size(BITMAP_ENTRIES); + const size_t b_size = bitmap_required_size(BITMAP_ENTRIES); block_bitmap *b = malloc(b_size); bitmap_initialize(b, BITMAP_ENTRIES); @@ -29,8 +29,8 @@ static int bitmap_test(_unused void *_) unsigned i = THREAD_REPS; while(i--) { - unsigned e = test_random_range(BITMAP_ENTRIES); - bool v = (double)test_random_u() / RAND_MAX > 0.5; + const unsigned e = test_random_range(BITMAP_ENTRIES); + const bool v = (double)test_random_u() / RAND_MAX > 0.5; if(v) bitmap_set(b, e); else @@ -45,13 +45,19 @@ static int bitmap_test(_unused void *_) while(i--) c -= b_check[i]; - if(c) + if(c) { + free(b); + free(b_check); return -1; + } #define bitmap_check_test(i) \ __extension__({ \ - if(!b_check[i]) \ + if(!b_check[i]) { \ + free(b); \ + free(b_check); \ return -1; \ + } \ b_check[i] = false; \ }) diff --git a/test/gvt/termination.c b/test/gvt/termination.c index acae09fd..d3322bec 100644 --- a/test/gvt/termination.c +++ b/test/gvt/termination.c @@ -14,8 +14,8 @@ static _Atomic bool initialized = false; -static void DummyProcessEvent(_unused lp_id_t me, _unused simtime_t now, _unused unsigned event_type, - _unused const void *event_content, _unused unsigned event_size, _unused void *st) +static void DummyProcessEvent(_unused const lp_id_t me, _unused const simtime_t now, _unused const unsigned event_type, + _unused const void *event_content, _unused const unsigned event_size, _unused void *st) { if(event_type == LP_FINI) return; diff --git a/test/integration/correctness/application.c b/test/integration/correctness/application.c index 80a0ad83..9a8308da 100644 --- a/test/integration/correctness/application.c +++ b/test/integration/correctness/application.c @@ -15,7 +15,7 @@ #define do_random() (rng_random(&state->rng_state)) -void ProcessEvent(lp_id_t me, simtime_t now, unsigned event_type, const void *event_content, unsigned event_size, void *st) +void ProcessEvent(const lp_id_t me, const simtime_t now, const unsigned event_type, const void *event_content, const unsigned event_size, void * const st) { lp_state *state = st; if(state && state->events >= COMPLETE_EVENTS) { @@ -46,9 +46,9 @@ void ProcessEvent(lp_id_t me, simtime_t now, unsigned event_type, const void *ev rng_init(&state->rng_state, ((test_rng_state)me + 1) * 4390023366657240769ULL); SetState(state); - unsigned buffers_to_allocate = do_random() * MAX_BUFFERS; + const unsigned buffers_to_allocate = do_random() * MAX_BUFFERS; for(unsigned i = 0; i < buffers_to_allocate; ++i) { - unsigned c = do_random() * MAX_BUFFER_SIZE / sizeof(uint64_t); + const unsigned c = do_random() * MAX_BUFFER_SIZE / sizeof(uint64_t); state->head = allocate_buffer(state, NULL, c); state->buffer_count++; } @@ -70,7 +70,7 @@ void ProcessEvent(lp_id_t me, simtime_t now, unsigned event_type, const void *ev read_buffer(state->head, do_random() * state->buffer_count, state->total_checksum); if(state->buffer_count < MAX_BUFFERS && do_random() < ALLOC_PROBABILITY) { - unsigned c = do_random() * MAX_BUFFER_SIZE / sizeof(uint64_t); + const unsigned c = do_random() * MAX_BUFFER_SIZE / sizeof(uint64_t); state->head = allocate_buffer(state, NULL, c); state->buffer_count++; } @@ -81,8 +81,8 @@ void ProcessEvent(lp_id_t me, simtime_t now, unsigned event_type, const void *ev } if(state->buffer_count && do_random() < SEND_PROBABILITY) { - unsigned i = do_random() * state->buffer_count; - buffer *to_send = get_buffer(state->head, i); + const unsigned i = do_random() * state->buffer_count; + const buffer *to_send = get_buffer(state->head, i); dest = do_random() * N_LPS; ScheduleNewEvent(dest, now + do_random() * 10, RECEIVE, to_send->data, diff --git a/test/integration/correctness/functions.c b/test/integration/correctness/functions.c index b93d3ef9..9e97c065 100644 --- a/test/integration/correctness/functions.c +++ b/test/integration/correctness/functions.c @@ -20,13 +20,13 @@ buffer *get_buffer(buffer *head, unsigned i) return head; } -uint32_t read_buffer(buffer *head, unsigned i, uint32_t old_crc) +uint32_t read_buffer(buffer *head, const unsigned i, const uint32_t old_crc) { head = get_buffer(head, i); return crc_update(head->data, head->count, old_crc); } -buffer *allocate_buffer(lp_state *state, const unsigned *data, unsigned count) +buffer *allocate_buffer(lp_state *state, const unsigned *data, const unsigned count) { buffer *new = rs_malloc(sizeof(buffer) + count * sizeof(uint64_t)); new->next = state->head; @@ -41,7 +41,7 @@ buffer *allocate_buffer(lp_state *state, const unsigned *data, unsigned count) return new; } -buffer *deallocate_buffer(buffer *head, unsigned i) +buffer *deallocate_buffer(buffer *head, const unsigned i) { buffer *prev = NULL; buffer *to_free = head; @@ -81,7 +81,7 @@ void crc_table_init(void) } } -uint32_t crc_update(const uint64_t *buf, size_t n, uint32_t crc) +uint32_t crc_update(const uint64_t *buf, size_t n, const uint32_t crc) { uint32_t c = crc ^ 0xffffffffUL; while(n--) { diff --git a/test/integration/phold.c b/test/integration/phold.c index a5bbfaad..1b73d990 100644 --- a/test/integration/phold.c +++ b/test/integration/phold.c @@ -42,7 +42,7 @@ static double Random(struct phold_state *state) { const __uint128_t multiplier = (((__uint128_t)0x0fc94e3bf4e9ab32ULL) << 64) + 0x866458cd56f5e605ULL; state->seed *= multiplier; - uint64_t ret = state->seed >> 64u; + const uint64_t ret = state->seed >> 64u; return (double)ret / (double)UINT64_MAX; } @@ -51,17 +51,17 @@ static double Expent(struct phold_state *state) return mean * (-log(1. - Random(state))); } -static void set_seed(__uint128_t seed, struct phold_state *state) +static void set_seed(const __uint128_t seed, struct phold_state *state) { state->seed = ((seed) << 1u) | 1u; } -void ProcessEvent(lp_id_t me, simtime_t now, unsigned event_type, _unused const void *content, _unused unsigned size, - void *s) +void ProcessEvent(const lp_id_t me, const simtime_t now, const unsigned event_type, _unused const void *content, + _unused const unsigned size, void *s) { - struct phold_message new_event = {0}; + const struct phold_message new_event = {0}; lp_id_t dest; - struct phold_state *state = (struct phold_state *)s; + struct phold_state *state = s; switch(event_type) { case LP_INIT: diff --git a/test/log/stats.c b/test/log/stats.c index 3963db4e..93bc64cf 100644 --- a/test/log/stats.c +++ b/test/log/stats.c @@ -12,8 +12,8 @@ #define N_THREADS 2 -void DummyProcessEvent(lp_id_t me, simtime_t now, unsigned event_type, const void *event_content, unsigned event_size, - void *st) +void DummyProcessEvent(const lp_id_t me, const simtime_t now, const unsigned event_type, const void *event_content, + const unsigned event_size, void *st) { (void)me; (void)now; @@ -23,7 +23,7 @@ void DummyProcessEvent(lp_id_t me, simtime_t now, unsigned event_type, const voi (void)st; } -bool DummyCanEnd(lp_id_t lid, const void *state) +bool DummyCanEnd(const lp_id_t lid, const void *state) { (void)lid; (void)state; @@ -85,7 +85,7 @@ int stats_measures_test(_unused void *arg) return 0; } -static void stats_subsystem_test(const char *name, test_fn thread_fn) +static void stats_subsystem_test(const char *name, const test_fn thread_fn) { conf.stats_file = name; RootsimInit(&conf); diff --git a/test/mm/buddy.c b/test/mm/buddy.c index 05f5993f..cb3ed27a 100644 --- a/test/mm/buddy.c +++ b/test/mm/buddy.c @@ -18,7 +18,7 @@ #define BUDDY_TEST_SEED 0x5E550UL -static void write_allocations(uint64_t **allocations, unsigned allocations_cnt, unsigned block_size, +static void write_allocations(uint64_t **allocations, const unsigned allocations_cnt, const unsigned block_size, test_rng_state *b_rng_p) { for(unsigned i = 0; i < allocations_cnt; ++i) @@ -39,11 +39,11 @@ static int check_and_free_allocations(uint64_t **allocations, unsigned allocatio return errs; } -static int block_size_test(struct mm_state *mm, unsigned b_exp) +static int block_size_test(struct mm_state *mm, const unsigned b_exp) { int errs = 0; - unsigned block_size = 1 << b_exp; - unsigned allocations_cnt = 1 << (B_TOTAL_EXP - b_exp); + const unsigned block_size = 1 << b_exp; + const unsigned allocations_cnt = 1 << (B_TOTAL_EXP - b_exp); test_rng_state b_rng, b_chk; rng_init(&b_rng, BUDDY_TEST_SEED); uint64_t **allocations = malloc(allocations_cnt * sizeof(uint64_t *)); diff --git a/test/mm/buddy_hard.c b/test/mm/buddy_hard.c index a6f7c48c..2bda351d 100644 --- a/test/mm/buddy_hard.c +++ b/test/mm/buddy_hard.c @@ -49,7 +49,7 @@ static void allocation_init(struct alc *alc) // __write_mem(alc->ptr, alc->c * sizeof(unsigned)); while(c--) { - unsigned v = test_random_u(); + const unsigned v = test_random_u(); alc->ptr[c] = v; alc->data[c] = v; } @@ -77,7 +77,7 @@ static void allocation_all_fini(struct alc *alc) free(alc); } -static void allocation_partial_write(struct alc *alc, unsigned p) +static void allocation_partial_write(struct alc *alc, const unsigned p) { alc += p * MAX_ALLOC_CNT; @@ -85,20 +85,20 @@ static void allocation_partial_write(struct alc *alc, unsigned p) unsigned w = test_random_range(MAX_ALLOC_CNT / 2); while(w--) { - unsigned i = test_random_range(MAX_ALLOC_CNT); + const unsigned i = test_random_range(MAX_ALLOC_CNT); if(alc[i].ptr == NULL) { continue; } - unsigned c = alc[i].c; - unsigned e = test_random_range(c + 1); - unsigned l = test_random_range(e + 1); + const unsigned c = alc[i].c; + const unsigned e = test_random_range(c + 1); + const unsigned l = test_random_range(e + 1); // __write_mem(alc[i].ptr + l, (e - l) * sizeof(unsigned)); for(unsigned j = l; j < e; ++j) { - unsigned v = test_random_u(); + const unsigned v = test_random_u(); alc[i].ptr[j] = v; alc[i].data[j] = v; } @@ -106,7 +106,7 @@ static void allocation_partial_write(struct alc *alc, unsigned p) w = test_random_range(MAX_ALLOC_CNT / 6); while(w--) { - unsigned i = test_random_range(MAX_ALLOC_CNT); + const unsigned i = test_random_range(MAX_ALLOC_CNT); if(alc[i].ptr == NULL) { allocation_init(&alc[i]); } else { @@ -117,7 +117,7 @@ static void allocation_partial_write(struct alc *alc, unsigned p) } } -static bool allocation_check(struct alc *alc, unsigned p) +static bool allocation_check(const struct alc *alc, const unsigned p) { alc += p * MAX_ALLOC_CNT; @@ -136,7 +136,7 @@ static bool allocation_check(struct alc *alc, unsigned p) return false; } -static bool allocation_cycle(struct mm_state *mm, struct alc *alc, unsigned c, unsigned up, unsigned down) +static bool allocation_cycle(struct mm_state *mm, struct alc *alc, unsigned c, unsigned up, const unsigned down) { for(unsigned i = c + 1; i <= up; ++i) { allocation_partial_write(alc, i); @@ -158,7 +158,7 @@ static bool allocation_cycle(struct mm_state *mm, struct alc *alc, unsigned c, u return true; } - unsigned s = test_random_range(MAX_ALLOC_STEP) + 1; + const unsigned s = test_random_range(MAX_ALLOC_STEP) + 1; if(up <= down + s) { break; @@ -187,8 +187,8 @@ int model_allocator_test_hard(_unused void *_) unsigned c = 0; for(unsigned j = 0; j < ALLOC_OSCILLATIONS; ++j) { - unsigned u = test_random_range(MAX_ALLOC_PHASES - 1) + 1; - unsigned d = test_random_range(u); + const unsigned u = test_random_range(MAX_ALLOC_PHASES - 1) + 1; + const unsigned d = test_random_range(u); if(allocation_cycle(&lp->mm_state, alc, c, u, d)) { return -1; diff --git a/test/mm/parallel.c b/test/mm/parallel.c index 561eefed..5862ea2d 100644 --- a/test/mm/parallel.c +++ b/test/mm/parallel.c @@ -35,7 +35,7 @@ struct bin_info { size_t size, bins; }; -static void mem_init(unsigned char *ptr, size_t size) +static void mem_init(unsigned char *ptr, const size_t size) { if(!size) return; @@ -51,7 +51,7 @@ static void mem_init(unsigned char *ptr, size_t size) ptr[size - 1] = j ^ (j >> 8); } -static int mem_check(const unsigned char *ptr, size_t size) +static int mem_check(const unsigned char *ptr, const size_t size) { if(!size) return 0; @@ -77,7 +77,7 @@ static int zero_check(void *p, size_t size) size -= sizeof(*ptr); } - unsigned char *ptr2 = (unsigned char *)ptr; + const unsigned char *ptr2 = (unsigned char *)ptr; while(size > 0) { if(*ptr2++) return -1; @@ -90,7 +90,7 @@ static int zero_check(void *p, size_t size) * Allocate a bin with malloc(), realloc() or memalign(). * r must be a random number >= 1024. */ -static void bin_alloc(struct bin *m, size_t size, unsigned r) +static void bin_alloc(struct bin *m, const size_t size, unsigned r) { test_assert(mem_check(m->ptr, m->size) == 0); @@ -129,7 +129,7 @@ static void bin_free(struct bin *m) m->size = 0; } -static void bin_test(struct bin_info *p) +static void bin_test(const struct bin_info *p) { for(size_t b = 0; b < p->bins; b++) test_assert(mem_check(p->m[b].ptr, p->m[b].size) == 0); @@ -159,15 +159,15 @@ int parallel_malloc_test(_unused void *_) unsigned actions = test_random_range(ACTIONS_MAX); for(unsigned j = 0; j < actions; j++) { - unsigned bin = test_random_range(p.bins); + const unsigned bin = test_random_range(p.bins); bin_free(&p.m[bin]); } i += actions; actions = test_random_range(ACTIONS_MAX); for(unsigned j = 0; j < actions; j++) { - unsigned bin = test_random_range(p.bins); - uint64_t action = test_random_u(); + const unsigned bin = test_random_range(p.bins); + const uint64_t action = test_random_u(); bin_alloc(&p.m[bin], test_random_range(p.size) + 1, action); bin_test(&p); } From 5a748b86644a3c8b022c3880113ab0d66b7682d6 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 00:57:12 +0200 Subject: [PATCH 03/15] Consistent use of __typeof__ Align __typeof to __typeof__ Signed-off-by: Alessandro Pellegrini --- src/datatypes/heap.h | 46 ++++++++++++++++++++++---------------------- src/datatypes/list.h | 14 +++++++------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/datatypes/heap.h b/src/datatypes/heap.h index 3de4edb3..51d35f6e 100644 --- a/src/datatypes/heap.h +++ b/src/datatypes/heap.h @@ -60,7 +60,7 @@ * @param self the heap * @return the highest priority element, cast to const */ -#define heap_min(self) (*(__typeof(*array_items(self)) *const)array_items(self)) +#define heap_min(self) (*(__typeof__ (*array_items(self)) *const)array_items(self)) /** * @brief Insert an element into the heap @@ -74,8 +74,8 @@ #define heap_insert(self, cmp_f, elem) \ __extension__({ \ array_reserve(self, 1); \ - __typeof(array_count(self)) i = array_count(self)++; \ - __typeof__(array_items(self)) items = array_items(self); \ + __typeof__ (array_count(self)) i = array_count(self)++; \ + __typeof__ (array_items(self)) items = array_items(self); \ while(i && cmp_f(elem, items[(i - 1U) / 2U])) { \ items[i] = items[(i - 1U) / 2U]; \ i = (i - 1U) / 2U; \ @@ -97,10 +97,10 @@ #define heap_insert_n(self, cmp_f, ins, n) \ __extension__({ \ array_reserve(self, n); \ - __typeof(array_count(self)) j = n; \ - __typeof__(array_items(self)) items = array_items(self); \ + __typeof__ (array_count(self)) j = n; \ + __typeof__ (array_items(self)) items = array_items(self); \ while(j--) { \ - __typeof(array_count(self)) i = array_count(self)++; \ + __typeof__ (array_count(self)) i = array_count(self)++; \ while(i && cmp_f((ins)[j], items[(i - 1U) / 2U])) { \ items[i] = items[(i - 1U) / 2U]; \ i = (i - 1U) / 2U; \ @@ -118,21 +118,21 @@ * For correct operation of the heap you need to always pass the same @a cmp_f both for insertion and extraction */ #define heap_extract(self, cmp_f) \ - __extension__({ \ - __typeof__(array_items(self)) items = array_items(self); \ - __typeof(*array_items(self)) ret = array_items(self)[0]; \ - __typeof(*array_items(self)) last = array_pop(self); \ - __typeof(array_count(self)) cnt = array_count(self); \ - __typeof(array_count(self)) i = 1U; \ - __typeof(array_count(self)) j = 0U; \ - while(i < cnt) { \ - i += i + 1 < cnt && cmp_f(items[i + 1U], items[i]); \ - if(!cmp_f(items[i], last)) \ - break; \ - items[j] = items[i]; \ - j = i; \ - i = i * 2U + 1U; \ - } \ - items[j] = last; \ - ret; \ + __extension__({ \ + __typeof__ (array_items(self)) items = array_items(self); \ + __typeof__ (*array_items(self)) ret = array_items(self)[0]; \ + __typeof__ (*array_items(self)) last = array_pop(self); \ + __typeof__ (array_count(self)) cnt = array_count(self); \ + __typeof__ (array_count(self)) i = 1U; \ + __typeof__ (array_count(self)) j = 0U; \ + while(i < cnt) { \ + i += i + 1 < cnt && cmp_f(items[i + 1U], items[i]); \ + if(!cmp_f(items[i], last)) \ + break; \ + items[j] = items[i]; \ + j = i; \ + i = i * 2U + 1U; \ + } \ + items[j] = last; \ + ret; \ }) diff --git a/src/datatypes/list.h b/src/datatypes/list.h index c15dbc8b..704a36b8 100644 --- a/src/datatypes/list.h +++ b/src/datatypes/list.h @@ -52,14 +52,14 @@ struct list { * * @param li a pointer to a list created using the new_list() macro. */ -#define list_head(li) ((__typeof__ (li))(((struct list *)(li))->head)) +#define list_head(li) ((__typeof__(li))(((struct list *)(li))->head)) /** * This macro retrieves a pointer to the tail node of a list. * * @param li a pointer to a list created using the new_list() macro. */ -#define list_tail(li) ((__typeof__ (li))(((struct list *)(li))->tail)) +#define list_tail(li) ((__typeof__(li))(((struct list *)(li))->tail)) /** * Given a pointer to a list node, this macro retrieves a pointer to the next node, if any. @@ -126,7 +126,7 @@ struct list { }else{\ __new_n->prev = NULL; /* Otherwise add at the beginning */\ __new_n->next = __l->head;\ - ((__typeof(data))__l->head)->prev = __new_n;\ + ((__typeof__(data))__l->head)->prev = __new_n;\ __l->head = __new_n;\ }\ __l->size++;\ @@ -161,13 +161,13 @@ struct list { /* Insert depending on the position */\ if(__n == __l->tail) { /* tail */\ __new_n->next = NULL;\ - ((__typeof(data))__l->tail)->next = __new_n;\ + ((__typeof__(data))__l->tail)->next = __new_n;\ __new_n->prev = __l->tail;\ __l->tail = __new_n;\ } else if(__n == NULL) { /* head */\ __new_n->prev = NULL;\ __new_n->next = __l->head;\ - ((__typeof(data))__l->head)->prev = __new_n;\ + ((__typeof__(data))__l->head)->prev = __new_n;\ __l->head = __new_n;\ } else { /* middle */\ __new_n->prev = __n;\ @@ -190,13 +190,13 @@ struct list { if(__l->head == __n) { \ __l->head = __n->next; \ if(__l->head != NULL) { \ - ((__typeof(node))__l->head)->prev = NULL; \ + ((__typeof__(node))__l->head)->prev = NULL; \ }\ }\ if(__l->tail == __n) {\ __l->tail = __n->prev;\ if(__l->tail != NULL) {\ - ((__typeof(node))__l->tail)->next = NULL;\ + ((__typeof__(node))__l->tail)->next = NULL;\ }\ }\ if(__n->next != NULL) {\ From 80772fe9c2b2d15a288901735fc2a23f7acee0db Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 01:18:23 +0200 Subject: [PATCH 04/15] More meaningful variable names Improve readability by using more readable variable names. Signed-off-by: Alessandro Pellegrini --- src/mm/buddy/buddy.c | 78 +++++++++++++++--------------- src/mm/buddy/buddy.h | 2 +- src/mm/buddy/multi.c | 102 +++++++++++++++++++-------------------- src/mm/buddy/multi.h | 5 +- src/mm/model_allocator.h | 4 +- 5 files changed, 95 insertions(+), 96 deletions(-) diff --git a/src/mm/buddy/buddy.c b/src/mm/buddy/buddy.c index 4392b2a7..4dd446f7 100644 --- a/src/mm/buddy/buddy.c +++ b/src/mm/buddy/buddy.c @@ -10,14 +10,14 @@ #include -#define is_power_of_2(i) (!((i) & ((i)-1))) +#define is_power_of_2(index) (!((index) & ((index)-1))) void buddy_init(struct buddy_state *self) { uint_fast8_t node_size = B_TOTAL_EXP; - for(uint_fast32_t i = 0; i < sizeof(self->longest) / sizeof(*self->longest); ++i) { - self->longest[i] = node_size; - node_size -= is_power_of_2(i + 2); + for(uint_fast32_t index = 0; index < sizeof(self->longest) / sizeof(*self->longest); ++index) { + self->longest[index] = node_size; + node_size -= is_power_of_2(index + 2); } } @@ -28,28 +28,28 @@ void *buddy_malloc(struct buddy_state *self, const uint_fast8_t req_blks_exp) /* search recursively for the child */ uint_fast8_t node_size = B_TOTAL_EXP; - uint_fast32_t i = 0; + uint_fast32_t index = 0; while(node_size > req_blks_exp) { /* choose the child with smaller longest value which * is still large at least *size* */ - i = buddy_left_child(i); - i += self->longest[i] < req_blks_exp; + index = buddy_left_child(index); + index += self->longest[index] < req_blks_exp; --node_size; } /* update the *longest* value back */ - self->longest[i] = 0; + self->longest[index] = 0; #ifdef ROOTSIM_INCREMENTAL - bitmap_set(self->dirty, i >> B_BLOCK_EXP); + bitmap_set(self->dirty, index >> B_BLOCK_EXP); #endif - const uint_fast32_t offset = ((i + 1) << node_size) - (1 << B_TOTAL_EXP); + const uint_fast32_t offset = ((index + 1) << node_size) - (1 << B_TOTAL_EXP); - while(i) { - i = buddy_parent(i); - self->longest[i] = max(self->longest[buddy_left_child(i)], self->longest[buddy_right_child(i)]); + while(index) { + index = buddy_parent(index); + self->longest[index] = max(self->longest[buddy_left_child(index)], self->longest[buddy_right_child(index)]); #ifdef ROOTSIM_INCREMENTAL - bitmap_set(self->dirty, i >> B_BLOCK_EXP); + bitmap_set(self->dirty, index >> B_BLOCK_EXP); #endif } @@ -59,35 +59,35 @@ void *buddy_malloc(struct buddy_state *self, const uint_fast8_t req_blks_exp) uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) { uint_fast8_t node_size = B_BLOCK_EXP; - uint_fast32_t o = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; - uint_fast32_t i = o + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; + uint_fast32_t offset = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; + uint_fast32_t index = offset + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; - for(; self->longest[i]; i = buddy_parent(i)) + for(; self->longest[index]; index = buddy_parent(index)) ++node_size; - self->longest[i] = node_size; + self->longest[index] = node_size; const uint_fast32_t ret = (uint_fast32_t)1U << node_size; #ifdef ROOTSIM_INCREMENTAL - bitmap_set(self->dirty, i >> B_BLOCK_EXP); + bitmap_set(self->dirty, index >> B_BLOCK_EXP); - uint_fast32_t b = (1 << (node_size - B_BLOCK_EXP)) - 1; - o += (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); + uint_fast32_t bitmap_idx = (1 << (node_size - B_BLOCK_EXP)) - 1; + offset += (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); // need to track freed blocks content because full checkpoints don't do { - bitmap_set(self->dirty, o + b); - } while(b--); + bitmap_set(self->dirty, offset + bitmap_idx); + } while(bitmap_idx--); #endif - while(i) { - i = buddy_parent(i); + while(index) { + index = buddy_parent(index); - uint_fast8_t left_long = self->longest[buddy_left_child(i)]; - uint_fast8_t right_long = self->longest[buddy_right_child(i)]; + uint_fast8_t left_long = self->longest[buddy_left_child(index)]; + uint_fast8_t right_long = self->longest[buddy_right_child(index)]; if(left_long == node_size && right_long == node_size) { - self->longest[i] = node_size + 1; + self->longest[index] = node_size + 1; } else { - self->longest[i] = max(left_long, right_long); + self->longest[index] = max(left_long, right_long); } #ifdef ROOTSIM_INCREMENTAL bitmap_set(self->dirty, i >> B_BLOCK_EXP); @@ -100,10 +100,10 @@ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *self, void *ptr, size_t req_size) { uint_fast8_t node_size = B_BLOCK_EXP; - const uint_fast32_t o = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; - uint_fast32_t i = o + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; + const uint_fast32_t offset = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; + uint_fast32_t index = offset + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; - for(; self->longest[i]; i = buddy_parent(i)) + for(; self->longest[index]; index = buddy_parent(index)) ++node_size; const uint_fast8_t req_blks_exp = buddy_allocation_block_compute(req_size); @@ -125,16 +125,16 @@ struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *sel return ret; } -void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t s) +void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t size) { const uintptr_t diff = ptr - (void *)self->base_mem; - const uint_fast32_t i = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); + const uint_fast32_t index = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); - s += diff & ((1 << B_BLOCK_EXP) - 1); - --s; - s >>= B_BLOCK_EXP; + size += diff & ((1 << B_BLOCK_EXP) - 1); + --size; + size >>= B_BLOCK_EXP; do { - bitmap_set(self->dirty, i + s); - } while(s--); + bitmap_set(self->dirty, index + size); + } while(size--); } diff --git a/src/mm/buddy/buddy.h b/src/mm/buddy/buddy.h index 38bb2ad4..4f6be646 100644 --- a/src/mm/buddy/buddy.h +++ b/src/mm/buddy/buddy.h @@ -62,4 +62,4 @@ struct buddy_realloc_res { }; }; extern struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *self, void *ptr, size_t req_size); -extern void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t s); +extern void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t size); diff --git a/src/mm/buddy/multi.c b/src/mm/buddy/multi.c index c64ba95a..047fed04 100644 --- a/src/mm/buddy/multi.c +++ b/src/mm/buddy/multi.c @@ -31,15 +31,15 @@ void model_allocator_lp_init(struct mm_state *self) void model_allocator_lp_fini(const struct mm_state *self) { - array_count_t i = array_count(self->logs); - while(i--) - mm_free(array_get_at(self->logs, i).c); + array_count_t index = array_count(self->logs); + while(index--) + mm_free(array_get_at(self->logs, index).ckpt); array_fini(self->logs); - i = array_count(self->buddies); - while(i--) - mm_free(array_get_at(self->buddies, i)); + index = array_count(self->buddies); + while(index--) + mm_free(array_get_at(self->buddies, index)); array_fini(self->buddies); } @@ -59,9 +59,9 @@ void *rs_malloc(size_t req_size) struct mm_state *self = ¤t_lp->mm_state; self->full_ckpt_size += 1 << req_blks_exp; - array_count_t i = array_count(self->buddies); - while(i--) { - void *ret = buddy_malloc(array_get_at(self->buddies, i), req_blks_exp); + array_count_t index = array_count(self->buddies); + while(index--) { + void *ret = buddy_malloc(array_get_at(self->buddies, index), req_blks_exp); if(likely(ret != NULL)) return ret; } @@ -69,11 +69,11 @@ void *rs_malloc(size_t req_size) struct buddy_state *new_buddy = mm_alloc(sizeof(*new_buddy)); buddy_init(new_buddy); - for(i = 0; i < array_count(self->buddies); ++i) - if(array_get_at(self->buddies, i) > new_buddy) + for(index = 0; index < array_count(self->buddies); ++index) + if(array_get_at(self->buddies, index) > new_buddy) break; - array_add_at(self->buddies, i, new_buddy); + array_add_at(self->buddies, index, new_buddy); self->full_ckpt_size += offsetof(struct buddy_checkpoint, base_mem); return buddy_malloc(new_buddy, req_blks_exp); } @@ -91,16 +91,16 @@ void *rs_calloc(const size_t nmemb, const size_t size) static inline struct buddy_state *buddy_find_by_address(const struct mm_state *self, const void *ptr) { - array_count_t l = 0, h = array_count(self->buddies) - 1; + array_count_t low = 0, high = array_count(self->buddies) - 1; while(1) { - const array_count_t m = (l + h) / 2; - struct buddy_state *b = array_get_at(self->buddies, m); - if(ptr < (void *)b) - h = m - 1; - else if(ptr > (void *)(b + 1)) - l = m + 1; + const array_count_t middle = (low + high) / 2; + struct buddy_state *buddy = array_get_at(self->buddies, middle); + if(ptr < (void *)buddy) + high = middle - 1; + else if(ptr > (void *)(buddy + 1)) + low = middle + 1; else - return b; + return buddy; } } @@ -110,8 +110,8 @@ void rs_free(void *ptr) return; struct mm_state *self = ¤t_lp->mm_state; - struct buddy_state *b = buddy_find_by_address(self, ptr); - self->full_ckpt_size -= buddy_free(b, ptr); + struct buddy_state *buddy = buddy_find_by_address(self, ptr); + self->full_ckpt_size -= buddy_free(buddy, ptr); } void *rs_realloc(void *ptr, size_t req_size) @@ -125,8 +125,8 @@ void *rs_realloc(void *ptr, size_t req_size) return rs_malloc(req_size); struct mm_state *self = ¤t_lp->mm_state; - struct buddy_state *b = buddy_find_by_address(self, ptr); - struct buddy_realloc_res ret = buddy_best_effort_realloc(b, ptr, req_size); + struct buddy_state *buddy = buddy_find_by_address(self, ptr); + struct buddy_realloc_res ret = buddy_best_effort_realloc(buddy, ptr, req_size); if(ret.handled) { self->full_ckpt_size += ret.variation; return ptr; @@ -142,30 +142,30 @@ void *rs_realloc(void *ptr, size_t req_size) return new_buffer; } -void __write_mem(const void *ptr, const size_t s) +void __write_mem(const void *ptr, const size_t size) { struct mm_state *self = ¤t_lp->mm_state; - if(unlikely(!s || array_is_empty(self->buddies))) + if(unlikely(!size || array_is_empty(self->buddies))) return; if(unlikely(ptr < (void *)array_get_at(self->buddies, 0) || ptr > (void *)(array_peek(self->buddies) + 1))) return; - struct buddy_state *b = buddy_find_by_address(self, ptr); + struct buddy_state *buddy = buddy_find_by_address(self, ptr); - buddy_dirty_mark(b, ptr, s); + buddy_dirty_mark(buddy, ptr, size); } // todo: incremental -void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_i) +void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_idx) { - struct mm_checkpoint *ckp = mm_alloc(self->full_ckpt_size); - ckp->ckpt_size = self->full_ckpt_size; + struct mm_checkpoint *ckpt = mm_alloc(self->full_ckpt_size); + ckpt->ckpt_size = self->full_ckpt_size; - const struct mm_log mm_log = {.ref_i = ref_i, .c = ckp}; + const struct mm_log mm_log = {.ref_idx = ref_idx, .ckpt = ckpt}; array_push(self->logs, mm_log); - struct buddy_checkpoint *buddy_ckp = (struct buddy_checkpoint *)ckp->chkps; + struct buddy_checkpoint *buddy_ckp = (struct buddy_checkpoint *)ckpt->chkps; array_count_t i = array_count(self->buddies); while(i--) buddy_ckp = checkpoint_full_take(array_get_at(self->buddies, i), buddy_ckp); @@ -178,57 +178,57 @@ void model_allocator_checkpoint_next_force_full(const struct mm_state *self) // TODO: force full checkpointing when incremental state saving is enabled } -array_count_t model_allocator_checkpoint_restore(struct mm_state *self, const array_count_t ref_i) +array_count_t model_allocator_checkpoint_restore(struct mm_state *self, const array_count_t ref_idx) { - array_count_t i = array_count(self->logs) - 1; - while(array_get_at(self->logs, i).ref_i > ref_i) - i--; + array_count_t index = array_count(self->logs) - 1; + while(array_get_at(self->logs, index).ref_idx > ref_idx) + index--; - const struct mm_checkpoint *ckp = array_get_at(self->logs, i).c; + const struct mm_checkpoint *ckp = array_get_at(self->logs, index).ckpt; self->full_ckpt_size = ckp->ckpt_size; - const struct buddy_checkpoint *buddy_ckp = (struct buddy_checkpoint *)ckp->chkps; + const struct buddy_checkpoint *buddy_ckpt = (struct buddy_checkpoint *)ckp->chkps; array_count_t k = array_count(self->buddies); while(k--) { struct buddy_state *b = array_get_at(self->buddies, k); - const struct buddy_checkpoint *c = checkpoint_full_restore(array_get_at(self->buddies, k), buddy_ckp); - if(unlikely(c == NULL)) { + const struct buddy_checkpoint *ckpt = checkpoint_full_restore(array_get_at(self->buddies, k), buddy_ckpt); + if(unlikely(ckpt == NULL)) { buddy_init(b); self->full_ckpt_size += offsetof(struct buddy_checkpoint, base_mem); } else { - buddy_ckp = c; + buddy_ckpt = ckpt; } } - for(array_count_t j = array_count(self->logs) - 1; j > i; --j) - mm_free(array_get_at(self->logs, j).c); + for(array_count_t j = array_count(self->logs) - 1; j > index; --j) + mm_free(array_get_at(self->logs, j).ckpt); - array_count(self->logs) = i + 1; - return array_get_at(self->logs, i).ref_i; + array_count(self->logs) = index + 1; + return array_get_at(self->logs, index).ref_idx; } array_count_t model_allocator_fossil_lp_collect(struct mm_state *self, const array_count_t tgt_ref_i) { array_count_t log_i = array_count(self->logs) - 1; - array_count_t ref_i = array_get_at(self->logs, log_i).ref_i; + array_count_t ref_i = array_get_at(self->logs, log_i).ref_idx; while(ref_i > tgt_ref_i) { --log_i; - ref_i = array_get_at(self->logs, log_i).ref_i; + ref_i = array_get_at(self->logs, log_i).ref_idx; } while(is_log_incremental(array_get_at(self->logs, log_i))) { --log_i; - ref_i = array_get_at(self->logs, log_i).ref_i; + ref_i = array_get_at(self->logs, log_i).ref_idx; } array_count_t j = array_count(self->logs); while(j > log_i) { --j; - array_get_at(self->logs, j).ref_i -= ref_i; + array_get_at(self->logs, j).ref_idx -= ref_i; } while(j--) - mm_free(array_get_at(self->logs, j).c); + mm_free(array_get_at(self->logs, j).ckpt); array_truncate_first(self->logs, log_i); return ref_i; diff --git a/src/mm/buddy/multi.h b/src/mm/buddy/multi.h index b4f9d554..ecc81239 100644 --- a/src/mm/buddy/multi.h +++ b/src/mm/buddy/multi.h @@ -26,9 +26,9 @@ struct mm_checkpoint { /// Binds a checkpoint together with a reference index struct mm_log { /// The reference index, used to identify this checkpoint - array_count_t ref_i; + array_count_t ref_idx; /// A pointer to the actual checkpoint - struct mm_checkpoint *c; + struct mm_checkpoint *ckpt; }; /// The checkpointable memory context assigned to a single LP @@ -40,4 +40,3 @@ struct mm_state { /// The total count of allocated bytes uint_fast32_t full_ckpt_size; }; - diff --git a/src/mm/model_allocator.h b/src/mm/model_allocator.h index 9fb9a5f1..d61c5915 100644 --- a/src/mm/model_allocator.h +++ b/src/mm/model_allocator.h @@ -15,7 +15,7 @@ extern void model_allocator_lp_init(struct mm_state *self); extern void model_allocator_lp_fini(const struct mm_state *self); -extern void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_i); +extern void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_idx); extern void model_allocator_checkpoint_next_force_full(const struct mm_state *self); -extern array_count_t model_allocator_checkpoint_restore(struct mm_state *self, array_count_t ref_i); +extern array_count_t model_allocator_checkpoint_restore(struct mm_state *self, array_count_t ref_idx); extern array_count_t model_allocator_fossil_lp_collect(struct mm_state *self, array_count_t tgt_ref_i); From 89b9c54ab52d48134c3be91e32311f59e87ca11e Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 12:10:37 +0200 Subject: [PATCH 05/15] Improve documentation Documenting several functions/datatypes with missing documentation, and fixing some documentation errors. Signed-off-by: Alessandro Pellegrini --- src/ROOT-Sim.h | 79 +++++++++++++++-- src/datatypes/list.h | 172 +++++++++++++++++++++++++++++++------- src/datatypes/msg_queue.c | 3 - src/datatypes/msg_queue.h | 3 + src/gvt/gvt.c | 46 ++++++++++ src/gvt/termination.c | 4 +- src/gvt/termination.h | 1 - src/lp/common.h | 9 ++ src/lp/lp.h | 3 + src/lp/msg.h | 8 ++ src/lp/process.c | 28 ++++++- src/lp/process.h | 29 +++++++ src/mm/auto_ckpt.c | 10 ++- src/mm/buddy/buddy.c | 65 +++++++++++++- src/mm/buddy/buddy.h | 10 +++ src/mm/buddy/ckpt.c | 34 ++++++++ src/mm/buddy/ckpt.h | 3 + src/mm/buddy/multi.c | 1 + 18 files changed, 461 insertions(+), 47 deletions(-) diff --git a/src/ROOT-Sim.h b/src/ROOT-Sim.h index 681282f6..1aee88db 100644 --- a/src/ROOT-Sim.h +++ b/src/ROOT-Sim.h @@ -66,6 +66,11 @@ typedef void (*ProcessEvent_t)(lp_id_t me, simtime_t now, unsigned event_type, c */ typedef bool (*CanEnd_t)(lp_id_t me, const void *snapshot); +/// @brief Internal event types used by the simulation kernel. +/// +/// These event types are automatically scheduled to the model according to the following logic: +/// - `LP_INIT`: Represents the initialization event for a logical process. +/// - `LP_FINI`: Represents the finalization event for a logical process. enum rootsim_event { LP_INIT = 65534, LP_FINI }; /** @@ -86,22 +91,82 @@ extern void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp, unsigned eve extern void SetState(void *new_state); +/** + * @brief Allocates rollbackable memory + * + * This function is part of the custom memory management system and is used to allocate + * memory dynamically. The allocated memory is not initialized. Upon a rollback, the previous + * content of the allocated memory buffer is restored to the previous (consistent) content. + * + * @param req_size The size of the memory block to allocate, in bytes. + * @return A pointer to the allocated memory block, or `NULL` if the allocation fails. + * + * @note If `req_size` is 0, the function returns `NULL`. + * @warning The returned memory _must_ be freed using `rs_free()`. + */ extern void *rs_malloc(size_t req_size); +/** + * @brief Allocates and zero-initializes rollbackable memory + * + * This function is part of the custom memory management system and is used to allocate + * memory dynamically. The allocated memory is initialized to zero. Upon a rollback, the + * previous content of the allocated memory buffer is restored to the previous (consistent) content. + * + * @param nmemb The number of elements to allocate. + * @param size The size of each element, in bytes. + * @return A pointer to the allocated memory block, or `NULL` if the allocation fails. + * + * @note If `nmemb` or `size` is 0, the function returns `NULL`. + * @warning The returned memory _must_ be freed using `rs_free()`. + */ extern void *rs_calloc(size_t nmemb, size_t size); +/** + * @brief Frees rollbackable memory + * + * This function is part of the custom memory management system and is used to free + * memory that was previously allocated using `rs_malloc()`, `rs_calloc()`, or `rs_realloc()`. + * Upon a rollback, the memory is restored to its previous (consistent) state. This means that + * also the address of the free'd buffer will be the same. Linked data structures can be therefore + * safely implemented in the model, as internal pointers will be valid after a rollback. + * + * @param ptr A pointer to the memory block to be freed. If `ptr` is `NULL`, no operation is performed. + * + * @warning The memory block must have been allocated using the custom memory management functions. + */ extern void rs_free(void *ptr); +/** + * @brief Reallocates rollbackable memory + * + * This function is part of the custom memory management system and is used to resize + * a previously allocated memory block. If the reallocation is successful, the content + * of the memory block is preserved up to the minimum of the old and new sizes. + * Upon a rollback, the memory is restored to its previous (consistent) state. + * + * @param ptr A pointer to the memory block to be reallocated. If `ptr` is `NULL`, the function behaves like `rs_malloc()`. + * @param req_size The new size of the memory block, in bytes. + * @return A pointer to the reallocated memory block, or `NULL` if the reallocation fails. + * + * @note If `req_size` is 0, the function frees the memory block and returns `NULL`. + * @warning The memory block must have been allocated using the custom memory management functions. + */ extern void *rs_realloc(void *ptr, size_t req_size); +/** + * @brief Logging levels used by the simulation kernel. + * + * These levels define the verbosity of log messages emitted during the simulation. + */ enum log_level { - LOG_TRACE, //!< The logging level reserved to very low priority messages - LOG_DEBUG, //!< The logging level reserved to useful debug messages - LOG_INFO, //!< The logging level reserved to useful runtime messages - LOG_WARN, //!< The logging level reserved to unexpected, non deal breaking conditions - LOG_ERROR, //!< The logging level reserved to unexpected, problematic conditions - LOG_FATAL, //!< The logging level reserved to unexpected, fatal conditions - LOG_SILENT //!< Emit no message during the simulation + LOG_TRACE, //!< The logging level reserved for very low priority messages. + LOG_DEBUG, //!< The logging level reserved for useful debug messages. + LOG_INFO, //!< The logging level reserved for useful runtime messages. + LOG_WARN, //!< The logging level reserved for unexpected, non-deal-breaking conditions. + LOG_ERROR, //!< The logging level reserved for unexpected, problematic conditions. + LOG_FATAL, //!< The logging level reserved for unexpected, fatal conditions. + LOG_SILENT //!< Emit no messages during the simulation. }; /// A set of configurable values used by other modules diff --git a/src/datatypes/list.h b/src/datatypes/list.h index 704a36b8..4fd2f255 100644 --- a/src/datatypes/list.h +++ b/src/datatypes/list.h @@ -44,7 +44,15 @@ struct list { __lmptr;\ }) -// Get the size of the current list. +/** + * @brief Retrieves the size of the list. + * + * This macro evaluates to the size of the list, which is stored in the `size` member + * of the `struct list`. + * + * @param list A pointer to a list created using the `new_list()` macro. + * @return The size of the list as a `size_t`. + */ #define list_sizeof(list) ((struct list *)list)->size /** @@ -90,6 +98,16 @@ struct list { */ #define list_empty(list) (((struct list *)list)->size == 0) + +/** + * @brief Inserts a new node at the tail of the list. + * + * This macro appends a new node to the end of the list. If the list is empty, + * the new node becomes both the head and the tail. The list size is incremented accordingly. + * + * @param li A pointer to the list created using the `new_list()` macro. + * @param data A pointer to the node to be inserted. The node must have `next` and `prev` members. + */ #define list_insert_tail(li, data) \ do { \ __typeof__(data) __new_n = (data); /* in-block scope variable */\ @@ -112,6 +130,16 @@ struct list { __l->size++;\ } while(0) + +/** + * @brief Inserts a new node at the head of the list. + * + * This macro adds a new node to the beginning of the list. If the list is empty, + * the new node becomes both the head and the tail. The list size is incremented accordingly. + * + * @param li A pointer to the list created using the `new_list()` macro. + * @param data A pointer to the node to be inserted. The node must have `next` and `prev` members. + */ #define list_insert_head(li, data) \ do { \ __typeof__(data) __new_n = (data); /* in-block scope variable */\ @@ -132,7 +160,27 @@ struct list { __l->size++;\ } while(0) -/// Insert a new node in the list + +/** + * @brief Inserts a new node into the list in a sorted order based on a key. + * + * This macro inserts a new node into the list while maintaining the order of the list + * based on the key value. The key is extracted from the node using the specified key name. + * The list is traversed from the tail to find the appropriate position for the new node. + * + * @param li A pointer to the list created using the `new_list()` macro. + * @param key_name The name of the key field in the node structure. + * @param data A pointer to the node to be inserted. The node must have `next` and `prev` members. + * + * @note The list must be sorted in increasing order of the key values. + * @note The key field in the node must be of type `double`. + * + * @pre The list must be initialized using the `new_list()` macro. + * @pre The node to be inserted must not already be part of another list. + * + * @post The list size is incremented by 1. + * @post The new node is inserted at the correct position based on the key value. + */ #define list_insert(li, key_name, data)\ do {\ __typeof__(data) __n; /* in-block scope variable */\ @@ -180,6 +228,23 @@ struct list { assert(__l->size == (__size_before + 1));\ } while(0) + +/** + * @brief Detaches a node from the list by its content. + * + * This macro removes a specified node from the list, updating the list's head, tail, and size + * as necessary. The node's `next` and `prev` pointers are set to invalid values to indicate + * that it is no longer part of the list. + * + * @param li A pointer to the list created using the `new_list()` macro. + * @param node A pointer to the node to be detached. The node must have `next` and `prev` members. + * + * @pre The list must be initialized using the `new_list()` macro. + * @pre The node to be detached must be part of the list. + * + * @post The node is removed from the list, and the list size is decremented by 1. + * @post The `next` and `prev` pointers of the detached node are set to invalid values. + */ #define list_detach_by_content(li, node) \ do { \ __typeof__(node) __n = (node); /* in-block scope variable */ \ @@ -190,7 +255,7 @@ struct list { if(__l->head == __n) { \ __l->head = __n->next; \ if(__l->head != NULL) { \ - ((__typeof__(node))__l->head)->prev = NULL; \ + ((__typeof__(node))__l->head)->prev = NULL; \ }\ }\ if(__l->tail == __n) {\ @@ -210,6 +275,22 @@ struct list { __l->size--;\ } while(0) + +/** + * @brief Removes the head node from the list. + * + * This macro removes the first node (head) from the list, updating the list's head pointer, + * size, and the `next` and `prev` pointers of the removed node. The removed node's pointers + * are set to invalid values to indicate that it is no longer part of the list. + * + * @param list A pointer to the list created using the `new_list()` macro. + * + * @pre The list must be initialized using the `new_list()` macro. + * @pre The list must not be NULL. + * + * @post The head node is removed from the list, and the list size is decremented by 1. + * @post The `next` and `prev` pointers of the removed node are set to invalid values. + */ #define list_pop(list)\ do {\ struct list *__l;\ @@ -234,34 +315,65 @@ struct list { }\ } while(0) -/// Truncate a list up to a certain point, starting from the head. + +/** + * @brief Truncates a list up to a certain point, starting from the head. + * + * This macro removes nodes from the head of the list up to the first node + * whose key is greater than or equal to the specified key value. The removed + * nodes are released using the provided release function. + * + * @param list A pointer to the list created using the `new_list()` macro. + * @param key_name The name of the key field in the node structure. + * @param key_value The key value up to which nodes should be removed. + * @param release_fn A function to release the memory or resources of the removed nodes. + * + * @return The number of nodes removed from the list. + * + * @pre The list must be initialized using the `new_list()` macro. + * @pre The nodes in the list must have a key field of type `double`. + * @pre The release function must be callable for each removed node. + * + * @post The list size is decremented by the number of removed nodes. + * @post The `next` and `prev` pointers of the removed nodes are set to invalid values. + */ #define list_trunc(list, key_name, key_value, release_fn) \ - ({\ - struct list *__l = (struct list *)(list);\ - __typeof__(list) __n;\ - __typeof__(list) __n_adjacent;\ - unsigned int __deleted = 0;\ - size_t __key_position = my_offsetof((list), key_name);\ - assert(__l);\ - size_t __size_before = __l->size;\ - /* Attempting to truncate an empty list? */\ - if(__l->size > 0) {\ - __n = __l->head;\ - while(__n != NULL && get_key(__n) < (key_value)) {\ - __deleted++;\ - __n_adjacent = __n->next;\ - __n->next = (void *)0xBAADF00D;\ - __n->prev = (void *)0xBAADF00D;\ - release_fn(__n);\ - __n = __n_adjacent;\ + ({\ + struct list *__l = (struct list *)(list);\ + __typeof__(list) __n;\ + __typeof__(list) __n_adjacent;\ + unsigned int __deleted = 0;\ + size_t __key_position = my_offsetof((list), key_name);\ + assert(__l);\ + size_t __size_before = __l->size;\ + /* Attempting to truncate an empty list? */\ + if(__l->size > 0) {\ + __n = __l->head;\ + while(__n != NULL && get_key(__n) < (key_value)) {\ + __deleted++;\ + __n_adjacent = __n->next;\ + __n->next = (void *)0xBAADF00D;\ + __n->prev = (void *)0xBAADF00D;\ + release_fn(__n);\ + __n = __n_adjacent;\ + }\ + __l->head = __n;\ + if(__l->head != NULL)\ + ((__typeof__(list))__l->head)->prev = NULL;\ }\ - __l->head = __n;\ - if(__l->head != NULL)\ - ((__typeof__(list))__l->head)->prev = NULL;\ - }\ - __l->size -= __deleted;\ - assert(__l->size == (__size_before - __deleted));\ - __deleted;\ - }) + __l->size -= __deleted;\ + assert(__l->size == (__size_before - __deleted));\ + __deleted;\ + }) + +/** + * @brief Retrieves the size of the list. + * + * This macro evaluates to the size of the list, which is stored in the `size` member + * of the `struct list`. + * + * @param li A pointer to a list created using the `new_list()` macro. + * @return The size of the list as a `size_t`. + */ #define list_size(li) ((struct list *)(li))->size diff --git a/src/datatypes/msg_queue.c b/src/datatypes/msg_queue.c index 3f7ae227..b5bff490 100644 --- a/src/datatypes/msg_queue.c +++ b/src/datatypes/msg_queue.c @@ -44,9 +44,6 @@ static struct msg_buffer *queues; /// The private thread queue static _Thread_local heap_declare(struct q_elem) mqp; -/** - * @brief Initializes the message queue at the node level - */ void msg_queue_global_init(void) { queues = mm_aligned_alloc(CACHE_LINE_SIZE, global_config.n_threads * sizeof(*queues)); diff --git a/src/datatypes/msg_queue.h b/src/datatypes/msg_queue.h index 11e7678a..7e97e712 100644 --- a/src/datatypes/msg_queue.h +++ b/src/datatypes/msg_queue.h @@ -13,6 +13,9 @@ #include #include +/** + * @brief Initializes the message queue at the node level + */ extern void msg_queue_global_init(void); extern void msg_queue_global_fini(void); extern void msg_queue_init(void); diff --git a/src/gvt/gvt.c b/src/gvt/gvt.c index 886ce316..ece6a442 100644 --- a/src/gvt/gvt.c +++ b/src/gvt/gvt.c @@ -132,6 +132,14 @@ void gvt_on_msg_extraction(const simtime_t msg_t) gvt_accumulator = msg_t; } +/** + * @brief Reduces the node-local GVT values across all threads. + * + * This function iterates through the `reducing_p` array, which contains the + * GVT values accumulated by each thread, and determines the minimum value. + * + * @return The minimum GVT value among all threads as a `simtime_t`. + */ static inline simtime_t gvt_node_reduce(void) { unsigned i = global_config.n_threads - 1; @@ -142,6 +150,21 @@ static inline simtime_t gvt_node_reduce(void) return candidate; } +/** + * @brief Executes a single step of the thread-local GVT phase. + * + * This function manages the progression of the thread-local GVT algorithm through its phases. + * Each phase performs specific synchronization and reduction tasks, ensuring that the GVT + * computation progresses correctly across all threads. + * + * @return `true` if the thread-local GVT computation has completed, `false` otherwise. + * + * @details + * - Phase A: Waits for all threads to complete their local reduction and transitions to Phase B. + * - Phase B: Ensures all threads have completed Phase A and transitions to Phase C. + * - Phase C: Updates the thread-local GVT accumulator and transitions to Phase D. + * - Phase D: Waits for all threads to complete Phase C and finalizes the thread-local computation. + */ static bool gvt_thread_phase_run(void) { switch(thread_phase) { @@ -176,6 +199,29 @@ static bool gvt_thread_phase_run(void) return false; } +/** + * @brief Executes a single step of the node-local GVT phase. + * + * This function manages the progression of the node-local GVT algorithm through its phases. + * Each phase performs specific synchronization and reduction tasks, ensuring that the GVT + * computation progresses correctly across all threads and nodes. + * + * @return `true` if the node-local GVT computation has completed, `false` otherwise. + * + * @details + * - `node_phase_redux_first` and `node_phase_redux_second`: Perform thread-local GVT reductions + * and transition to the next phase. + * - `node_sent_reduce`: Aggregates the count of remote messages sent and transitions to the + * reduction phase. + * - `node_sent_reduce_wait`: Waits for the completion of the remote message count reduction. + * - `node_sent_wait`: Waits for all remote messages to be processed and transitions to the + * second reduction phase. + * - `node_min_reduce`: Initiates the reduction of the minimum GVT value across threads. + * - `node_min_reduce_wait`: Waits for the completion of the minimum GVT reduction. + * - `node_min_wait`: Ensures all threads have completed the reduction and transitions to the + * final phase. + * - `node_done`: Finalizes the node-local GVT computation and signals completion. + */ static bool gvt_node_phase_run(void) { static _Thread_local enum node_phase node_phase = node_phase_redux_first; diff --git a/src/gvt/termination.c b/src/gvt/termination.c index c8ab63f9..9eb473b8 100644 --- a/src/gvt/termination.c +++ b/src/gvt/termination.c @@ -42,6 +42,7 @@ void termination_lp_init(struct lp_ctx *lp) /** * @brief Compute termination operations after a new message has been processed + * @param lp the LP that has just processed a message * @param msg_time the timestamp of the freshly processed message */ void termination_on_msg_process(struct lp_ctx *lp, simtime_t msg_time) @@ -97,7 +98,8 @@ void RootsimStop(void) /** * @brief Compute termination operations after a LP has been rollbacked - * @param msg_time the timestamp of the straggler or anti message which caused the rollback + * @param lp the LP that has been rollbacked + * @param msg_time the timestamp of the straggler or anti message that caused the rollback */ void termination_on_lp_rollback(struct lp_ctx *lp, const simtime_t msg_time) { diff --git a/src/gvt/termination.h b/src/gvt/termination.h index 309987c6..cad02257 100644 --- a/src/gvt/termination.h +++ b/src/gvt/termination.h @@ -27,4 +27,3 @@ extern void termination_on_msg_process(struct lp_ctx *lp, simtime_t msg_time); extern void termination_on_gvt(simtime_t current_gvt); extern void termination_on_lp_rollback(struct lp_ctx *lp, simtime_t msg_time); extern void termination_on_ctrl_msg(void); -extern void termination_force(void); diff --git a/src/lp/common.h b/src/lp/common.h index ca22efda..57c2f685 100644 --- a/src/lp/common.h +++ b/src/lp/common.h @@ -14,6 +14,15 @@ #include #include +/** + * @brief Processes a message for a given LP (Logical Process). + * + * This function handles the processing of a message by invoking the dispatcher + * and recording relevant statistics about the processing time and count. + * + * @param lp A pointer to the LP associated with the message. + * @param msg A pointer to the message to be processed. + */ static inline void common_msg_process(const struct lp_ctx *lp, const struct lp_msg *msg) { timer_uint t = timer_hr_new(); diff --git a/src/lp/lp.h b/src/lp/lp.h index 7b4d4ac1..a41f4d01 100644 --- a/src/lp/lp.h +++ b/src/lp/lp.h @@ -57,7 +57,10 @@ extern _Thread_local struct lp_ctx *current_lp; extern struct lp_ctx *lps; #ifndef NDEBUG +/// Indicates whether LPs have been initialized. Prevents calling SetState() outside of LP_INIT extern bool lp_initialized; + +/// Macro to set the LP initialization flag to true #define lp_initialized_set() (lp_initialized = true) #else #define lp_initialized_set() diff --git a/src/lp/msg.h b/src/lp/msg.h index 8406037e..5cba8da3 100644 --- a/src/lp/msg.h +++ b/src/lp/msg.h @@ -87,6 +87,14 @@ struct lp_msg { unsigned char extra_pl[]; }; +/** + * @brief Bits to implement a finite-state machine to handle incoming events/antievents. + * + * For a comprehensive description of the usage of the finite state machine, refer to: + * A. Piccione and A. Pellegrini + * “Efficient Non-Blocking Event Management for Speculative Parallel Discrete Event Simulation” + * in Proceedings of the 2024 ACM SIGSIM Conference on Principles of Advanced Discrete Simulation, 2024. + */ enum msg_flag { MSG_FLAG_ANTI = 1, MSG_FLAG_PROCESSED = 2 }; /** diff --git a/src/lp/process.c b/src/lp/process.c index 28a50106..b1515012 100644 --- a/src/lp/process.c +++ b/src/lp/process.c @@ -30,11 +30,35 @@ static _Thread_local bool silent_processing = false; static _Thread_local struct lp_msg *current_msg; #endif +/** + * @brief Marks a message as remote. + * @param msg_p A pointer to the message to mark. + * @return A pointer to the marked message. + */ #define mark_msg_remote(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) | 2U)) + +/** + * @brief Marks a message as sent. + * @param msg_p A pointer to the message to mark. + * @return A pointer to the marked message. + */ #define mark_msg_sent(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) | 1U)) + +/** + * @brief Unmarks a message as remote. + * @param msg_p A pointer to the message to unmark. + * @return A pointer to the unmarked message. + */ #define unmark_msg_remote(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) - 2U)) + +/** + * @brief Unmarks a message as sent. + * @param msg_p A pointer to the message to unmark. + * @return A pointer to the unmarked message. + */ #define unmark_msg_sent(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) - 1U)) + void ScheduleNewEvent(const lp_id_t receiver, const simtime_t timestamp, const unsigned event_type, const void *payload, unsigned payload_size) { @@ -250,7 +274,7 @@ static inline array_count_t match_anti_msg(const struct process_ctx *proc_p, con /** * @brief Handle the reception of a remote anti-message - * @param proc_p the message processing data for the LP that has to handle the anti-message + * @param lp the message processing data for the LP that has to handle the anti-message * @param a_msg the remote anti-message */ static inline void handle_remote_anti_msg(struct lp_ctx *lp, struct lp_msg *a_msg) @@ -289,7 +313,7 @@ static inline void handle_remote_anti_msg(struct lp_ctx *lp, struct lp_msg *a_ms /** * @brief Check if a remote message has already been invalidated by an early remote anti-message * @param proc_p the message processing data of the current LP - * @param a_msg the remote message to check + * @param msg the remote message to check * @return true if the message has been matched with an early remote anti-message, false otherwise */ static inline bool check_early_anti_messages(struct process_ctx *proc_p, struct lp_msg *msg) diff --git a/src/lp/process.h b/src/lp/process.h index c6f36994..ee8d628e 100644 --- a/src/lp/process.h +++ b/src/lp/process.h @@ -25,10 +25,39 @@ struct process_ctx { simtime_t bound; }; +/** + * @brief Checks if a message has been sent. + * @param msg_p Pointer to the message. + * @return True if the message has been sent, false otherwise. + */ #define is_msg_sent(msg_p) (((uintptr_t)(msg_p)) & 3U) + +/** + * @brief Checks if a message is remote. + * @param msg_p Pointer to the message. + * @return True if the message is remote, false otherwise. + */ #define is_msg_remote(msg_p) (((uintptr_t)(msg_p)) & 2U) + +/** + * @brief Checks if a message is locally sent. + * @param msg_p Pointer to the message. + * @return True if the message is locally sent, false otherwise. + */ #define is_msg_local_sent(msg_p) (((uintptr_t)(msg_p)) & 1U) + +/** + * @brief Checks if a message is in the past. + * @param msg_p Pointer to the message. + * @return True if the message is in the past, false otherwise. + */ #define is_msg_past(msg_p) (!(((uintptr_t)(msg_p)) & 3U)) + +/** + * @brief Removes any marking from a message pointer. + * @param msg_p Pointer to the message. + * @return The unmarked message pointer. + */ #define unmark_msg(msg_p) ((struct lp_msg *)(((uintptr_t)(msg_p)) & (UINTPTR_MAX - 3))) struct lp_ctx; // forward declaration diff --git a/src/mm/auto_ckpt.c b/src/mm/auto_ckpt.c index 14eb2db5..e42a4c8d 100644 --- a/src/mm/auto_ckpt.c +++ b/src/mm/auto_ckpt.c @@ -29,9 +29,15 @@ o *(((f)-1.0) / (f)) + s *(1.0 / (f)); \ }) +/** + * @brief Thread-local context for the auto checkpoint module + * + * This structure holds thread-local metrics used for computing + * the optimal checkpoint interval. + */ static _Thread_local struct { - double ckpt_avg_cost; - double inv_sil_avg_cost; + double ckpt_avg_cost; /**< Exponential moving average of checkpoint cost per byte */ + double inv_sil_avg_cost; /**< Inverse of the exponential moving average of silent message cost */ } ackpt; /** diff --git a/src/mm/buddy/buddy.c b/src/mm/buddy/buddy.c index 4dd446f7..a382d1b6 100644 --- a/src/mm/buddy/buddy.c +++ b/src/mm/buddy/buddy.c @@ -10,8 +10,18 @@ #include +/// Tells if the given index is a power of 2 #define is_power_of_2(index) (!((index) & ((index)-1))) +/** + * @brief Initializes the buddy system allocator. + * + * This function sets up the buddy system allocator by initializing the `longest` array + * in the `buddy_state` structure. Each entry in the array represents the size of the largest + * free block in the corresponding subtree of the buddy system. + * + * @param self Pointer to the `buddy_state` structure to initialize. + */ void buddy_init(struct buddy_state *self) { uint_fast8_t node_size = B_TOTAL_EXP; @@ -21,6 +31,18 @@ void buddy_init(struct buddy_state *self) } } + +/** + * @brief Allocates memory using the buddy system allocator. + * + * This function allocates a memory block of the requested size (expressed as a power of 2) + * from the buddy system. It searches for the smallest suitable block, marks it as used, + * and updates the internal state of the allocator. + * + * @param self Pointer to the `buddy_state` structure representing the buddy system allocator. + * @param req_blks_exp The size of the requested memory block, expressed as a power of 2. + * @return A pointer to the allocated memory block, or `NULL` if no suitable block is available. + */ void *buddy_malloc(struct buddy_state *self, const uint_fast8_t req_blks_exp) { if(unlikely(self->longest[0] < req_blks_exp)) @@ -56,6 +78,18 @@ void *buddy_malloc(struct buddy_state *self, const uint_fast8_t req_blks_exp) return ((char *)self->base_mem) + offset; } + +/** + * @brief Frees a memory block allocated by the buddy system allocator. + * + * This function releases a previously allocated memory block back to the buddy system. + * It updates the internal state of the allocator to reflect the newly freed block + * and merges adjacent free blocks if possible. + * + * @param self Pointer to the `buddy_state` structure representing the buddy system allocator. + * @param ptr Pointer to the memory block to be freed. + * @return The size of the freed memory block in bytes. + */ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) { uint_fast8_t node_size = B_BLOCK_EXP; @@ -72,7 +106,7 @@ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) uint_fast32_t bitmap_idx = (1 << (node_size - B_BLOCK_EXP)) - 1; offset += (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); - // need to track freed blocks content because full checkpoints don't + // Track freed blocks content because full checkpoints don't do { bitmap_set(self->dirty, offset + bitmap_idx); } while(bitmap_idx--); @@ -97,6 +131,24 @@ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) return ret; } + +/** + * @brief Attempts to reallocate memory with the buddy system allocator. + * + * This function tries to resize a memory block allocated by the buddy system + * to the requested size. If the requested size matches the current size, the + * operation is handled without any changes. Otherwise, it determines whether + * the reallocation can be performed and provides information about the + * original size of the block. + * + * @param self Pointer to the `buddy_state` structure representing the buddy system allocator. + * @param ptr Pointer to the memory block to be reallocated. + * @param req_size The requested size for the memory block in bytes. + * @return A `buddy_realloc_res` structure containing the result of the reallocation attempt: + * - `handled`: Indicates whether the reallocation was handled. + * - `variation`: The size difference if the reallocation was handled. + * - `original`: The original size of the memory block if the reallocation was not handled. + */ struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *self, void *ptr, size_t req_size) { uint_fast8_t node_size = B_BLOCK_EXP; @@ -125,6 +177,17 @@ struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *sel return ret; } +/** + * @brief Marks a memory region as dirty for incremental checkpointing. + * + * This function marks a specified memory region as dirty in the buddy system allocator. + * The dirty marking is used to track changes to memory blocks for incremental checkpointing. + * Note: Incremental checkpointing is currently not functioning. + * + * @param self Pointer to the `buddy_state` structure representing the buddy system allocator. + * @param ptr Pointer to the start of the memory region to be marked as dirty. + * @param size The size of the memory region to be marked as dirty, in bytes. + */ void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t size) { const uintptr_t diff = ptr - (void *)self->base_mem; diff --git a/src/mm/buddy/buddy.h b/src/mm/buddy/buddy.h index 4f6be646..fcad345a 100644 --- a/src/mm/buddy/buddy.h +++ b/src/mm/buddy/buddy.h @@ -54,10 +54,20 @@ extern void buddy_init(struct buddy_state *self); extern void *buddy_malloc(struct buddy_state *self, uint_fast8_t req_blks_exp); extern uint_fast32_t buddy_free(struct buddy_state *self, void *ptr); +/** + * @brief Represents the result of a best-effort reallocation in the buddy system. + * + * This structure is used to indicate whether a reallocation request was handled + * and to provide additional information about the result of the operation. + */ struct buddy_realloc_res { + /// Indicates whether the reallocation request was successfully handled. bool handled; + /// Union containing details about the reallocation result. union { + /// The variation in memory size if the reallocation was handled. int_fast32_t variation; + /// The original memory size if the reallocation was not handled. uint_fast32_t original; }; }; diff --git a/src/mm/buddy/ckpt.c b/src/mm/buddy/ckpt.c index 0c8a20c4..fa29a214 100644 --- a/src/mm/buddy/ckpt.c +++ b/src/mm/buddy/ckpt.c @@ -11,6 +11,18 @@ #include +/** + * @brief Traverses the buddy tree and performs an action on each unallocated block. + * + * This macro iterates over the buddy tree represented by the `longest` array and + * invokes the provided `on_visit` action for each unallocated memory block. + * + * @param longest The array representing the buddy tree. + * @param on_visit A callback action to perform on each unallocated block. The callback + * receives two parameters: + * - `offset`: The offset of the block in the memory buffer. + * - `length`: The size of the block. + */ #define buddy_tree_visit(longest, on_visit) \ __extension__({ \ bool __vis = false; \ @@ -128,6 +140,16 @@ void checkpoint_incremental_restore(struct buddy_state *self, const struct buddy #endif +/** + * @brief Takes a full checkpoint. + * + * This function creates a full checkpoint of the given buddy system state by copying + * the current state of the allocation tree and memory buffer into the provided checkpoint structure. + * + * @param self A pointer to the `buddy_state` structure representing the current buddy system state. + * @param ret A pointer to the `buddy_checkpoint` structure where the checkpoint will be stored. + * @return A pointer to the next available memory location after the checkpoint data. + */ struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *ret) { ret->orig = self; @@ -149,6 +171,18 @@ struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, st return (struct buddy_checkpoint *)ptr; } +/** + * @brief Restores the full state. + * + * This function restores the state of the buddy system, including the allocation tree + * and memory buffer, from the provided checkpoint. It ensures that the checkpoint + * corresponds to the given buddy system before performing the restoration. + * + * @param self A pointer to the `buddy_state` structure representing the current buddy system. + * @param ckp A pointer to the `buddy_checkpoint` structure containing the checkpoint data. + * @return A pointer to the next available memory location after the checkpoint data, + * or `NULL` if the checkpoint does not match the buddy system. + */ const struct buddy_checkpoint *checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *ckp) { if(unlikely(ckp->orig != self)) diff --git a/src/mm/buddy/ckpt.h b/src/mm/buddy/ckpt.h index c266eacc..d7b147c2 100644 --- a/src/mm/buddy/ckpt.h +++ b/src/mm/buddy/ckpt.h @@ -37,5 +37,8 @@ static_assert( extern struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *data); extern const struct buddy_checkpoint *checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *data); + +#ifdef ROOTSIM_INCREMENTAL extern struct buddy_checkpoint *checkpoint_incremental_take(const struct buddy_state *self, struct buddy_checkpoint *data); extern const struct buddy_checkpoint * checkpoint_incremental_restore(struct buddy_state *self, const struct buddy_checkpoint *ckp); +#endif diff --git a/src/mm/buddy/multi.c b/src/mm/buddy/multi.c index 047fed04..962e6d08 100644 --- a/src/mm/buddy/multi.c +++ b/src/mm/buddy/multi.c @@ -17,6 +17,7 @@ #include #ifdef ROOTSIM_INCREMENTAL +/// Tells whether a checkpoint is incremental or not. #define is_log_incremental(l) ((uintptr_t)(l).c & 0x1) #else #define is_log_incremental(l) false From a01af0d37b6dfb3794bb27df0a648d33219cdbce Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 12:49:11 +0200 Subject: [PATCH 06/15] Update email address in CoC There was an old email address in the code of conduct. Signed-off-by: Alessandro Pellegrini --- docs/CODE_OF_CONDUCT.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md index c0ba42ba..817aae81 100644 --- a/docs/CODE_OF_CONDUCT.md +++ b/docs/CODE_OF_CONDUCT.md @@ -44,9 +44,9 @@ event. Representation of a project may be further defined and clarified by proje ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at -pellegrini@diag.uniroma1.it. The project team will review and investigate all complaints, and will respond in a way that -it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the -reporter of an incident. Further details of specific enforcement policies may be posted separately. +a.pellegrini@ing.uniroma2.it. The project team will review and investigate all complaints, and will respond in a way +that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard +to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. From b603ab1b0dea308a658a5f3952e7e37a02ff9a51 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 16:43:06 +0200 Subject: [PATCH 07/15] Improve documentation Documenting several functions/datatypes with missing documentation, and fixing some documentation errors. Signed-off-by: Alessandro Pellegrini --- src/mm/buddy/multi.c | 101 ++++++++++++++++++++++++++++++++++++++++- src/mm/msg_allocator.c | 4 +- src/mm/msg_allocator.h | 14 ++++++ 3 files changed, 117 insertions(+), 2 deletions(-) diff --git a/src/mm/buddy/multi.c b/src/mm/buddy/multi.c index 117b18ad..3ad7ab4d 100644 --- a/src/mm/buddy/multi.c +++ b/src/mm/buddy/multi.c @@ -20,9 +20,21 @@ /// Tells whether a checkpoint is incremental or not. #define is_log_incremental(l) ((uintptr_t)(l).c & 0x1) #else +/// Tells whether a checkpoint is incremental or not. #define is_log_incremental(l) false #endif +/** + * @brief Initializes the memory management state for a logical process. + * + * This function sets up the memory management state for a logical process by + * initializing the arrays used to manage buddy systems and logs. It also + * calculates the initial size of a full checkpoint based on the structure + * layout. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + */ void model_allocator_lp_init(struct mm_state *self) { array_init(self->buddies); @@ -30,6 +42,17 @@ void model_allocator_lp_init(struct mm_state *self) self->full_ckpt_size = offsetof(struct mm_checkpoint, chkps) + sizeof(struct buddy_state *); } + +/** + * @brief Finalizes the memory management state for a logical process. + * + * This function releases all resources associated with the memory management + * state of a logical process. It frees all memory allocated for logs and buddy + * systems and ensures proper cleanup of the associated arrays. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + */ void model_allocator_lp_fini(const struct mm_state *self) { array_count_t index = array_count(self->logs); @@ -45,6 +68,7 @@ void model_allocator_lp_fini(const struct mm_state *self) array_fini(self->buddies); } + void *rs_malloc(size_t req_size) { if(unlikely(!req_size)) @@ -90,6 +114,18 @@ void *rs_calloc(const size_t nmemb, const size_t size) return ret; } +/** + * @brief Finds the buddy system managing a given memory address. + * + * This function performs a binary search to locate the `buddy_state` structure + * that manages the memory block containing the specified address. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + * @param ptr A pointer to the memory address to locate within the buddy system. + * @return A pointer to the `buddy_state` structure managing the memory block + * containing the specified address. + */ static inline struct buddy_state *buddy_find_by_address(const struct mm_state *self, const void *ptr) { array_count_t low = 0, high = array_count(self->buddies) - 1; @@ -105,6 +141,7 @@ static inline struct buddy_state *buddy_find_by_address(const struct mm_state *s } } + void rs_free(void *ptr) { if(unlikely(!ptr)) @@ -115,6 +152,7 @@ void rs_free(void *ptr) self->full_ckpt_size -= buddy_free(buddy, ptr); } + void *rs_realloc(void *ptr, size_t req_size) { if(!req_size) { // Adhering to C11 standard §7.20.3.1 @@ -143,6 +181,20 @@ void *rs_realloc(void *ptr, size_t req_size) return new_buffer; } + +/** + * @brief Marks a memory region as dirty for incremental checkpointing. + * + * This function is intended to be an entry point for the model's code, injected at compile time, + * to mark a memory region as dirty whenever a write operation is performed. It updates the + * corresponding buddy system to track the modified memory region. + * + * @note This function is currently unused because the incremental checkpointing subsystem + * is disabled. + * + * @param ptr A pointer to the start of the memory region being written to. + * @param size The size of the memory region being written to, in bytes. + */ void __write_mem(const void *ptr, const size_t size) { struct mm_state *self = ¤t_lp->mm_state; @@ -157,7 +209,16 @@ void __write_mem(const void *ptr, const size_t size) buddy_dirty_mark(buddy, ptr, size); } -// todo: incremental +/** + * @brief Takes a full checkpoint of the memory management state. + * + * This function creates a full checkpoint of the memory management state for a logical process. + * It allocates memory for the checkpoint, records its size, and stores it in the logs. Each buddy + * system's state is saved into the checkpoint structure. + * + * @param self A pointer to the `mm_state` structure representing the memory management state. + * @param ref_idx The reference index associated with the checkpoint. + */ void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_idx) { struct mm_checkpoint *ckpt = mm_alloc(self->full_ckpt_size); @@ -173,12 +234,37 @@ void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_id buddy_ckp->orig = NULL; } +/** + * @brief Forces the next checkpoint to be a full checkpoint. + * + * This function is a placeholder for enabling full checkpointing when + * incremental state saving is active. Currently, it does nothing as + * incremental checkpointing is disabled. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + */ void model_allocator_checkpoint_next_force_full(const struct mm_state *self) { (void)self; // TODO: force full checkpointing when incremental state saving is enabled } + +/** + * @brief Restores the memory management state to a specific checkpoint. + * + * This function restores the memory management state of a logical process to the state + * recorded in the checkpoint corresponding to the given reference index. It ensures + * that all buddy systems are restored to their respective states as recorded in the + * checkpoint. If a checkpoint is missing for a buddy system, it reinitializes the buddy + * system to a default state. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + * @param ref_idx The reference index of the checkpoint to restore. + * @return The reference index of the restored checkpoint. + */ array_count_t model_allocator_checkpoint_restore(struct mm_state *self, const array_count_t ref_idx) { array_count_t index = array_count(self->logs) - 1; @@ -208,6 +294,19 @@ array_count_t model_allocator_checkpoint_restore(struct mm_state *self, const ar return array_get_at(self->logs, index).ref_idx; } + +/** + * @brief Collects fossil logs up to a target reference index. + * + * This function removes logs from the memory management state that are no longer + * needed, based on the specified target reference index. It ensures that only + * the logs required for restoring the state up to the target index are retained. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + * @param tgt_ref_i The target reference index up to which logs should be collected. + * @return The reference index of the last retained log. + */ array_count_t model_allocator_fossil_lp_collect(struct mm_state *self, const array_count_t tgt_ref_i) { array_count_t log_i = array_count(self->logs) - 1; diff --git a/src/mm/msg_allocator.c b/src/mm/msg_allocator.c index ed825fc6..209f6ea5 100644 --- a/src/mm/msg_allocator.c +++ b/src/mm/msg_allocator.c @@ -14,7 +14,9 @@ #include #include +/// Cache of message structs used to avoid frequent allocations/deallocations static _Thread_local dyn_array(struct lp_msg *) free_list = {0}; +/// Cache of message structs free'd upon GVT reduction static _Thread_local dyn_array(struct lp_msg *) at_gvt_list = {0}; /** @@ -105,7 +107,7 @@ void msg_allocator_on_gvt(const simtime_t current_gvt) * @param event_type a field which can be used by the model to distinguish them * @param payload the payload to copy into the message * @param payload_size the size in bytes of the payload to copy into the message - * @return a new populated message + * @return A new populated message */ extern struct lp_msg *msg_allocator_pack(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *payload, unsigned payload_size); diff --git a/src/mm/msg_allocator.h b/src/mm/msg_allocator.h index e097858f..add91269 100644 --- a/src/mm/msg_allocator.h +++ b/src/mm/msg_allocator.h @@ -22,6 +22,20 @@ extern void msg_allocator_free(struct lp_msg *msg); extern void msg_allocator_free_at_gvt(struct lp_msg *msg); extern void msg_allocator_on_gvt(simtime_t current_gvt); +/** + * @brief Allocates and populates a new message. + * + * This function allocates a new message with the specified payload size and populates + * its fields with the provided parameters. If a payload is provided, it is copied + * into the message's payload buffer. + * + * @param receiver The ID of the LP that will receive this message. + * @param timestamp The logical time at which this message must be processed. + * @param event_type A field used by the model to distinguish event types. + * @param payload A pointer to the payload data to copy into the message. + * @param payload_size The size in bytes of the payload to copy into the message. + * @return A pointer to the newly allocated and populated message. + */ static inline struct lp_msg *msg_allocator_pack(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *payload, unsigned payload_size) { From 06915e2898065317431f261eb028e90d567c5b54 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 17:47:11 +0200 Subject: [PATCH 08/15] Reorganize the mm subsystem This commit moves around functions and data structures, based on the following core ideas: - Buddy system stuff are confined in mm/buddy/ files - model_allocator.c should implement everything that can be seen by the model or pertains to the LP state memory. It interacts with the buddy system, so the concept of "multi.c" is not necessary, nor pertains to mm/buddy/. Out of mm/ no one should explicitly see the buddy system. - in mm/checkpoint we have everything that relates to checkpointing of the LP state. So we now have an `autonomic.c` unit, a `full.c` unit, and an `incremental.c` unit, that is currently only keeping old code. `mm/checkpoint/checkpoint.h` is the only header exposing all checkpointing-related stuff, so independently of what you need (autonomic/full/incremental), you can include this header. I am convinced this refactor helps people go and find stuff based on the organization of the tree. There could be a minimal penaly, as we have lost one `static inline` for a function, but I am happy tolerating a minimal performance penalty in favor of readability. Signed-off-by: Alessandro Pellegrini --- src/CMakeLists.txt | 8 +- src/core/core.h | 3 - src/core/sync.c | 2 +- src/datatypes/msg_queue.c | 1 + src/lp/lp.h | 2 +- src/lp/process.c | 2 +- src/mm/buddy/buddy.c | 2 +- src/mm/buddy/{ckpt.c => checkpoint.c} | 10 +- src/mm/buddy/{ckpt.h => checkpoint.h} | 8 +- src/mm/buddy/multi.h | 42 ---- .../{auto_ckpt.c => checkpoint/autonomic.c} | 4 +- .../{auto_ckpt.h => checkpoint/checkpoint.h} | 35 +++- src/mm/checkpoint/full.c | 82 ++++++++ src/mm/checkpoint/incremental.c | 58 ++++++ src/mm/{buddy/multi.c => model_allocator.c} | 190 ++++-------------- src/mm/model_allocator.h | 15 +- 16 files changed, 239 insertions(+), 225 deletions(-) rename src/mm/buddy/{ckpt.c => checkpoint.c} (96%) rename src/mm/buddy/{ckpt.h => checkpoint.h} (81%) delete mode 100644 src/mm/buddy/multi.h rename src/mm/{auto_ckpt.c => checkpoint/autonomic.c} (98%) rename src/mm/{auto_ckpt.h => checkpoint/checkpoint.h} (68%) create mode 100644 src/mm/checkpoint/full.c create mode 100644 src/mm/checkpoint/incremental.c rename src/mm/{buddy/multi.c => model_allocator.c} (54%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b6208636..fb396ced 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,10 +17,12 @@ set(rscore_srcs log/stats.c lp/lp.c lp/process.c - mm/auto_ckpt.c + mm/checkpoint/autonomic.c + mm/checkpoint/full.c + mm/checkpoint/incremental.c mm/buddy/buddy.c - mm/buddy/ckpt.c - mm/buddy/multi.c + mm/buddy/checkpoint.c + mm/model_allocator.c mm/msg_allocator.c parallel/parallel.c serial/serial.c) diff --git a/src/core/core.h b/src/core/core.h index ea384a2a..8e74cd1b 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -11,9 +11,6 @@ #pragma once #include -#include -#include -#include #include diff --git a/src/core/sync.c b/src/core/sync.c index c1010401..876383ce 100644 --- a/src/core/sync.c +++ b/src/core/sync.c @@ -40,4 +40,4 @@ bool sync_thread_barrier(void) phase = (phase + 1) & 3U; return l; -} \ No newline at end of file +} diff --git a/src/datatypes/msg_queue.c b/src/datatypes/msg_queue.c index 732dace7..0fcdd127 100644 --- a/src/datatypes/msg_queue.c +++ b/src/datatypes/msg_queue.c @@ -19,6 +19,7 @@ #include #include +#include #include #include diff --git a/src/lp/lp.h b/src/lp/lp.h index 03cdcdc8..8c156c5c 100644 --- a/src/lp/lp.h +++ b/src/lp/lp.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include /// A complete LP context diff --git a/src/lp/process.c b/src/lp/process.c index 43ff8e4b..a9d050e8 100644 --- a/src/lp/process.c +++ b/src/lp/process.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/mm/buddy/buddy.c b/src/mm/buddy/buddy.c index 45503012..f30263b9 100644 --- a/src/mm/buddy/buddy.c +++ b/src/mm/buddy/buddy.c @@ -190,7 +190,7 @@ struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *sel */ void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t size) { - const uintptr_t diff = ptr - (void *)self->base_mem; + const uintptr_t diff = (unsigned char *)ptr - (unsigned char *)self->base_mem; const uint_fast32_t index = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); size += diff & ((1 << B_BLOCK_EXP) - 1); diff --git a/src/mm/buddy/ckpt.c b/src/mm/buddy/checkpoint.c similarity index 96% rename from src/mm/buddy/ckpt.c rename to src/mm/buddy/checkpoint.c index c59c6282..05826072 100644 --- a/src/mm/buddy/ckpt.c +++ b/src/mm/buddy/checkpoint.c @@ -1,12 +1,12 @@ /** - * @file mm/buddy/ckpt.c + * @file mm/buddy/checkpoint.c * - * @brief Checkpointing capabilities + * @brief Buddy system checkpointing capabilities * * SPDX-FileCopyrightText: 2008-2025 HPCS Group * SPDX-License-Identifier: GPL-3.0-only */ -#include +#include #include @@ -150,7 +150,7 @@ void checkpoint_incremental_restore(struct buddy_state *self, const struct buddy * @param ret A pointer to the `buddy_checkpoint` structure where the checkpoint will be stored. * @return A pointer to the next available memory location after the checkpoint data. */ -struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *ret) +struct buddy_checkpoint *buddy_checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *ret) { ret->orig = self; #ifdef ROOTSIM_INCREMENTAL @@ -183,7 +183,7 @@ struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, st * @return A pointer to the next available memory location after the checkpoint data, * or `NULL` if the checkpoint does not match the buddy system. */ -const struct buddy_checkpoint *checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *ckp) +const struct buddy_checkpoint *buddy_checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *ckp) { if(unlikely(ckp->orig != self)) return NULL; diff --git a/src/mm/buddy/ckpt.h b/src/mm/buddy/checkpoint.h similarity index 81% rename from src/mm/buddy/ckpt.h rename to src/mm/buddy/checkpoint.h index b9d982d8..26d0d6fe 100644 --- a/src/mm/buddy/ckpt.h +++ b/src/mm/buddy/checkpoint.h @@ -1,7 +1,7 @@ /** - * @file mm/buddy/ckpt.h + * @file mm/buddy/checkpoint.h * - * @brief Checkpointing capabilities + * @brief Buddy system checkpointing capabilities * * SPDX-FileCopyrightText: 2008-2025 HPCS Group * SPDX-License-Identifier: GPL-3.0-only @@ -35,8 +35,8 @@ static_assert( sizeof(((struct buddy_checkpoint *)0)->longest), "longest and base_mem are not contiguous, this will break incremental checkpointing"); -extern struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *data); -extern const struct buddy_checkpoint *checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *data); +extern struct buddy_checkpoint *buddy_checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *data); +extern const struct buddy_checkpoint *buddy_checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *data); #ifdef ROOTSIM_INCREMENTAL extern struct buddy_checkpoint *checkpoint_incremental_take(const struct buddy_state *self, struct buddy_checkpoint *data); diff --git a/src/mm/buddy/multi.h b/src/mm/buddy/multi.h deleted file mode 100644 index 4bbe4325..00000000 --- a/src/mm/buddy/multi.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file mm/buddy/multi.h - * - * @brief Handling of multiple buddy systems - * - * SPDX-FileCopyrightText: 2008-2025 HPCS Group - * SPDX-License-Identifier: GPL-3.0-only - */ -#pragma once - -#include - -#include -#include -#include -#include - -/// The checkpoint for the multiple buddy system allocator -struct mm_checkpoint { - /// The total count of allocated bytes at the moment of the checkpoint - uint_fast32_t ckpt_size; - /// The sequence of checkpoints of the allocated buddy systems (see @a buddy_checkpoint) - unsigned char chkps[]; -}; - -/// Binds a checkpoint together with a reference index -struct mm_log { - /// The reference index, used to identify this checkpoint - array_count_t ref_idx; - /// A pointer to the actual checkpoint - struct mm_checkpoint *ckpt; -}; - -/// The checkpointable memory context assigned to a single LP -struct mm_state { - /// The array of pointers to the allocated buddy systems for the LP - dyn_array(struct buddy_state *) buddies; - /// The array of checkpoints - dyn_array(struct mm_log) logs; - /// The total count of allocated bytes - uint_fast32_t full_ckpt_size; -}; diff --git a/src/mm/auto_ckpt.c b/src/mm/checkpoint/autonomic.c similarity index 98% rename from src/mm/auto_ckpt.c rename to src/mm/checkpoint/autonomic.c index 86b9be41..99d4bcf8 100644 --- a/src/mm/auto_ckpt.c +++ b/src/mm/checkpoint/autonomic.c @@ -1,5 +1,5 @@ /** - * @file mm/auto_ckpt.c + * @file mm/checkpoint/autonomic.c * * @brief Autonomic checkpoint interval selection module * @@ -8,7 +8,7 @@ * SPDX-FileCopyrightText: 2008-2025 HPCS Group * SPDX-License-Identifier: GPL-3.0-only */ -#include +#include #include #include diff --git a/src/mm/auto_ckpt.h b/src/mm/checkpoint/checkpoint.h similarity index 68% rename from src/mm/auto_ckpt.h rename to src/mm/checkpoint/checkpoint.h index d1fd4cfd..71e06752 100644 --- a/src/mm/auto_ckpt.h +++ b/src/mm/checkpoint/checkpoint.h @@ -1,17 +1,41 @@ /** - * @file mm/auto_ckpt.h + * @file mm/checkpoint/checkpoint.h * - * @brief Autonomic checkpoint interval selection header - * - * The module which attempts to select the best checkpoint interval + * @brief Header of the model allocator checkpointing subsystem * * SPDX-FileCopyrightText: 2008-2025 HPCS Group * SPDX-License-Identifier: GPL-3.0-only */ #pragma once +#include #include +#ifdef ROOTSIM_INCREMENTAL +/// Tells whether a checkpoint is incremental or not. +#define is_log_incremental(l) ((uintptr_t)(l).c & 0x1) +#else +/// Tells whether a checkpoint is incremental or not. +#define is_log_incremental(l) false +#endif + + +/// The checkpoint for the multiple buddy system allocator +struct mm_checkpoint { + /// The total count of allocated bytes at the moment of the checkpoint + uint_fast32_t ckpt_size; + /// The sequence of checkpoints of the allocated buddy systems (see @a buddy_checkpoint) + unsigned char chkps[]; +}; + +/// Binds a checkpoint together with a reference index +struct mm_log { + /// The reference index, used to identify this checkpoint + array_count_t ref_idx; + /// A pointer to the actual checkpoint + struct mm_checkpoint *ckpt; +}; + /// Structure to keep data used for autonomic checkpointing selection struct auto_ckpt { /// The inverse of the rollback probability @@ -62,3 +86,6 @@ extern void auto_ckpt_init(void); extern void auto_ckpt_lp_init(struct auto_ckpt *auto_ckpt); extern void auto_ckpt_on_gvt(void); extern void auto_ckpt_recompute(struct auto_ckpt *auto_ckpt, uint_fast32_t state_size); +extern void model_allocator_checkpoint_next_force_full(const struct mm_state *self); +extern void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_idx); +extern array_count_t model_allocator_checkpoint_restore(struct mm_state *self, array_count_t ref_idx); diff --git a/src/mm/checkpoint/full.c b/src/mm/checkpoint/full.c new file mode 100644 index 00000000..3bfbf0c2 --- /dev/null +++ b/src/mm/checkpoint/full.c @@ -0,0 +1,82 @@ +/** +* @file mm/checkpoint/full.c + * + * @brief Full checkpointing routines + * + * This unit contains the implementation of full checkpointing routines for the LP memory management + * + * SPDX-FileCopyrightText: 2008-2025 HPCS Group + * SPDX-License-Identifier: GPL-3.0-only + */ +#include +#include +#include +/** + * @brief Takes a full checkpoint of the memory management state. + * + * This function creates a full checkpoint of the memory management state for a logical process. + * It allocates memory for the checkpoint, records its size, and stores it in the logs. Each buddy + * system's state is saved into the checkpoint structure. + * + * @param self A pointer to the `mm_state` structure representing the memory management state. + * @param ref_idx The reference index associated with the checkpoint. + */ +void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_idx) +{ + struct mm_checkpoint *ckpt = mm_alloc(self->full_ckpt_size); + ckpt->ckpt_size = self->full_ckpt_size; + + const struct mm_log mm_log = {.ref_idx = ref_idx, .ckpt = ckpt}; + array_push(self->logs, mm_log); + + struct buddy_checkpoint *buddy_ckp = (struct buddy_checkpoint *)ckpt->chkps; + array_count_t i = array_count(self->buddies); + while(i--) + buddy_ckp = buddy_checkpoint_full_take(array_get_at(self->buddies, i), buddy_ckp); + buddy_ckp->orig = NULL; +} + + +/** + * @brief Restores the memory management state to a specific checkpoint. + * + * This function restores the memory management state of a logical process to the state + * recorded in the checkpoint corresponding to the given reference index. It ensures + * that all buddy systems are restored to their respective states as recorded in the + * checkpoint. If a checkpoint is missing for a buddy system, it reinitializes the buddy + * system to a default state. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + * @param ref_idx The reference index of the checkpoint to restore. + * @return The reference index of the restored checkpoint. + */ +array_count_t model_allocator_checkpoint_restore(struct mm_state *self, const array_count_t ref_idx) +{ + array_count_t index = array_count(self->logs) - 1; + while(array_get_at(self->logs, index).ref_idx > ref_idx) + index--; + + const struct mm_checkpoint *ckp = array_get_at(self->logs, index).ckpt; + self->full_ckpt_size = ckp->ckpt_size; + const struct buddy_checkpoint *buddy_ckpt = (struct buddy_checkpoint *)ckp->chkps; + + array_count_t k = array_count(self->buddies); + while(k--) { + struct buddy_state *b = array_get_at(self->buddies, k); + const struct buddy_checkpoint *ckpt = + buddy_checkpoint_full_restore(array_get_at(self->buddies, k), buddy_ckpt); + if(unlikely(ckpt == NULL)) { + buddy_init(b); + self->full_ckpt_size += offsetof(struct buddy_checkpoint, base_mem); + } else { + buddy_ckpt = ckpt; + } + } + + for(array_count_t j = array_count(self->logs) - 1; j > index; --j) + mm_free(array_get_at(self->logs, j).ckpt); + + array_count(self->logs) = index + 1; + return array_get_at(self->logs, index).ref_idx; +} diff --git a/src/mm/checkpoint/incremental.c b/src/mm/checkpoint/incremental.c new file mode 100644 index 00000000..2916f32c --- /dev/null +++ b/src/mm/checkpoint/incremental.c @@ -0,0 +1,58 @@ +/** +* @file mm/checkpoint/incremental.c + * + * @brief Incremental checkpointing routines + * + * This unit contains the implementation of incremental checkpointing routines for the LP memory management + * + * SPDX-FileCopyrightText: 2008-2025 HPCS Group + * SPDX-License-Identifier: GPL-3.0-only + */ +#include +#include +#include +#include + +/** + * @brief Forces the next checkpoint to be a full checkpoint. + * + * This function is a placeholder for enabling full checkpointing when + * incremental state saving is active. Currently, it does nothing as + * incremental checkpointing is disabled. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + */ +void model_allocator_checkpoint_next_force_full(const struct mm_state *self) +{ + (void)self; + // TODO: force full checkpointing when incremental state saving is enabled +} + + +/** + * @brief Marks a memory region as dirty for incremental checkpointing. + * + * This function is intended to be an entry point for the model's code, injected at compile time, + * to mark a memory region as dirty whenever a write operation is performed. It updates the + * corresponding buddy system to track the modified memory region. + * + * @note This function is currently unused because the incremental checkpointing subsystem + * is disabled. + * + * @param ptr A pointer to the start of the memory region being written to. + * @param size The size of the memory region being written to, in bytes. + */ +void __write_mem(const void *ptr, const size_t size) +{ + struct mm_state *self = ¤t_lp->mm_state; + if(unlikely(!size || array_is_empty(self->buddies))) + return; + + if(unlikely(ptr < (void *)array_get_at(self->buddies, 0) || ptr > (void *)(array_peek(self->buddies) + 1))) + return; + + struct buddy_state *buddy = buddy_find_by_address(self, ptr); + + buddy_dirty_mark(buddy, ptr, size); +} diff --git a/src/mm/buddy/multi.c b/src/mm/model_allocator.c similarity index 54% rename from src/mm/buddy/multi.c rename to src/mm/model_allocator.c index 3ad7ab4d..cc2141bb 100644 --- a/src/mm/buddy/multi.c +++ b/src/mm/model_allocator.c @@ -1,28 +1,20 @@ /** - * @file mm/buddy/multi.c + * @file mm/model_allocator.c * - * @brief Handling of multiple buddy systems + * @brief The subsystem managing the memory state of an LP * * SPDX-FileCopyrightText: 2008-2025 HPCS Group * SPDX-License-Identifier: GPL-3.0-only */ -#include +#include +#include +#include +#include #include -#include +#include #include -#include -#include -#include - -#ifdef ROOTSIM_INCREMENTAL -/// Tells whether a checkpoint is incremental or not. -#define is_log_incremental(l) ((uintptr_t)(l).c & 0x1) -#else -/// Tells whether a checkpoint is incremental or not. -#define is_log_incremental(l) false -#endif /** * @brief Initializes the memory management state for a logical process. @@ -69,6 +61,34 @@ void model_allocator_lp_fini(const struct mm_state *self) } +/** + * @brief Finds the buddy system managing a given memory address. + * + * This function performs a binary search to locate the `buddy_state` structure + * that manages the memory block containing the specified address. + * + * @param self A pointer to the `mm_state` structure representing the memory + * management state of the logical process. + * @param ptr A pointer to the memory address to locate within the buddy system. + * @return A pointer to the `buddy_state` structure managing the memory block + * containing the specified address. + */ +struct buddy_state *buddy_find_by_address(const struct mm_state *self, const void *ptr) +{ + array_count_t low = 0, high = array_count(self->buddies) - 1; + while(1) { + const array_count_t middle = (low + high) / 2; + struct buddy_state *buddy = array_get_at(self->buddies, middle); + if(ptr < (void *)buddy) + high = middle - 1; + else if(ptr > (void *)(buddy + 1)) + low = middle + 1; + else + return buddy; + } +} + + void *rs_malloc(size_t req_size) { if(unlikely(!req_size)) @@ -103,6 +123,7 @@ void *rs_malloc(size_t req_size) return buddy_malloc(new_buddy, req_blks_exp); } + void *rs_calloc(const size_t nmemb, const size_t size) { const size_t tot = nmemb * size; @@ -114,33 +135,6 @@ void *rs_calloc(const size_t nmemb, const size_t size) return ret; } -/** - * @brief Finds the buddy system managing a given memory address. - * - * This function performs a binary search to locate the `buddy_state` structure - * that manages the memory block containing the specified address. - * - * @param self A pointer to the `mm_state` structure representing the memory - * management state of the logical process. - * @param ptr A pointer to the memory address to locate within the buddy system. - * @return A pointer to the `buddy_state` structure managing the memory block - * containing the specified address. - */ -static inline struct buddy_state *buddy_find_by_address(const struct mm_state *self, const void *ptr) -{ - array_count_t low = 0, high = array_count(self->buddies) - 1; - while(1) { - const array_count_t middle = (low + high) / 2; - struct buddy_state *buddy = array_get_at(self->buddies, middle); - if(ptr < (void *)buddy) - high = middle - 1; - else if(ptr > (void *)(buddy + 1)) - low = middle + 1; - else - return buddy; - } -} - void rs_free(void *ptr) { @@ -182,118 +176,6 @@ void *rs_realloc(void *ptr, size_t req_size) } -/** - * @brief Marks a memory region as dirty for incremental checkpointing. - * - * This function is intended to be an entry point for the model's code, injected at compile time, - * to mark a memory region as dirty whenever a write operation is performed. It updates the - * corresponding buddy system to track the modified memory region. - * - * @note This function is currently unused because the incremental checkpointing subsystem - * is disabled. - * - * @param ptr A pointer to the start of the memory region being written to. - * @param size The size of the memory region being written to, in bytes. - */ -void __write_mem(const void *ptr, const size_t size) -{ - struct mm_state *self = ¤t_lp->mm_state; - if(unlikely(!size || array_is_empty(self->buddies))) - return; - - if(unlikely(ptr < (void *)array_get_at(self->buddies, 0) || ptr > (void *)(array_peek(self->buddies) + 1))) - return; - - struct buddy_state *buddy = buddy_find_by_address(self, ptr); - - buddy_dirty_mark(buddy, ptr, size); -} - -/** - * @brief Takes a full checkpoint of the memory management state. - * - * This function creates a full checkpoint of the memory management state for a logical process. - * It allocates memory for the checkpoint, records its size, and stores it in the logs. Each buddy - * system's state is saved into the checkpoint structure. - * - * @param self A pointer to the `mm_state` structure representing the memory management state. - * @param ref_idx The reference index associated with the checkpoint. - */ -void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_idx) -{ - struct mm_checkpoint *ckpt = mm_alloc(self->full_ckpt_size); - ckpt->ckpt_size = self->full_ckpt_size; - - const struct mm_log mm_log = {.ref_idx = ref_idx, .ckpt = ckpt}; - array_push(self->logs, mm_log); - - struct buddy_checkpoint *buddy_ckp = (struct buddy_checkpoint *)ckpt->chkps; - array_count_t i = array_count(self->buddies); - while(i--) - buddy_ckp = checkpoint_full_take(array_get_at(self->buddies, i), buddy_ckp); - buddy_ckp->orig = NULL; -} - -/** - * @brief Forces the next checkpoint to be a full checkpoint. - * - * This function is a placeholder for enabling full checkpointing when - * incremental state saving is active. Currently, it does nothing as - * incremental checkpointing is disabled. - * - * @param self A pointer to the `mm_state` structure representing the memory - * management state of the logical process. - */ -void model_allocator_checkpoint_next_force_full(const struct mm_state *self) -{ - (void)self; - // TODO: force full checkpointing when incremental state saving is enabled -} - - -/** - * @brief Restores the memory management state to a specific checkpoint. - * - * This function restores the memory management state of a logical process to the state - * recorded in the checkpoint corresponding to the given reference index. It ensures - * that all buddy systems are restored to their respective states as recorded in the - * checkpoint. If a checkpoint is missing for a buddy system, it reinitializes the buddy - * system to a default state. - * - * @param self A pointer to the `mm_state` structure representing the memory - * management state of the logical process. - * @param ref_idx The reference index of the checkpoint to restore. - * @return The reference index of the restored checkpoint. - */ -array_count_t model_allocator_checkpoint_restore(struct mm_state *self, const array_count_t ref_idx) -{ - array_count_t index = array_count(self->logs) - 1; - while(array_get_at(self->logs, index).ref_idx > ref_idx) - index--; - - const struct mm_checkpoint *ckp = array_get_at(self->logs, index).ckpt; - self->full_ckpt_size = ckp->ckpt_size; - const struct buddy_checkpoint *buddy_ckpt = (struct buddy_checkpoint *)ckp->chkps; - - array_count_t k = array_count(self->buddies); - while(k--) { - struct buddy_state *b = array_get_at(self->buddies, k); - const struct buddy_checkpoint *ckpt = checkpoint_full_restore(array_get_at(self->buddies, k), buddy_ckpt); - if(unlikely(ckpt == NULL)) { - buddy_init(b); - self->full_ckpt_size += offsetof(struct buddy_checkpoint, base_mem); - } else { - buddy_ckpt = ckpt; - } - } - - for(array_count_t j = array_count(self->logs) - 1; j > index; --j) - mm_free(array_get_at(self->logs, j).ckpt); - - array_count(self->logs) = index + 1; - return array_get_at(self->logs, index).ref_idx; -} - /** * @brief Collects fossil logs up to a target reference index. diff --git a/src/mm/model_allocator.h b/src/mm/model_allocator.h index db15912e..3bd12b2c 100644 --- a/src/mm/model_allocator.h +++ b/src/mm/model_allocator.h @@ -11,11 +11,18 @@ #pragma once #include -#include +/// The checkpointable memory context assigned to a single LP +struct mm_state { + /// The array of pointers to the allocated buddy systems for the LP + dyn_array(struct buddy_state *) buddies; + /// The array of checkpoints + dyn_array(struct mm_log) logs; + /// The total count of allocated bytes + uint_fast32_t full_ckpt_size; +}; + +extern struct buddy_state *buddy_find_by_address(const struct mm_state *self, const void *ptr); extern void model_allocator_lp_init(struct mm_state *self); extern void model_allocator_lp_fini(const struct mm_state *self); -extern void model_allocator_checkpoint_take(struct mm_state *self, array_count_t ref_idx); -extern void model_allocator_checkpoint_next_force_full(const struct mm_state *self); -extern array_count_t model_allocator_checkpoint_restore(struct mm_state *self, array_count_t ref_idx); extern array_count_t model_allocator_fossil_lp_collect(struct mm_state *self, array_count_t tgt_ref_i); From a928c8aff70b4f18a1f98f7016da45593317ac44 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 18:04:15 +0200 Subject: [PATCH 09/15] Enforce code formatting style Ensure that all files are adhering to the ROOT-Sim code formatting style. There are some exceptions that have been discussed in the past, that I am keeping as is as they are more readable. Signed-off-by: Alessandro Pellegrini --- src/ROOT-Sim.h | 69 ++++--- src/core/sync.c | 2 +- src/datatypes/heap.h | 46 ++--- src/datatypes/list.h | 343 ++++++++++++++++---------------- src/datatypes/msg_queue.c | 2 +- src/init.c | 4 +- src/log/file.c | 16 +- src/log/file.h | 18 +- src/lp/common.h | 14 +- src/lp/msg.h | 4 +- src/mm/buddy/buddy.c | 7 +- src/mm/buddy/buddy.h | 21 +- src/mm/buddy/checkpoint.c | 11 +- src/mm/buddy/checkpoint.h | 32 ++- src/mm/checkpoint/autonomic.c | 4 +- src/mm/checkpoint/full.c | 3 +- src/mm/checkpoint/incremental.c | 2 +- src/mm/model_allocator.c | 1 - src/mm/model_allocator.h | 12 +- src/serial/serial.c | 2 +- src/serial/serial.h | 2 +- 21 files changed, 305 insertions(+), 310 deletions(-) diff --git a/src/ROOT-Sim.h b/src/ROOT-Sim.h index ae233086..d4b76a30 100644 --- a/src/ROOT-Sim.h +++ b/src/ROOT-Sim.h @@ -87,7 +87,7 @@ enum rootsim_event { LP_INIT = 65534, LP_FINI }; * @param event_size The size (in bytes) of the event content */ extern void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *event_content, - unsigned event_size); + unsigned event_size); extern void SetState(void *new_state); @@ -145,7 +145,8 @@ extern void rs_free(void *ptr); * of the memory block is preserved up to the minimum of the old and new sizes. * Upon a rollback, the memory is restored to its previous (consistent) state. * - * @param ptr A pointer to the memory block to be reallocated. If `ptr` is `NULL`, the function behaves like `rs_malloc()`. + * @param ptr A pointer to the memory block to be reallocated. If `ptr` is `NULL`, the function behaves like + * `rs_malloc()`. * @param req_size The new size of the memory block, in bytes. * @return A pointer to the reallocated memory block, or `NULL` if the reallocation fails. * @@ -160,45 +161,43 @@ extern void *rs_realloc(void *ptr, size_t req_size); * These levels define the verbosity of log messages emitted during the simulation. */ enum log_level { - LOG_TRACE, //!< The logging level reserved for very low priority messages. - LOG_DEBUG, //!< The logging level reserved for useful debug messages. - LOG_INFO, //!< The logging level reserved for useful runtime messages. - LOG_WARN, //!< The logging level reserved for unexpected, non-deal-breaking conditions. - LOG_ERROR, //!< The logging level reserved for unexpected, problematic conditions. - LOG_FATAL, //!< The logging level reserved for unexpected, fatal conditions. - LOG_SILENT //!< Emit no messages during the simulation. + LOG_TRACE, //!< The logging level reserved for very low priority messages. + LOG_DEBUG, //!< The logging level reserved for useful debug messages. + LOG_INFO, //!< The logging level reserved for useful runtime messages. + LOG_WARN, //!< The logging level reserved for unexpected, non-deal-breaking conditions. + LOG_ERROR, //!< The logging level reserved for unexpected, problematic conditions. + LOG_FATAL, //!< The logging level reserved for unexpected, fatal conditions. + LOG_SILENT //!< Emit no messages during the simulation. }; /// A set of configurable values used by other modules struct simulation_configuration { - /// The number of LPs to be used in the simulation - lp_id_t lps; - /// The number of threads to be used in the simulation. If zero, it defaults to the amount of available cores - unsigned n_threads; - /// The target termination logical time. Setting this value to zero means that LVT-based termination is disabled - simtime_t termination_time; - /// The gvt period expressed in microseconds - unsigned gvt_period; - /// The logger verbosity level - enum log_level log_level; - /// File where to write logged information: if not NULL, output is redirected to this file - FILE *logfile; - /// Path to the statistics file. If NULL, no statistics are produced. - const char *stats_file; - /// The checkpointing interval - unsigned ckpt_interval; - /// If set, worker threads are bound to physical cores - bool core_binding; - /// If set, the simulation will run on the serial runtime - bool serial; - /// Function pointer to the dispatching function - ProcessEvent_t dispatcher; - /// Function pointer to the termination detection function - CanEnd_t committed; + /// The number of LPs to be used in the simulation + lp_id_t lps; + /// The number of threads to be used in the simulation. If zero, it defaults to the amount of available cores + unsigned n_threads; + /// The target termination logical time. Setting this value to zero means that LVT-based termination is disabled + simtime_t termination_time; + /// The gvt period expressed in microseconds + unsigned gvt_period; + /// The logger verbosity level + enum log_level log_level; + /// File where to write logged information: if not NULL, output is redirected to this file + FILE *logfile; + /// Path to the statistics file. If NULL, no statistics are produced. + const char *stats_file; + /// The checkpointing interval + unsigned ckpt_interval; + /// If set, worker threads are bound to physical cores + bool core_binding; + /// If set, the simulation will run on the serial runtime + bool serial; + /// Function pointer to the dispatching function + ProcessEvent_t dispatcher; + /// Function pointer to the termination detection function + CanEnd_t committed; }; extern int RootsimInit(const struct simulation_configuration *conf); - extern int RootsimRun(void); - extern void RootsimStop(void); diff --git a/src/core/sync.c b/src/core/sync.c index 876383ce..8c42d7bb 100644 --- a/src/core/sync.c +++ b/src/core/sync.c @@ -21,7 +21,7 @@ bool sync_thread_barrier(void) bool l; unsigned r; - static __thread unsigned phase; + static _Thread_local unsigned phase; static atomic_uint cs[2]; // FIXME: this makes this barrier stateful with respect to the threads used atomic_uint *c = cs + (phase & 1U); diff --git a/src/datatypes/heap.h b/src/datatypes/heap.h index 575a9741..17bd78e1 100644 --- a/src/datatypes/heap.h +++ b/src/datatypes/heap.h @@ -60,7 +60,7 @@ * @param self the heap * @return the highest priority element, cast to const */ -#define heap_min(self) (*(__typeof__ (*array_items(self)) *const)array_items(self)) +#define heap_min(self) (*(__typeof__(*array_items(self)) *const)array_items(self)) /** * @brief Insert an element into the heap @@ -74,8 +74,8 @@ #define heap_insert(self, cmp_f, elem) \ __extension__({ \ array_reserve(self, 1); \ - __typeof__ (array_count(self)) i = array_count(self)++; \ - __typeof__ (array_items(self)) items = array_items(self); \ + __typeof__(array_count(self)) i = array_count(self)++; \ + __typeof__(array_items(self)) items = array_items(self); \ while(i && cmp_f(elem, items[(i - 1U) / 2U])) { \ items[i] = items[(i - 1U) / 2U]; \ i = (i - 1U) / 2U; \ @@ -97,10 +97,10 @@ #define heap_insert_n(self, cmp_f, ins, n) \ __extension__({ \ array_reserve(self, n); \ - __typeof__ (array_count(self)) j = n; \ - __typeof__ (array_items(self)) items = array_items(self); \ + __typeof__(array_count(self)) j = n; \ + __typeof__(array_items(self)) items = array_items(self); \ while(j--) { \ - __typeof__ (array_count(self)) i = array_count(self)++; \ + __typeof__(array_count(self)) i = array_count(self)++; \ while(i && cmp_f((ins)[j], items[(i - 1U) / 2U])) { \ items[i] = items[(i - 1U) / 2U]; \ i = (i - 1U) / 2U; \ @@ -118,21 +118,21 @@ * For correct operation of the heap you need to always pass the same @a cmp_f both for insertion and extraction */ #define heap_extract(self, cmp_f) \ - __extension__({ \ - __typeof__ (array_items(self)) items = array_items(self); \ - __typeof__ (*array_items(self)) ret = array_items(self)[0]; \ - __typeof__ (*array_items(self)) last = array_pop(self); \ - __typeof__ (array_count(self)) cnt = array_count(self); \ - __typeof__ (array_count(self)) i = 1U; \ - __typeof__ (array_count(self)) j = 0U; \ - while(i < cnt) { \ - i += i + 1 < cnt && cmp_f(items[i + 1U], items[i]); \ - if(!cmp_f(items[i], last)) \ - break; \ - items[j] = items[i]; \ - j = i; \ - i = i * 2U + 1U; \ - } \ - items[j] = last; \ - ret; \ + __extension__({ \ + __typeof__(array_items(self)) items = array_items(self); \ + __typeof__(*array_items(self)) ret = array_items(self)[0]; \ + __typeof__(*array_items(self)) last = array_pop(self); \ + __typeof__(array_count(self)) cnt = array_count(self); \ + __typeof__(array_count(self)) i = 1U; \ + __typeof__(array_count(self)) j = 0U; \ + while(i < cnt) { \ + i += i + 1 < cnt && cmp_f(items[i + 1U], items[i]); \ + if(!cmp_f(items[i], last)) \ + break; \ + items[j] = items[i]; \ + j = i; \ + i = i * 2U + 1U; \ + } \ + items[j] = last; \ + ret; \ }) diff --git a/src/datatypes/list.h b/src/datatypes/list.h index 7919dd79..749e42be 100644 --- a/src/datatypes/list.h +++ b/src/datatypes/list.h @@ -1,13 +1,13 @@ /** -* @file datatypes/list.h -* -* @brief List datatype -* -* A generic doubly-linked list -* -* SPDX-FileCopyrightText: 2008-2025 HPCS Group -* SPDX-License-Identifier: GPL-3.0-only -*/ + * @file datatypes/list.h + * + * @brief List datatype + * + * A generic doubly-linked list + * + * SPDX-FileCopyrightText: 2008-2025 HPCS Group + * SPDX-License-Identifier: GPL-3.0-only + */ #pragma once #include @@ -25,7 +25,7 @@ struct list { }; /// This macro is a slightly-different implementation of the standard offsetof macro -#define my_offsetof(st, m) ((size_t)( (unsigned char *)&((st)->m ) - (unsigned char *)(st))) +#define my_offsetof(st, m) ((size_t)((unsigned char *)&((st)->m) - (unsigned char *)(st))) /// Declare a "typed" list. This is a pointer to type, but the variable will instead reference a struct rootsim_list! #define list(type) type * @@ -36,12 +36,12 @@ struct list { * list(int) = new_list(int); * \endcode */ -#define new_list(type) \ - __extension__({ \ - void *__lmptr; \ - __lmptr = malloc(sizeof(struct list)); \ - memset(__lmptr, 0, sizeof(struct list));\ - __lmptr;\ +#define new_list(type) \ + __extension__({ \ + void *__lmptr; \ + __lmptr = malloc(sizeof(struct list)); \ + memset(__lmptr, 0, sizeof(struct list)); \ + __lmptr; \ }) /** @@ -84,11 +84,12 @@ struct list { #define list_prev(ptr) ((ptr)->prev) /// This macro retrieves the key of a payload data structure given its offset, and casts the value to double. -#define get_key(data) ({\ - char *__key_ptr = ((char *)(data) + __key_position);\ - double *__key_double_ptr = (double *)__key_ptr;\ - *__key_double_ptr;\ - }) +#define get_key(data) \ + ({ \ + char *__key_ptr = ((char *)(data) + __key_position); \ + double *__key_double_ptr = (double *)__key_ptr; \ + *__key_double_ptr; \ + }) /** * Given a pointer to a list, this macro evaluates to a boolean telling whether @@ -108,26 +109,26 @@ struct list { * @param li A pointer to the list created using the `new_list()` macro. * @param data A pointer to the node to be inserted. The node must have `next` and `prev` members. */ -#define list_insert_tail(li, data) \ - do { \ - __typeof__(data) __new_n = (data); /* in-block scope variable */\ - struct list *__l;\ - __new_n->next = NULL;\ - __new_n->prev = NULL;\ - do {\ - __l = (struct list *)(li);\ - assert(__l);\ - if(__l->size == 0) { /* is the list empty? */\ - __l->head = __new_n;\ - __l->tail = __new_n;\ - break; /* leave the inner do-while */\ - }\ - __new_n->next = NULL; /* Otherwise add at the end */\ - __new_n->prev = __l->tail;\ - ((__typeof__(data))(__l->tail))->next = __new_n;\ - __l->tail = __new_n;\ - } while(0);\ - __l->size++;\ +#define list_insert_tail(li, data) \ + do { \ + __typeof__(data) __new_n = (data); /* in-block scope variable */ \ + struct list *__l; \ + __new_n->next = NULL; \ + __new_n->prev = NULL; \ + do { \ + __l = (struct list *)(li); \ + assert(__l); \ + if(__l->size == 0) { /* is the list empty? */ \ + __l->head = __new_n; \ + __l->tail = __new_n; \ + break; /* leave the inner do-while */ \ + } \ + __new_n->next = NULL; /* Otherwise add at the end */ \ + __new_n->prev = __l->tail; \ + ((__typeof__(data))(__l->tail))->next = __new_n; \ + __l->tail = __new_n; \ + } while(0); \ + __l->size++; \ } while(0) @@ -140,24 +141,24 @@ struct list { * @param li A pointer to the list created using the `new_list()` macro. * @param data A pointer to the node to be inserted. The node must have `next` and `prev` members. */ -#define list_insert_head(li, data) \ - do { \ - __typeof__(data) __new_n = (data); /* in-block scope variable */\ - struct list *__l;\ - __new_n->next = NULL;\ - __new_n->prev = NULL;\ - __l = (struct list *)(li);\ - assert(__l);\ - if(__l->size == 0) { /* is the list empty? */\ - __l->head = __new_n;\ - __l->tail = __new_n;\ - }else{\ - __new_n->prev = NULL; /* Otherwise add at the beginning */\ - __new_n->next = __l->head;\ - ((__typeof__(data))__l->head)->prev = __new_n;\ - __l->head = __new_n;\ - }\ - __l->size++;\ +#define list_insert_head(li, data) \ + do { \ + __typeof__(data) __new_n = (data); /* in-block scope variable */ \ + struct list *__l; \ + __new_n->next = NULL; \ + __new_n->prev = NULL; \ + __l = (struct list *)(li); \ + assert(__l); \ + if(__l->size == 0) { /* is the list empty? */ \ + __l->head = __new_n; \ + __l->tail = __new_n; \ + } else { \ + __new_n->prev = NULL; /* Otherwise add at the beginning */ \ + __new_n->next = __l->head; \ + ((__typeof__(data))__l->head)->prev = __new_n; \ + __l->head = __new_n; \ + } \ + __l->size++; \ } while(0) @@ -181,51 +182,51 @@ struct list { * @post The list size is incremented by 1. * @post The new node is inserted at the correct position based on the key value. */ -#define list_insert(li, key_name, data)\ - do {\ - __typeof__(data) __n; /* in-block scope variable */\ - __typeof__(data) __new_n = (data);\ - size_t __key_position = my_offsetof((li), key_name);\ - double __key;\ - size_t __size_before;\ - struct list *__l;\ - do {\ - __l = (struct list *)(li);\ - assert(__l);\ - __size_before = __l->size;\ - if(__l->size == 0) { /* Is the list empty? */\ - __new_n->prev = NULL;\ - __new_n->next = NULL;\ - __l->head = __new_n;\ - __l->tail = __new_n;\ - break;\ - }\ - __key = get_key(__new_n); /* Retrieve the new node's key */\ - /* Scan from the tail, as keys are ordered in an increasing order */\ - __n = __l->tail;\ - while(__n != NULL && __key < get_key(__n)) {\ - __n = __n->prev;\ - }\ - /* Insert depending on the position */\ - if(__n == __l->tail) { /* tail */\ - __new_n->next = NULL;\ - ((__typeof__(data))__l->tail)->next = __new_n;\ - __new_n->prev = __l->tail;\ - __l->tail = __new_n;\ - } else if(__n == NULL) { /* head */\ - __new_n->prev = NULL;\ - __new_n->next = __l->head;\ - ((__typeof__(data))__l->head)->prev = __new_n;\ - __l->head = __new_n;\ - } else { /* middle */\ - __new_n->prev = __n;\ - __new_n->next = __n->next;\ - __n->next->prev = __new_n;\ - __n->next = __new_n;\ - }\ - } while(0);\ - __l->size++;\ - assert(__l->size == (__size_before + 1));\ +#define list_insert(li, key_name, data) \ + do { \ + __typeof__(data) __n; /* in-block scope variable */ \ + __typeof__(data) __new_n = (data); \ + size_t __key_position = my_offsetof((li), key_name); \ + double __key; \ + size_t __size_before; \ + struct list *__l; \ + do { \ + __l = (struct list *)(li); \ + assert(__l); \ + __size_before = __l->size; \ + if(__l->size == 0) { /* Is the list empty? */ \ + __new_n->prev = NULL; \ + __new_n->next = NULL; \ + __l->head = __new_n; \ + __l->tail = __new_n; \ + break; \ + } \ + __key = get_key(__new_n); /* Retrieve the new node's key */ \ + /* Scan from the tail, as keys are ordered in an increasing order */ \ + __n = __l->tail; \ + while(__n != NULL && __key < get_key(__n)) { \ + __n = __n->prev; \ + } \ + /* Insert depending on the position */ \ + if(__n == __l->tail) { /* tail */ \ + __new_n->next = NULL; \ + ((__typeof__(data))__l->tail)->next = __new_n; \ + __new_n->prev = __l->tail; \ + __l->tail = __new_n; \ + } else if(__n == NULL) { /* head */ \ + __new_n->prev = NULL; \ + __new_n->next = __l->head; \ + ((__typeof__(data))__l->head)->prev = __new_n; \ + __l->head = __new_n; \ + } else { /* middle */ \ + __new_n->prev = __n; \ + __new_n->next = __n->next; \ + __n->next->prev = __new_n; \ + __n->next = __new_n; \ + } \ + } while(0); \ + __l->size++; \ + assert(__l->size == (__size_before + 1)); \ } while(0) @@ -256,23 +257,23 @@ struct list { __l->head = __n->next; \ if(__l->head != NULL) { \ ((__typeof__(node))__l->head)->prev = NULL; \ - }\ - }\ - if(__l->tail == __n) {\ - __l->tail = __n->prev;\ - if(__l->tail != NULL) {\ - ((__typeof__(node))__l->tail)->next = NULL;\ - }\ - }\ - if(__n->next != NULL) {\ - __n->next->prev = __n->prev;\ - }\ - if(__n->prev != NULL) {\ - __n->prev->next = __n->next;\ - }\ - __n->next = (void *)0xBEEFC0DE;\ - __n->prev = (void *)0xDEADC0DE;\ - __l->size--;\ + } \ + } \ + if(__l->tail == __n) { \ + __l->tail = __n->prev; \ + if(__l->tail != NULL) { \ + ((__typeof__(node))__l->tail)->next = NULL; \ + } \ + } \ + if(__n->next != NULL) { \ + __n->next->prev = __n->prev; \ + } \ + if(__n->prev != NULL) { \ + __n->prev->next = __n->next; \ + } \ + __n->next = (void *)0xBEEFC0DE; \ + __n->prev = (void *)0xDEADC0DE; \ + __l->size--; \ } while(0) @@ -291,28 +292,28 @@ struct list { * @post The head node is removed from the list, and the list size is decremented by 1. * @post The `next` and `prev` pointers of the removed node are set to invalid values. */ -#define list_pop(list)\ - do {\ - struct list *__l;\ - size_t __size_before;\ - __typeof__ (list) __n;\ - __typeof__ (list) __n_next;\ - __l = (struct list *)(list);\ - assert(__l);\ - __size_before = __l->size;\ - __n = __l->head;\ - if(__n != NULL) {\ - __l->head = __n->next;\ - if(__n->next != NULL) {\ - __n->next->prev = NULL;\ - }\ - __n_next = __n->next;\ - __n->next = (void *)0xDEFEC8ED;\ - __n->prev = (void *)0xDEFEC8ED;\ - __n = __n_next;\ - __l->size--;\ - assert(__l->size == (__size_before - 1));\ - }\ +#define list_pop(list) \ + do { \ + struct list *__l; \ + size_t __size_before; \ + __typeof__(list) __n; \ + __typeof__(list) __n_next; \ + __l = (struct list *)(list); \ + assert(__l); \ + __size_before = __l->size; \ + __n = __l->head; \ + if(__n != NULL) { \ + __l->head = __n->next; \ + if(__n->next != NULL) { \ + __n->next->prev = NULL; \ + } \ + __n_next = __n->next; \ + __n->next = (void *)0xDEFEC8ED; \ + __n->prev = (void *)0xDEFEC8ED; \ + __n = __n_next; \ + __l->size--; \ + assert(__l->size == (__size_before - 1)); \ + } \ } while(0) @@ -337,34 +338,34 @@ struct list { * @post The list size is decremented by the number of removed nodes. * @post The `next` and `prev` pointers of the removed nodes are set to invalid values. */ -#define list_trunc(list, key_name, key_value, release_fn) \ - ({\ - struct list *__l = (struct list *)(list);\ - __typeof__(list) __n;\ - __typeof__(list) __n_adjacent;\ - unsigned int __deleted = 0;\ - size_t __key_position = my_offsetof((list), key_name);\ - assert(__l);\ - size_t __size_before = __l->size;\ - /* Attempting to truncate an empty list? */\ - if(__l->size > 0) {\ - __n = __l->head;\ - while(__n != NULL && get_key(__n) < (key_value)) {\ - __deleted++;\ - __n_adjacent = __n->next;\ - __n->next = (void *)0xBAADF00D;\ - __n->prev = (void *)0xBAADF00D;\ - release_fn(__n);\ - __n = __n_adjacent;\ - }\ - __l->head = __n;\ - if(__l->head != NULL)\ - ((__typeof__(list))__l->head)->prev = NULL;\ - }\ - __l->size -= __deleted;\ - assert(__l->size == (__size_before - __deleted));\ - __deleted;\ - }) +#define list_trunc(list, key_name, key_value, release_fn) \ + ({ \ + struct list *__l = (struct list *)(list); \ + __typeof__(list) __n; \ + __typeof__(list) __n_adjacent; \ + unsigned int __deleted = 0; \ + size_t __key_position = my_offsetof((list), key_name); \ + assert(__l); \ + size_t __size_before = __l->size; \ + /* Attempting to truncate an empty list? */ \ + if(__l->size > 0) { \ + __n = __l->head; \ + while(__n != NULL && get_key(__n) < (key_value)) { \ + __deleted++; \ + __n_adjacent = __n->next; \ + __n->next = (void *)0xBAADF00D; \ + __n->prev = (void *)0xBAADF00D; \ + release_fn(__n); \ + __n = __n_adjacent; \ + } \ + __l->head = __n; \ + if(__l->head != NULL) \ + ((__typeof__(list))__l->head)->prev = NULL; \ + } \ + __l->size -= __deleted; \ + assert(__l->size == (__size_before - __deleted)); \ + __deleted; \ + }) /** diff --git a/src/datatypes/msg_queue.c b/src/datatypes/msg_queue.c index 0fcdd127..1d563807 100644 --- a/src/datatypes/msg_queue.c +++ b/src/datatypes/msg_queue.c @@ -24,7 +24,7 @@ #include /// Determine an ordering between two elements in a queue -#define q_elem_is_before(ma, mb) ((ma).t < (mb).t) +#define q_elem_is_before(ma, mb) ((ma).t < (mb).t) /// An element in the message queue struct q_elem { diff --git a/src/init.c b/src/init.c index 28ad6b16..38347780 100644 --- a/src/init.c +++ b/src/init.c @@ -110,9 +110,9 @@ int RootsimInit(const struct simulation_configuration *conf) log_init(global_config.logfile); - if (global_config.serial) + if(global_config.serial) global_config.n_threads = 1; - else if (global_config.n_threads == 0) + else if(global_config.n_threads == 0) global_config.n_threads = thread_cores_count(); if(global_config.termination_time == 0) diff --git a/src/log/file.c b/src/log/file.c index dce671bf..78a616ab 100644 --- a/src/log/file.c +++ b/src/log/file.c @@ -1,12 +1,12 @@ /** -* @file log/file.c -* -* @brief File utilities -* -* Some file utility functions -* -* SPDX-FileCopyrightText: 2008-2025 HPCS Group -* SPDX-License-Identifier: GPL-3.0-only + * @file log/file.c + * + * @brief File utilities + * + * Some file utility functions + * + * SPDX-FileCopyrightText: 2008-2025 HPCS Group + * SPDX-License-Identifier: GPL-3.0-only */ #include diff --git a/src/log/file.h b/src/log/file.h index d4a5215b..1db4088b 100644 --- a/src/log/file.h +++ b/src/log/file.h @@ -1,13 +1,13 @@ /** -* @file log/file.h -* -* @brief File utilities -* -* Some file utility functions -* -* SPDX-FileCopyrightText: 2008-2025 HPCS Group -* SPDX-License-Identifier: GPL-3.0-only -*/ + * @file log/file.h + * + * @brief File utilities + * + * Some file utility functions + * + * SPDX-FileCopyrightText: 2008-2025 HPCS Group + * SPDX-License-Identifier: GPL-3.0-only + */ #pragma once #include diff --git a/src/lp/common.h b/src/lp/common.h index f2718df1..4afc5b39 100644 --- a/src/lp/common.h +++ b/src/lp/common.h @@ -1,11 +1,11 @@ /** -* @file lp/common.h -* -* @brief Common LP functionalities -* -* SPDX-FileCopyrightText: 2008-2025 HPCS Group -* SPDX-License-Identifier: GPL-3.0-only -*/ + * @file lp/common.h + * + * @brief Common LP functionalities + * + * SPDX-FileCopyrightText: 2008-2025 HPCS Group + * SPDX-License-Identifier: GPL-3.0-only + */ #pragma once #include diff --git a/src/lp/msg.h b/src/lp/msg.h index 7ab9c0b0..5ef0d035 100644 --- a/src/lp/msg.h +++ b/src/lp/msg.h @@ -110,10 +110,10 @@ enum msg_flag { MSG_FLAG_ANTI = 1, MSG_FLAG_PROCESSED = 2 }; */ static inline bool msg_is_before_extended(const struct lp_msg *restrict a, const struct lp_msg *restrict b) { - if (a->m_type != b->m_type) + if(a->m_type != b->m_type) return a->m_type > b->m_type; - if (a->pl_size != b->pl_size) + if(a->pl_size != b->pl_size) return a->pl_size < b->pl_size; return memcmp(a->pl, b->pl, a->pl_size) > 0; diff --git a/src/mm/buddy/buddy.c b/src/mm/buddy/buddy.c index f30263b9..f6f92ceb 100644 --- a/src/mm/buddy/buddy.c +++ b/src/mm/buddy/buddy.c @@ -11,7 +11,7 @@ #include /// Tells if the given index is a power of 2 -#define is_power_of_2(index) (!((index) & ((index)-1))) +#define is_power_of_2(index) (!((index) & ((index) - 1))) /** * @brief Initializes the buddy system allocator. @@ -69,7 +69,8 @@ void *buddy_malloc(struct buddy_state *self, const uint_fast8_t req_blks_exp) while(index) { index = buddy_parent(index); - self->longest[index] = max(self->longest[buddy_left_child(index)], self->longest[buddy_right_child(index)]); + self->longest[index] = + max(self->longest[buddy_left_child(index)], self->longest[buddy_right_child(index)]); #ifdef ROOTSIM_INCREMENTAL bitmap_set(self->dirty, index >> B_BLOCK_EXP); #endif @@ -190,7 +191,7 @@ struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *sel */ void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t size) { - const uintptr_t diff = (unsigned char *)ptr - (unsigned char *)self->base_mem; + const uintptr_t diff = (unsigned char *)ptr - (unsigned char *)self->base_mem; const uint_fast32_t index = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); size += diff & ((1 << B_BLOCK_EXP) - 1); diff --git a/src/mm/buddy/buddy.h b/src/mm/buddy/buddy.h index fcf18c65..14fb23a1 100644 --- a/src/mm/buddy/buddy.h +++ b/src/mm/buddy/buddy.h @@ -34,21 +34,16 @@ struct buddy_state { /// The memory buffer served to the model alignas(16) unsigned char base_mem[1U << B_TOTAL_EXP]; /// Keeps track of memory blocks which have been dirtied by a write - block_bitmap dirty[ - bitmap_required_size( - // this tracks writes to the allocation tree - (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)) + - // while this tracks writes to the actual memory buffer - (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - ) - ]; + block_bitmap dirty[bitmap_required_size( + // this tracks writes to the allocation tree + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)) + + // while this tracks writes to the actual memory buffer + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)))]; }; -static_assert( - offsetof(struct buddy_state, longest) == - offsetof(struct buddy_state, base_mem) - - sizeof(((struct buddy_state *)0)->longest), - "longest and base_mem are not contiguous, this will break incremental checkpointing"); +static_assert(offsetof(struct buddy_state, longest) == + offsetof(struct buddy_state, base_mem) - sizeof(((struct buddy_state *)0)->longest), + "longest and base_mem are not contiguous, this will break incremental checkpointing"); extern void buddy_init(struct buddy_state *self); extern void *buddy_malloc(struct buddy_state *self, uint_fast8_t req_blks_exp); diff --git a/src/mm/buddy/checkpoint.c b/src/mm/buddy/checkpoint.c index 05826072..39c87041 100644 --- a/src/mm/buddy/checkpoint.c +++ b/src/mm/buddy/checkpoint.c @@ -179,16 +179,17 @@ struct buddy_checkpoint *buddy_checkpoint_full_take(const struct buddy_state *se * corresponds to the given buddy system before performing the restoration. * * @param self A pointer to the `buddy_state` structure representing the current buddy system. - * @param ckp A pointer to the `buddy_checkpoint` structure containing the checkpoint data. + * @param ckpt A pointer to the `buddy_checkpoint` structure containing the checkpoint data. * @return A pointer to the next available memory location after the checkpoint data, * or `NULL` if the checkpoint does not match the buddy system. */ -const struct buddy_checkpoint *buddy_checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *ckp) +const struct buddy_checkpoint *buddy_checkpoint_full_restore(struct buddy_state *self, + const struct buddy_checkpoint *ckpt) { - if(unlikely(ckp->orig != self)) + if(unlikely(ckpt->orig != self)) return NULL; - memcpy(self->longest, ckp->longest, sizeof(self->longest)); + memcpy(self->longest, ckpt->longest, sizeof(self->longest)); #define buddy_block_copy_from_ckp(offset, len) \ __extension__({ \ @@ -196,7 +197,7 @@ const struct buddy_checkpoint *buddy_checkpoint_full_restore(struct buddy_state ptr += (len); \ }) - const unsigned char *ptr = ckp->base_mem; + const unsigned char *ptr = ckpt->base_mem; buddy_tree_visit(self->longest, buddy_block_copy_from_ckp); #undef buddy_block_copy_from_ckp diff --git a/src/mm/buddy/checkpoint.h b/src/mm/buddy/checkpoint.h index 26d0d6fe..ab27ae72 100644 --- a/src/mm/buddy/checkpoint.h +++ b/src/mm/buddy/checkpoint.h @@ -15,30 +15,28 @@ struct buddy_checkpoint { // todo only log longest[] if changed, or incrementall /// The buddy system to which this checkpoint applies. TODO: reengineer the multi-checkpointing approach const struct buddy_state *orig; /// The checkpoint of the dirty bitmap - block_bitmap dirty [ - bitmap_required_size( - // this tracks writes to the allocation tree... - (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)) + - // ...while this tracks writes to the actual memory buffer - (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - ) - ]; + block_bitmap dirty[bitmap_required_size( + // this tracks writes to the allocation tree... + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)) + + // ...while this tracks writes to the actual memory buffer + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)))]; /// The checkpointed binary tree representing the buddy system uint8_t longest[(1U << (B_TOTAL_EXP - B_BLOCK_EXP + 1))]; /// The checkpointed memory buffer assigned to the model unsigned char base_mem[]; }; -static_assert( - offsetof(struct buddy_checkpoint, longest) == - offsetof(struct buddy_checkpoint, base_mem) - - sizeof(((struct buddy_checkpoint *)0)->longest), - "longest and base_mem are not contiguous, this will break incremental checkpointing"); +static_assert(offsetof(struct buddy_checkpoint, longest) == + offsetof(struct buddy_checkpoint, base_mem) - sizeof(((struct buddy_checkpoint *)0)->longest), + "longest and base_mem are not contiguous, this will break incremental checkpointing"); -extern struct buddy_checkpoint *buddy_checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *data); -extern const struct buddy_checkpoint *buddy_checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *data); +extern struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *data); +extern const struct buddy_checkpoint *checkpoint_full_restore(struct buddy_state *self, + const struct buddy_checkpoint *data); #ifdef ROOTSIM_INCREMENTAL -extern struct buddy_checkpoint *checkpoint_incremental_take(const struct buddy_state *self, struct buddy_checkpoint *data); -extern const struct buddy_checkpoint * checkpoint_incremental_restore(struct buddy_state *self, const struct buddy_checkpoint *ckp); +extern struct buddy_checkpoint *checkpoint_incremental_take(const struct buddy_state *self, + struct buddy_checkpoint *data); +extern const struct buddy_checkpoint *checkpoint_incremental_restore(struct buddy_state *self, + const struct buddy_checkpoint *ckp); #endif diff --git a/src/mm/checkpoint/autonomic.c b/src/mm/checkpoint/autonomic.c index 99d4bcf8..297231cf 100644 --- a/src/mm/checkpoint/autonomic.c +++ b/src/mm/checkpoint/autonomic.c @@ -26,7 +26,7 @@ __extension__({ \ double s = (sample); \ double o = (old_v); \ - o *(((f)-1.0) / (f)) + s *(1.0 / (f)); \ + o *(((f) - 1.0) / (f)) + s * (1.0 / (f)); \ }) /** @@ -36,7 +36,7 @@ * the optimal checkpoint interval. */ static _Thread_local struct { - double ckpt_avg_cost; /**< Exponential moving average of checkpoint cost per byte */ + double ckpt_avg_cost; /**< Exponential moving average of checkpoint cost per byte */ double inv_sil_avg_cost; /**< Inverse of the exponential moving average of silent message cost */ } ackpt; diff --git a/src/mm/checkpoint/full.c b/src/mm/checkpoint/full.c index 3bfbf0c2..9e1830e7 100644 --- a/src/mm/checkpoint/full.c +++ b/src/mm/checkpoint/full.c @@ -1,5 +1,5 @@ /** -* @file mm/checkpoint/full.c + * @file mm/checkpoint/full.c * * @brief Full checkpointing routines * @@ -11,6 +11,7 @@ #include #include #include + /** * @brief Takes a full checkpoint of the memory management state. * diff --git a/src/mm/checkpoint/incremental.c b/src/mm/checkpoint/incremental.c index 2916f32c..cf21f54f 100644 --- a/src/mm/checkpoint/incremental.c +++ b/src/mm/checkpoint/incremental.c @@ -1,5 +1,5 @@ /** -* @file mm/checkpoint/incremental.c + * @file mm/checkpoint/incremental.c * * @brief Incremental checkpointing routines * diff --git a/src/mm/model_allocator.c b/src/mm/model_allocator.c index cc2141bb..3c93edd2 100644 --- a/src/mm/model_allocator.c +++ b/src/mm/model_allocator.c @@ -176,7 +176,6 @@ void *rs_realloc(void *ptr, size_t req_size) } - /** * @brief Collects fossil logs up to a target reference index. * diff --git a/src/mm/model_allocator.h b/src/mm/model_allocator.h index 3bd12b2c..d3f251a8 100644 --- a/src/mm/model_allocator.h +++ b/src/mm/model_allocator.h @@ -14,12 +14,12 @@ /// The checkpointable memory context assigned to a single LP struct mm_state { - /// The array of pointers to the allocated buddy systems for the LP - dyn_array(struct buddy_state *) buddies; - /// The array of checkpoints - dyn_array(struct mm_log) logs; - /// The total count of allocated bytes - uint_fast32_t full_ckpt_size; + /// The array of pointers to the allocated buddy systems for the LP + dyn_array(struct buddy_state *) buddies; + /// The array of checkpoints + dyn_array(struct mm_log) logs; + /// The total count of allocated bytes + uint_fast32_t full_ckpt_size; }; extern struct buddy_state *buddy_find_by_address(const struct mm_state *self, const void *ptr); diff --git a/src/serial/serial.c b/src/serial/serial.c index 5239813a..effa052d 100644 --- a/src/serial/serial.c +++ b/src/serial/serial.c @@ -125,7 +125,7 @@ static int serial_simulation_run(void) * @param payload_size size of the payload */ void ScheduleNewEvent_serial(const lp_id_t receiver, const simtime_t timestamp, const unsigned event_type, - const void *payload, const unsigned payload_size) + const void *payload, const unsigned payload_size) { struct lp_msg *msg = msg_allocator_pack(receiver, timestamp, event_type, payload, payload_size); diff --git a/src/serial/serial.h b/src/serial/serial.h index 1b8412ea..7efc7d29 100644 --- a/src/serial/serial.h +++ b/src/serial/serial.h @@ -12,4 +12,4 @@ extern int serial_simulation(void); extern void ScheduleNewEvent_serial(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *payload, - unsigned payload_size); + unsigned payload_size); From 1eaf1adc4b5ed144b02008b5815205c5a2aa2357 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Tue, 27 May 2025 18:09:37 +0200 Subject: [PATCH 10/15] Fix erroneous exported function name In the mm refactor, a renamed function was not renamed in the corresponding header. Signed-off-by: Alessandro Pellegrini --- src/mm/buddy/checkpoint.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mm/buddy/checkpoint.h b/src/mm/buddy/checkpoint.h index ab27ae72..48c0fafe 100644 --- a/src/mm/buddy/checkpoint.h +++ b/src/mm/buddy/checkpoint.h @@ -30,8 +30,8 @@ static_assert(offsetof(struct buddy_checkpoint, longest) == offsetof(struct buddy_checkpoint, base_mem) - sizeof(((struct buddy_checkpoint *)0)->longest), "longest and base_mem are not contiguous, this will break incremental checkpointing"); -extern struct buddy_checkpoint *checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *data); -extern const struct buddy_checkpoint *checkpoint_full_restore(struct buddy_state *self, +extern struct buddy_checkpoint *buddy_checkpoint_full_take(const struct buddy_state *self, struct buddy_checkpoint *data); +extern const struct buddy_checkpoint *buddy_checkpoint_full_restore(struct buddy_state *self, const struct buddy_checkpoint *data); #ifdef ROOTSIM_INCREMENTAL From 12ab293ed2e92c0909ff2292f4c247956670fcf9 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Thu, 29 May 2025 14:25:12 +0200 Subject: [PATCH 11/15] Pin actions to full-length SHA This is dumb, because _we_ manage the actions, but yes, our code is waaaay more secure now. Signed-off-by: Alessandro Pellegrini --- .github/workflows/build_and_test.yml | 4 ++-- .github/workflows/code_coverage.yml | 4 ++-- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/doc_coverage.yml | 6 +++--- .github/workflows/reuse_check.yml | 2 +- .github/workflows/update-copyright.yml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index eca4873b..51bbb265 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -33,9 +33,9 @@ jobs: - name: Checkpout repository uses: actions/checkout@v4 - name: Initialize Environment - uses: ROOT-Sim/ci-actions/init@v1.5.3 + uses: ROOT-Sim/ci-actions/init@030cae234d9698712812e888d0d9d13ca8e1814f - name: Build & Test - uses: ROOT-Sim/ci-actions/cmake@v1.5.3 + uses: ROOT-Sim/ci-actions/cmake@030cae234d9698712812e888d0d9d13ca8e1814f with: build-dir: ${{ runner.workspace }}/build cc: ${{ matrix.compiler }} diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 90f7b357..a3955178 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -13,9 +13,9 @@ jobs: - name: Fetch ROOT-Sim repository uses: actions/checkout@v4 - name: Initialize Environment - uses: ROOT-Sim/ci-actions/init@v1.5.3 + uses: ROOT-Sim/ci-actions/init@030cae234d9698712812e888d0d9d13ca8e1814f - name: Build & Test - uses: ROOT-Sim/ci-actions/cmake@v1.5.3 + uses: ROOT-Sim/ci-actions/cmake@030cae234d9698712812e888d0d9d13ca8e1814f with: build-dir: ${{ runner.workspace }}/build cc: gcc diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 636d4b04..acee919c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,9 +31,9 @@ jobs: with: languages: ${{ matrix.language }} - name: Initialize Environment - uses: ROOT-Sim/ci-actions/init@v1.5.3 + uses: ROOT-Sim/ci-actions/init@030cae234d9698712812e888d0d9d13ca8e1814f - name: Build & Test - uses: ROOT-Sim/ci-actions/cmake@v1.5.3 + uses: ROOT-Sim/ci-actions/cmake@030cae234d9698712812e888d0d9d13ca8e1814f with: build-dir: ${{ runner.workspace }}/build cc: clang diff --git a/.github/workflows/doc_coverage.yml b/.github/workflows/doc_coverage.yml index 7c6336d2..dd32cb46 100644 --- a/.github/workflows/doc_coverage.yml +++ b/.github/workflows/doc_coverage.yml @@ -14,13 +14,13 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 - name: Initialize Environment - uses: ROOT-Sim/ci-actions/init@v1.5.3 + uses: ROOT-Sim/ci-actions/init@030cae234d9698712812e888d0d9d13ca8e1814f - name: Generate Documentation - uses: ROOT-Sim/ci-actions/docs@v1.5.3 + uses: ROOT-Sim/ci-actions/docs@030cae234d9698712812e888d0d9d13ca8e1814f with: docs-target: rscore-doc - name: Documentation Coverage - uses: ROOT-Sim/ci-actions/docs-coverage@v1.5.3 + uses: ROOT-Sim/ci-actions/docs-coverage@030cae234d9698712812e888d0d9d13ca8e1814f with: build-path: docs - name: Comment PR diff --git a/.github/workflows/reuse_check.yml b/.github/workflows/reuse_check.yml index b04f5ff1..d8c7c5be 100644 --- a/.github/workflows/reuse_check.yml +++ b/.github/workflows/reuse_check.yml @@ -13,4 +13,4 @@ jobs: - name: Checkpout repository uses: actions/checkout@v4 - name: REUSE check - uses: ROOT-Sim/ci-actions/reuse-check@v1.5.3 + uses: ROOT-Sim/ci-actions/reuse-check@030cae234d9698712812e888d0d9d13ca8e1814f diff --git a/.github/workflows/update-copyright.yml b/.github/workflows/update-copyright.yml index 44b43a5c..34514057 100644 --- a/.github/workflows/update-copyright.yml +++ b/.github/workflows/update-copyright.yml @@ -10,6 +10,6 @@ jobs: steps: - uses: actions/checkout@v4 - name: Update copyright - uses: ROOT-Sim/ci-actions/update-copyright@v1.6 + uses: ROOT-Sim/ci-actions/update-copyright@030cae234d9698712812e888d0d9d13ca8e1814f with: branch-to-update: develop From e9d0b3a40b105ecb396bf0c71478ba265b4b72f5 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Wed, 25 Jun 2025 05:47:10 +0200 Subject: [PATCH 12/15] Avoid clashing with index(3) In stdlib there is the deprecated index(3) function which has been deprecated in favour of strchr(3). Avoid using index as the name of the variable to avoid any possible issues. Signed-off-by: Alessandro Pellegrini --- src/mm/buddy/buddy.c | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/mm/buddy/buddy.c b/src/mm/buddy/buddy.c index f6f92ceb..2abd84b8 100644 --- a/src/mm/buddy/buddy.c +++ b/src/mm/buddy/buddy.c @@ -11,7 +11,7 @@ #include /// Tells if the given index is a power of 2 -#define is_power_of_2(index) (!((index) & ((index) - 1))) +#define is_power_of_2(idx) (!((idx) & ((idx) - 1))) /** * @brief Initializes the buddy system allocator. @@ -25,9 +25,9 @@ void buddy_init(struct buddy_state *self) { uint_fast8_t node_size = B_TOTAL_EXP; - for(uint_fast32_t index = 0; index < sizeof(self->longest) / sizeof(*self->longest); ++index) { - self->longest[index] = node_size; - node_size -= is_power_of_2(index + 2); + for(uint_fast32_t idx = 0; idx < sizeof(self->longest) / sizeof(*self->longest); ++idx) { + self->longest[idx] = node_size; + node_size -= is_power_of_2(idx + 2); } } @@ -50,29 +50,29 @@ void *buddy_malloc(struct buddy_state *self, const uint_fast8_t req_blks_exp) /* search recursively for the child */ uint_fast8_t node_size = B_TOTAL_EXP; - uint_fast32_t index = 0; + uint_fast32_t idx = 0; while(node_size > req_blks_exp) { /* choose the child with smaller longest value which * is still large at least *size* */ - index = buddy_left_child(index); - index += self->longest[index] < req_blks_exp; + idx = buddy_left_child(idx); + idx += self->longest[idx] < req_blks_exp; --node_size; } /* update the *longest* value back */ - self->longest[index] = 0; + self->longest[idx] = 0; #ifdef ROOTSIM_INCREMENTAL - bitmap_set(self->dirty, index >> B_BLOCK_EXP); + bitmap_set(self->dirty, idx >> B_BLOCK_EXP); #endif - const uint_fast32_t offset = ((index + 1) << node_size) - (1 << B_TOTAL_EXP); + const uint_fast32_t offset = ((idx + 1) << node_size) - (1 << B_TOTAL_EXP); - while(index) { - index = buddy_parent(index); - self->longest[index] = - max(self->longest[buddy_left_child(index)], self->longest[buddy_right_child(index)]); + while(idx) { + idx = buddy_parent(idx); + self->longest[idx] = + max(self->longest[buddy_left_child(idx)], self->longest[buddy_right_child(idx)]); #ifdef ROOTSIM_INCREMENTAL - bitmap_set(self->dirty, index >> B_BLOCK_EXP); + bitmap_set(self->dirty, idx >> B_BLOCK_EXP); #endif } @@ -95,15 +95,15 @@ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) { uint_fast8_t node_size = B_BLOCK_EXP; uint_fast32_t offset = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; - uint_fast32_t index = offset + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; + uint_fast32_t idx = offset + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; - for(; self->longest[index]; index = buddy_parent(index)) + for(; self->longest[idx]; idx = buddy_parent(idx)) ++node_size; - self->longest[index] = node_size; + self->longest[idx] = node_size; const uint_fast32_t ret = (uint_fast32_t)1U << node_size; #ifdef ROOTSIM_INCREMENTAL - bitmap_set(self->dirty, index >> B_BLOCK_EXP); + bitmap_set(self->dirty, idx >> B_BLOCK_EXP); uint_fast32_t bitmap_idx = (1 << (node_size - B_BLOCK_EXP)) - 1; offset += (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); @@ -113,16 +113,16 @@ uint_fast32_t buddy_free(struct buddy_state *self, void *ptr) } while(bitmap_idx--); #endif - while(index) { - index = buddy_parent(index); + while(idx) { + idx = buddy_parent(idx); - uint_fast8_t left_long = self->longest[buddy_left_child(index)]; - uint_fast8_t right_long = self->longest[buddy_right_child(index)]; + uint_fast8_t left_long = self->longest[buddy_left_child(idx)]; + uint_fast8_t right_long = self->longest[buddy_right_child(idx)]; if(left_long == node_size && right_long == node_size) { - self->longest[index] = node_size + 1; + self->longest[idx] = node_size + 1; } else { - self->longest[index] = max(left_long, right_long); + self->longest[idx] = max(left_long, right_long); } #ifdef ROOTSIM_INCREMENTAL bitmap_set(self->dirty, i >> B_BLOCK_EXP); @@ -154,9 +154,9 @@ struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *sel { uint_fast8_t node_size = B_BLOCK_EXP; const uint_fast32_t offset = ((uintptr_t)ptr - (uintptr_t)self->base_mem) >> B_BLOCK_EXP; - uint_fast32_t index = offset + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; + uint_fast32_t idx = offset + (1 << (B_TOTAL_EXP - B_BLOCK_EXP)) - 1; - for(; self->longest[index]; index = buddy_parent(index)) + for(; self->longest[idx]; idx = buddy_parent(idx)) ++node_size; const uint_fast8_t req_blks_exp = buddy_allocation_block_compute(req_size); @@ -192,13 +192,13 @@ struct buddy_realloc_res buddy_best_effort_realloc(const struct buddy_state *sel void buddy_dirty_mark(const struct buddy_state *self, const void *ptr, size_t size) { const uintptr_t diff = (unsigned char *)ptr - (unsigned char *)self->base_mem; - const uint_fast32_t index = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); + const uint_fast32_t idx = (diff >> B_BLOCK_EXP) + (1 << (B_TOTAL_EXP - 2 * B_BLOCK_EXP + 1)); size += diff & ((1 << B_BLOCK_EXP) - 1); --size; size >>= B_BLOCK_EXP; do { - bitmap_set(self->dirty, index + size); + bitmap_set(self->dirty, idx + size); } while(size--); } From 63ed7ec4ae1ccfcdd6e866687297e41d2f4d29ee Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Wed, 25 Jun 2025 05:48:00 +0200 Subject: [PATCH 13/15] Fix documentation Fix wrong documentation. Signed-off-by: Alessandro Pellegrini --- src/lp/process.h | 8 ++++---- src/mm/buddy/checkpoint.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lp/process.h b/src/lp/process.h index d9548666..46778dc0 100644 --- a/src/lp/process.h +++ b/src/lp/process.h @@ -17,11 +17,11 @@ struct process_ctx { /// The messages processed in the past by the owner LP dyn_array(struct lp_msg *) p_msgs; - /// The list of remote anti-messages delivered before their original counterpart - /** Hopefully this is 99.9% of the time empty */ + /** The list of remote anti-messages delivered before their original counterpart. + * Hopefully this is 99.9% of the time empty */ struct lp_msg *early_antis; - /// The current logical time at which this LP is - /** This is lazily updated and not always accurate; it's sufficient for faster straggler detection */ + /** The current logical time at which this LP is. This is lazily updated and not always accurate; + * it's sufficient for faster straggler detection */ simtime_t bound; }; diff --git a/src/mm/buddy/checkpoint.c b/src/mm/buddy/checkpoint.c index 39c87041..f3cb9124 100644 --- a/src/mm/buddy/checkpoint.c +++ b/src/mm/buddy/checkpoint.c @@ -12,13 +12,13 @@ /** - * @brief Traverses the buddy tree and performs an action on each unallocated block. + * @brief Traverses the buddy tree and performs an action on each allocated block. * * This macro iterates over the buddy tree represented by the `longest` array and - * invokes the provided `on_visit` action for each unallocated memory block. + * invokes the provided `on_visit` action for each allocated memory block. * * @param longest The array representing the buddy tree. - * @param on_visit A callback action to perform on each unallocated block. The callback + * @param on_visit A callback action to perform on each allocated block. The callback * receives two parameters: * - `offset`: The offset of the block in the memory buffer. * - `length`: The size of the block. From a4d016c1a575bba77997a1e97b38057e46eceba5 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Wed, 25 Jun 2025 05:52:37 +0200 Subject: [PATCH 14/15] Fix incorrect parameter name I confused by mistake the message processing data with an LP context. This is fixed, and the arguments names are made consistent in the code base. Signed-off-by: Alessandro Pellegrini --- src/lp/process.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/lp/process.c b/src/lp/process.c index a9d050e8..965430a9 100644 --- a/src/lp/process.c +++ b/src/lp/process.c @@ -183,14 +183,14 @@ static inline void silent_execution(const struct lp_ctx *lp, array_count_t last_ /** * @brief Send anti-messages - * @param lp the message processing data for the LP that has to send anti-messages + * @param msg_processing the message processing data for the LP that has to send anti-messages * @param past_i the index in @a proc_p of the last validly processed message */ -static inline void send_anti_messages(struct process_ctx *lp, const array_count_t past_i) +static inline void send_anti_messages(struct process_ctx *msg_processing, const array_count_t past_i) { - const array_count_t p_cnt = array_count(lp->p_msgs); + const array_count_t p_cnt = array_count(msg_processing->p_msgs); for(array_count_t i = past_i; i < p_cnt; ++i) { - struct lp_msg *msg = array_get_at(lp->p_msgs, i); + struct lp_msg *msg = array_get_at(msg_processing->p_msgs, i); while(is_msg_sent(msg)) { if(is_msg_remote(msg)) { @@ -207,7 +207,7 @@ static inline void send_anti_messages(struct process_ctx *lp, const array_count_ } stats_take(STATS_MSG_ANTI, 1); - msg = array_get_at(lp->p_msgs, ++i); + msg = array_get_at(msg_processing->p_msgs, ++i); } const uint32_t f = atomic_fetch_add_explicit(&msg->flags, -MSG_FLAG_PROCESSED, memory_order_relaxed); @@ -215,7 +215,7 @@ static inline void send_anti_messages(struct process_ctx *lp, const array_count_ msg_queue_insert_self(msg); stats_take(STATS_MSG_ROLLBACK, 1); } - array_count(lp->p_msgs) = past_i; + array_count(msg_processing->p_msgs) = past_i; } /** @@ -235,37 +235,37 @@ static void do_rollback(struct lp_ctx *lp, const array_count_t past_i) /** * @brief Find the last valid processed message with respect to a straggler message - * @param proc_p the message processing data for the LP + * @param msg_processing the message processing data for the LP * @param s_msg the straggler message * @return the index in @a proc_p of the last validly processed message */ -static inline array_count_t match_straggler_msg(const struct process_ctx *proc_p, const struct lp_msg *s_msg) +static inline array_count_t match_straggler_msg(const struct process_ctx *msg_processing, const struct lp_msg *s_msg) { - array_count_t i = array_count(proc_p->p_msgs) - 1; + array_count_t i = array_count(msg_processing->p_msgs) - 1; const struct lp_msg *msg; do { if(!i) return 0; - msg = array_get_at(proc_p->p_msgs, --i); + msg = array_get_at(msg_processing->p_msgs, --i); } while(is_msg_sent(msg) || msg_is_before(s_msg, msg)); return i + 1; } /** * @brief Find the last valid processed message with respect to a received anti-message - * @param proc_p the message processing data for the LP + * @param msg_processing the message processing data for the LP * @param a_msg the anti-message * @return the index in @a proc_p of the last validly processed message */ -static inline array_count_t match_anti_msg(const struct process_ctx *proc_p, const struct lp_msg *a_msg) +static inline array_count_t match_anti_msg(const struct process_ctx *msg_processing, const struct lp_msg *a_msg) { - array_count_t i = array_count(proc_p->p_msgs) - 1; - const struct lp_msg *msg = array_get_at(proc_p->p_msgs, i); + array_count_t i = array_count(msg_processing->p_msgs) - 1; + const struct lp_msg *msg = array_get_at(msg_processing->p_msgs, i); while(a_msg != msg) - msg = array_get_at(proc_p->p_msgs, --i); + msg = array_get_at(msg_processing->p_msgs, --i); while(i) { - msg = array_get_at(proc_p->p_msgs, --i); + msg = array_get_at(msg_processing->p_msgs, --i); if(is_msg_past(msg)) return i + 1; } @@ -312,14 +312,14 @@ static inline void handle_remote_anti_msg(struct lp_ctx *lp, struct lp_msg *a_ms /** * @brief Check if a remote message has already been invalidated by an early remote anti-message - * @param proc_p the message processing data of the current LP + * @param msg_processing the message processing data of the current LP * @param msg the remote message to check * @return true if the message has been matched with an early remote anti-message, false otherwise */ -static inline bool check_early_anti_messages(struct process_ctx *proc_p, struct lp_msg *msg) +static inline bool check_early_anti_messages(struct process_ctx *msg_processing, struct lp_msg *msg) { const uint32_t m_id = msg->raw_flags, m_seq = msg->m_seq; - struct lp_msg **prev_p = &proc_p->early_antis; + struct lp_msg **prev_p = &msg_processing->early_antis; struct lp_msg *a_msg = *prev_p; do { if(a_msg->raw_flags == m_id && a_msg->m_seq == m_seq) { From 3985d96af5102abebc1f71b59960ab626fb38ed6 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Wed, 25 Jun 2025 05:54:04 +0200 Subject: [PATCH 15/15] Make consistent the include order This is made to align to the project conventions. Signed-off-by: Alessandro Pellegrini --- src/mm/model_allocator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mm/model_allocator.c b/src/mm/model_allocator.c index 3c93edd2..0cfc8dfc 100644 --- a/src/mm/model_allocator.c +++ b/src/mm/model_allocator.c @@ -6,8 +6,7 @@ * SPDX-FileCopyrightText: 2008-2025 HPCS Group * SPDX-License-Identifier: GPL-3.0-only */ -#include -#include +#include #include #include @@ -15,6 +14,7 @@ #include #include +#include /** * @brief Initializes the memory management state for a logical process.