The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
checkpoints.c
Go to the documentation of this file.
1 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <fcntl.h>
34 
35 #include <mm/dymelor.h>
36 #include <core/timer.h>
37 #include <core/core.h>
38 #include <scheduler/scheduler.h>
39 #include <scheduler/process.h>
40 #include <statistics/statistics.h>
41 
76 void *log_full(struct lp_struct *lp)
77 {
78 
79  void *ptr = NULL, *ckpt = NULL;
80  int i;
81  size_t size, chunk_size, bitmap_size;
82  malloc_area *m_area;
83  malloc_state *m_state;
84 
85  // Timers for self-tuning of the simulation platform
86  timer checkpoint_timer;
87  timer_start(checkpoint_timer);
88 
89  m_state = lp->mm->m_state;
90  m_state->is_incremental = false;
91  size = get_log_size(m_state);
92 
93  ckpt = rsalloc(size);
94 
95  if (unlikely(ckpt == NULL)) {
96  rootsim_error(true, "(%d) Unable to acquire memory for checkpointing the current state (memory exhausted?)", lp->lid.to_int);
97  }
98 
99  ptr = ckpt;
100 
101  // Copy malloc_state in the ckpt
102  memcpy(ptr, m_state, sizeof(malloc_state));
103  ptr = (void *)((char *)ptr + sizeof(malloc_state));
104  ((malloc_state *) ckpt)->timestamp = lvt(lp);
105 
106  for (i = 0; i < m_state->num_areas; i++) {
107 
108  m_area = &m_state->areas[i];
109 
110  // Copy the bitmap
111 
112  bitmap_size = bitmap_required_size(m_area->num_chunks);
113 
114  // Check if there is at least one chunk used in the area
115  if (unlikely(m_area->alloc_chunks == 0)) {
116 
117  m_area->dirty_chunks = 0;
118  m_area->state_changed = 0;
119 
120  if (likely(m_area->use_bitmap != NULL)) {
121  memset(m_area->dirty_bitmap, 0, bitmap_size);
122  }
123 
124  continue;
125  }
126  // Copy malloc_area into the ckpt
127  memcpy(ptr, m_area, sizeof(malloc_area));
128  ptr = (void *)((char *)ptr + sizeof(malloc_area));
129 
130  memcpy(ptr, m_area->use_bitmap, bitmap_size);
131  ptr = (void *)((char *)ptr + bitmap_size);
132 
133  chunk_size = UNTAGGED_CHUNK_SIZE(m_area);
134 
135  // Check whether the area should be completely copied (not on a per-chunk basis)
136  // using a threshold-based heuristic
137  if (CHECK_LOG_MODE_BIT(m_area)) {
138 
139  // If the malloc_area is almost (over a threshold) full, copy it entirely
140  memcpy(ptr, m_area->area, m_area->num_chunks * chunk_size);
141  ptr = (void *)((char *)ptr + m_area->num_chunks * chunk_size);
142 
143  } else {
144 
145 #define copy_from_area(x) ({\
146  memcpy(ptr, (void*)((char*)m_area->area + ((x) * chunk_size)), chunk_size);\
147  ptr = (void*)((char*)ptr + chunk_size);})
148 
149  // Copy only the allocated chunks
150  bitmap_foreach_set(m_area->use_bitmap, bitmap_size, copy_from_area);
151 
152 #undef copy_from_area
153  }
154 
155  // Reset Dirty Bitmap, as there is a full ckpt in the chain now
156  m_area->dirty_chunks = 0;
157  m_area->state_changed = 0;
158  bzero(m_area->dirty_bitmap, bitmap_size);
159 
160  } // For each malloc area
161 
162  // Sanity check
163  if (unlikely((char *)ckpt + size != ptr))
164  rootsim_error(true, "Actual (full) ckpt size is wrong by %d bytes!\nlid = %d ckpt = %p size = %#x (%d), ptr = %p, ckpt + size = %p\n",
165  (char *)ckpt + size - (char *)ptr, lp->lid.to_int,
166  ckpt, size, size, ptr, (char *)ckpt + size);
167 
168  m_state->total_inc_size = sizeof(malloc_state);
169 
170  statistics_post_data(lp, STAT_CKPT_TIME, (double)timer_value_micro(checkpoint_timer));
171  statistics_post_data(lp, STAT_CKPT_MEM, (double)size);
172 
173  return ckpt;
174 }
175 
195 void *log_state(struct lp_struct *lp)
196 {
197  statistics_post_data(lp, STAT_CKPT, 1.0);
198  return log_full(lp);
199 }
200 
225 void restore_full(struct lp_struct *lp, void *ckpt)
226 {
227  char *ptr, *target_ptr;
228  int i, original_num_areas;
229  size_t chunk_size, bitmap_size;
230  malloc_area *m_area;
231  malloc_state *m_state;
232 
233  // Timers for simulation platform self-tuning
234  timer recovery_timer;
235  timer_start(recovery_timer);
236  ptr = ckpt;
237  m_state = lp->mm->m_state;
238  target_ptr = ptr + ((malloc_state *) ptr)->total_log_size;
239  original_num_areas = m_state->num_areas;
240 
241  // restore the old malloc state except for the malloc areas array
242  m_area = m_state->areas;
243  memcpy(m_state, ptr, sizeof(malloc_state));
244  m_state->areas = m_area;
245  ptr += sizeof(malloc_state);
246 
247  // Scan areas and chunk to restore them
248  for (i = 0; i < m_state->num_areas; i++) {
249 
250  m_area = &m_state->areas[i];
251 
252  bitmap_size = bitmap_required_size(m_area->num_chunks);
253 
254  if (ptr >= target_ptr || m_area->idx != ((malloc_area *) ptr)->idx) {
255 
256  m_area->dirty_chunks = 0;
257  m_area->state_changed = 0;
258  m_area->alloc_chunks = 0;
259  m_area->next_chunk = 0;
260  RESET_LOG_MODE_BIT(m_area);
261  RESET_AREA_LOCK_BIT(m_area);
262 
263  if (likely(m_area->use_bitmap != NULL)) {
264  memset(m_area->use_bitmap, 0, bitmap_size);
265  memset(m_area->dirty_bitmap, 0, bitmap_size);
266  }
267  m_area->last_access = m_state->timestamp;
268 
269  continue;
270  }
271  // Restore the malloc_area
272  memcpy(m_area, ptr, sizeof(malloc_area));
273  ptr += sizeof(malloc_area);
274 
275  // Restore use bitmap
276  memcpy(m_area->use_bitmap, ptr, bitmap_size);
277  ptr += bitmap_size;
278 
279  // Reset dirty bitmap
280  bzero(m_area->dirty_bitmap, bitmap_size);
281  m_area->dirty_chunks = 0;
282  m_area->state_changed = 0;
283 
284  chunk_size = UNTAGGED_CHUNK_SIZE(m_area);
285 
286  // Check how the area has been logged
287  if (CHECK_LOG_MODE_BIT(m_area)) {
288  // The area has been entirely logged
289  memcpy(m_area->area, ptr, m_area->num_chunks * chunk_size);
290  ptr += m_area->num_chunks * chunk_size;
291 
292  } else {
293  // The area was partially logged.
294  // Logged chunks are the ones associated with a used bit whose value is 1
295  // Their number is in the alloc_chunks counter
296 
297 #define copy_to_area(x) ({\
298  memcpy((void*)((char*)m_area->area + ((x) * chunk_size)), ptr, chunk_size);\
299  ptr += chunk_size;})
300 
301  bitmap_foreach_set(m_area->use_bitmap, bitmap_size, copy_to_area);
302 
303 #undef copy_to_area
304  }
305 
306  }
307 
308  // Check whether there are more allocated areas which are not present in the log
309  if (original_num_areas > m_state->num_areas) {
310 
311  for (i = m_state->num_areas; i < original_num_areas; i++) {
312 
313  m_area = &m_state->areas[i];
314  m_area->alloc_chunks = 0;
315  m_area->dirty_chunks = 0;
316  m_area->state_changed = 0;
317  m_area->next_chunk = 0;
318  m_area->last_access = m_state->timestamp;
319  m_state->areas[m_area->prev].next = m_area->idx;
320 
321  RESET_LOG_MODE_BIT(m_area);
322  RESET_AREA_LOCK_BIT(m_area);
323 
324  if (likely(m_area->use_bitmap != NULL)) {
325  bitmap_size = bitmap_required_size(m_area->num_chunks);
326 
327  memset(m_area->use_bitmap, 0, bitmap_size);
328  memset(m_area->dirty_bitmap, 0, bitmap_size);
329  }
330  }
331  m_state->num_areas = original_num_areas;
332  }
333 
334  m_state->timestamp = -1;
335  m_state->is_incremental = false;
336  m_state->total_inc_size = sizeof(malloc_state);
337 
338  statistics_post_data(lp, STAT_RECOVERY_TIME, (double)timer_value_micro(recovery_timer));
339 }
340 
355 void log_restore(struct lp_struct *lp, state_t *state_queue_node)
356 {
357  statistics_post_data(lp, STAT_RECOVERY, 1.0);
358  restore_full(lp, state_queue_node->log);
359 }
360 
371 void log_delete(void *ckpt)
372 {
373  if (likely(ckpt != NULL)) {
374  rsfree(ckpt);
375  }
376 }
#define lvt(lp)
Definition: process.h:168
#define likely(exp)
Optimize the branch as likely taken.
Definition: core.h:72
Structure for LP&#39;s state.
Definition: state.h:49
void log_delete(void *ckpt)
Definition: checkpoints.c:371
Core ROOT-Sim functionalities.
#define bitmap_required_size(requested_bits)
Computes the required size of a bitmap with requested_bits entries.
Definition: bitmap.h:92
Dynamic Memory Logger and Restorer (DyMeLoR)
unsigned int to_int
The LID numerical value.
Definition: core.h:145
Timers.
Statistics module.
The ROOT-Sim scheduler main module header.
struct memory_map * mm
Memory map of the LP.
Definition: process.h:76
void log_restore(struct lp_struct *lp, state_t *state_queue_node)
Definition: checkpoints.c:355
bool is_incremental
Tells if it is an incremental log or a full one (when used for logging)
Definition: dymelor.h:121
void * log_state(struct lp_struct *lp)
Definition: checkpoints.c:195
void * log
A pointer to the actual log.
Definition: state.h:57
LP control blocks.
Definition of the memory map.
Definition: dymelor.h:120
LID_t lid
Local ID of the LP.
Definition: process.h:79
size_t get_log_size(malloc_state *logged_state)
Definition: dymelor.c:526
#define bitmap_foreach_set(bitmap, bitmap_size, func)
This executes a user supplied function for each set bit in bitmap.
Definition: bitmap.h:192
void * log_full(struct lp_struct *lp)
Definition: checkpoints.c:76
void restore_full(struct lp_struct *lp, void *ckpt)
Definition: checkpoints.c:225
#define unlikely(exp)
Optimize the branch as likely not taken.
Definition: core.h:74
This structure let DyMeLoR handle one malloc area (for serving given-size memory requests) ...
Definition: dymelor.h:97