Line data Source code
1 1 : /**
2 : * @file gvt/fossil.c
3 : *
4 : * @brief Housekeeping operations
5 : *
6 : * In this module all the housekeeping operations related to GVT computation phase
7 : * are present.
8 : *
9 : * @copyright
10 : * Copyright (C) 2008-2019 HPDCS Group
11 : * https://hpdcs.github.io
12 : *
13 : * This file is part of ROOT-Sim (ROme OpTimistic Simulator).
14 : *
15 : * ROOT-Sim is free software; you can redistribute it and/or modify it under the
16 : * terms of the GNU General Public License as published by the Free Software
17 : * Foundation; only version 3 of the License applies.
18 : *
19 : * ROOT-Sim is distributed in the hope that it will be useful, but WITHOUT ANY
20 : * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
21 : * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22 : *
23 : * You should have received a copy of the GNU General Public License along with
24 : * ROOT-Sim; if not, write to the Free Software Foundation, Inc.,
25 : * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 : *
27 : * @author Alessandro Pellegrini
28 : * @author Francesco Quaglia
29 : */
30 :
31 : #include <arch/thread.h>
32 : #include <core/init.h>
33 : #include <gvt/gvt.h>
34 : #include <gvt/ccgs.h>
35 : #include <mm/state.h>
36 : #include <mm/mm.h>
37 : #include <scheduler/process.h>
38 : #include <scheduler/scheduler.h>
39 : #include <statistics/statistics.h>
40 :
41 : /// Counter for the invocations of adopt_new_gvt. This is used to determine whether a consistent state must be reconstructed
42 1 : static unsigned long long snapshot_cycles;
43 :
44 : /**
45 : * Determine which snapshots in the state queue can be free'd because are placed before the current time barrier.
46 : *
47 : * Queues are cleaned by deleting all the events the timestamp of which is STRICTLY lower than the time barrier.
48 : * Since state_pointer points to an event in queue_in, the state queue must be cleaned after the input queue.
49 : *
50 : * @param lp A pointer to the lp_struct for which we want to recollect memory
51 : * @param time_barrier The current barrier
52 : */
53 1 : void fossil_collection(struct lp_struct *lp, simtime_t time_barrier)
54 : {
55 : state_t *state;
56 : msg_t *last_kept_event;
57 : double committed_events;
58 :
59 : // State list must be handled specifically, as nodes point to malloc'd
60 : // nodes. We therefore manually scan the list and free the memory.
61 : while ((state = list_head(lp->queue_states)) != NULL
62 : && state->lvt < time_barrier) {
63 : log_delete(state->log);
64 : if(&topology_settings && topology_settings.write_enabled)
65 : rsfree(state->topology);
66 : if(&abm_settings)
67 : rsfree(state->region_data);
68 : #ifndef NDEBUG
69 : state->last_event = (void *)0xDEADBABE;
70 : #endif
71 : list_pop(lp->queue_states);
72 : }
73 :
74 : // Determine queue pruning horizon
75 : state = list_head(lp->queue_states);
76 : last_kept_event = state->last_event;
77 :
78 : // Truncate the input queue, accounting for the event which is pointed by the lastly kept state
79 : committed_events =
80 : (double)list_trunc(lp->queue_in, timestamp,
81 : last_kept_event->timestamp, msg_release);
82 : statistics_post_data(lp, STAT_COMMITTED, committed_events);
83 :
84 : // Truncate the output queue
85 : list_trunc(lp->queue_out, send_time, last_kept_event->timestamp,
86 : msg_hdr_release);
87 : }
88 :
89 : /**
90 : * This function is used by Master and Slave Kernels to determine the time barrier
91 : * and perform some housekeeping once the new GVT value has been computed.
92 : *
93 : * @param new_gvt This is a new GVT value which has been computed and can be used
94 : * to perform fossil collection and to activate CCGS
95 : */
96 1 : void adopt_new_gvt(simtime_t new_gvt)
97 : {
98 : unsigned int i;
99 :
100 : state_t *time_barrier_pointer[n_prc_per_thread];
101 : bool compute_snapshot;
102 :
103 : // Snapshot should be recomputed only periodically
104 : snapshot_cycles++;
105 : compute_snapshot =
106 : ((snapshot_cycles % rootsim_config.gvt_snapshot_cycles) == 0);
107 :
108 : // Precompute the time barrier for each process
109 : i = 0;
110 : foreach_bound_lp(lp) {
111 : time_barrier_pointer[i++] = find_time_barrier(lp, new_gvt);
112 : }
113 :
114 : // If needed, call the CCGS subsystem
115 : if (compute_snapshot)
116 : ccgs_compute_snapshot(time_barrier_pointer, new_gvt);
117 :
118 : i = 0;
119 : foreach_bound_lp(lp) {
120 : if (time_barrier_pointer[i] == NULL)
121 : continue;
122 :
123 : // Execute the fossil collection
124 : fossil_collection(lp, time_barrier_pointer[i]->lvt);
125 :
126 : // Actually release memory buffer allocated by the LPs and then released via free() calls
127 : clean_buffers_on_gvt(lp, time_barrier_pointer[i]->lvt);
128 :
129 : i++;
130 : }
131 : }
|