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/mm.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 
84  // Timers for self-tuning of the simulation platform
85  timer checkpoint_timer;
86  timer_start(checkpoint_timer);
87 
88  lp->mm->m_state->is_incremental = false;
89  size = get_log_size(lp->mm->m_state);
90 
91  ckpt = rsalloc(size);
92 
93  if (unlikely(ckpt == NULL)) {
94  rootsim_error(true, "(%d) Unable to acquire memory for checkpointing the current state (memory exhausted?)", lp->lid.to_int);
95  }
96 
97  ptr = ckpt;
98 
99  // Copy malloc_state in the ckpt
100  memcpy(ptr, lp->mm->m_state, sizeof(malloc_state));
101  ptr = (void *)((char *)ptr + sizeof(malloc_state));
102  ((malloc_state *) ckpt)->timestamp = lvt(lp);
103 
104  for (i = 0; i < lp->mm->m_state->num_areas; i++) {
105 
106  m_area = &lp->mm->m_state->areas[i];
107 
108  // Copy the bitmap
109 
110  bitmap_size = bitmap_required_size(m_area->num_chunks);
111 
112  // Check if there is at least one chunk used in the area
113  if (unlikely(m_area->alloc_chunks == 0)) {
114 
115  m_area->dirty_chunks = 0;
116  m_area->state_changed = 0;
117 
118  if (likely(m_area->use_bitmap != NULL)) {
119  memset(m_area->dirty_bitmap, 0, bitmap_size);
120  }
121 
122  continue;
123  }
124  // Copy malloc_area into the ckpt
125  memcpy(ptr, m_area, sizeof(malloc_area));
126  ptr = (void *)((char *)ptr + sizeof(malloc_area));
127 
128  memcpy(ptr, m_area->use_bitmap, bitmap_size);
129  ptr = (void *)((char *)ptr + bitmap_size);
130 
131  chunk_size = UNTAGGED_CHUNK_SIZE(m_area);
132 
133  // Check whether the area should be completely copied (not on a per-chunk basis)
134  // using a threshold-based heuristic
135  if (CHECK_LOG_MODE_BIT(m_area)) {
136 
137  // If the malloc_area is almost (over a threshold) full, copy it entirely
138  memcpy(ptr, m_area->area, m_area->num_chunks * chunk_size);
139  ptr = (void *)((char *)ptr + m_area->num_chunks * chunk_size);
140 
141  } else {
142 
143 #define copy_from_area(x) ({\
144  memcpy(ptr, (void*)((char*)m_area->area + ((x) * chunk_size)), chunk_size);\
145  ptr = (void*)((char*)ptr + chunk_size);})
146 
147  // Copy only the allocated chunks
148  bitmap_foreach_set(m_area->use_bitmap, bitmap_size, copy_from_area);
149 
150 #undef copy_from_area
151  }
152 
153  // Reset Dirty Bitmap, as there is a full ckpt in the chain now
154  m_area->dirty_chunks = 0;
155  m_area->state_changed = 0;
156  bzero((void *)m_area->dirty_bitmap, bitmap_size);
157 
158  } // For each malloc area
159 
160  // Sanity check
161  if (unlikely((char *)ckpt + size != ptr))
162  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",
163  (char *)ckpt + size - (char *)ptr, lp->lid.to_int,
164  ckpt, size, size, ptr, (char *)ckpt + size);
165 
166  lp->mm->m_state->dirty_areas = 0;
167  lp->mm->m_state->dirty_bitmap_size = 0;
168  lp->mm->m_state->total_inc_size = 0;
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  void *ptr;
228  int i, original_num_areas, restored_areas;
229  size_t chunk_size, bitmap_size;
230  malloc_area *m_area, *new_area;
231 
232  // Timers for simulation platform self-tuning
233  timer recovery_timer;
234  timer_start(recovery_timer);
235  restored_areas = 0;
236  ptr = ckpt;
237  original_num_areas = lp->mm->m_state->num_areas;
238  new_area = lp->mm->m_state->areas;
239 
240  // Restore malloc_state
241  memcpy(lp->mm->m_state, ptr, sizeof(malloc_state));
242  ptr = (void *)((char *)ptr + sizeof(malloc_state));
243 
244  lp->mm->m_state->areas = new_area;
245 
246  // Scan areas and chunk to restore them
247  for (i = 0; i < lp->mm->m_state->num_areas; i++) {
248 
249  m_area = &lp->mm->m_state->areas[i];
250 
251  bitmap_size = bitmap_required_size(m_area->num_chunks);
252 
253  if (restored_areas == lp->mm->m_state->busy_areas || m_area->idx != ((malloc_area *) ptr)->idx) {
254 
255  m_area->dirty_chunks = 0;
256  m_area->state_changed = 0;
257  m_area->alloc_chunks = 0;
258  m_area->next_chunk = 0;
259  RESET_LOG_MODE_BIT(m_area);
260  RESET_AREA_LOCK_BIT(m_area);
261 
262  if (likely(m_area->use_bitmap != NULL)) {
263  memset(m_area->use_bitmap, 0, bitmap_size);
264  memset(m_area->dirty_bitmap, 0, bitmap_size);
265  }
266  m_area->last_access = lp->mm->m_state->timestamp;
267 
268  continue;
269  }
270  // Restore the malloc_area
271  memcpy(m_area, ptr, sizeof(malloc_area));
272  ptr = (void *)((char *)ptr + sizeof(malloc_area));
273 
274  restored_areas++;
275 
276  // Restore use bitmap
277  memcpy(m_area->use_bitmap, ptr, bitmap_size);
278  ptr = (void *)((char *)ptr + bitmap_size);
279 
280  // Reset dirty bitmap
281  bzero(m_area->dirty_bitmap, bitmap_size);
282  m_area->dirty_chunks = 0;
283  m_area->state_changed = 0;
284 
285  chunk_size = UNTAGGED_CHUNK_SIZE(m_area);
286 
287  // Check how the area has been logged
288  if (CHECK_LOG_MODE_BIT(m_area)) {
289  // The area has been entirely logged
290  memcpy(m_area->area, ptr, m_area->num_chunks * chunk_size);
291  ptr = (void *)((char *)ptr + m_area->num_chunks * chunk_size);
292 
293  } else {
294  // The area was partially logged.
295  // Logged chunks are the ones associated with a used bit whose value is 1
296  // Their number is in the alloc_chunks counter
297 
298 #define copy_to_area(x) ({\
299  memcpy((void*)((char*)m_area->area + ((x) * chunk_size)), ptr, chunk_size);\
300  ptr = (void*)((char*)ptr + chunk_size);})
301 
302  bitmap_foreach_set(m_area->use_bitmap, bitmap_size, copy_to_area);
303 
304 #undef copy_to_area
305  }
306 
307  }
308 
309  // Check whether there are more allocated areas which are not present in the log
310  if (original_num_areas > lp->mm->m_state->num_areas) {
311 
312  for (i = lp->mm->m_state->num_areas; i < original_num_areas; i++) {
313 
314  m_area = &lp->mm->m_state->areas[i];
315  m_area->alloc_chunks = 0;
316  m_area->dirty_chunks = 0;
317  m_area->state_changed = 0;
318  m_area->next_chunk = 0;
319  m_area->last_access = lp->mm->m_state->timestamp;
320  lp->mm->m_state->areas[m_area->prev].next = m_area->idx;
321 
322  RESET_LOG_MODE_BIT(m_area);
323  RESET_AREA_LOCK_BIT(m_area);
324 
325  if (likely(m_area->use_bitmap != NULL)) {
326  bitmap_size = bitmap_required_size(m_area->num_chunks);
327 
328  memset(m_area->use_bitmap, 0, bitmap_size);
329  memset(m_area->dirty_bitmap, 0, bitmap_size);
330  }
331  }
332  lp->mm->m_state->num_areas = original_num_areas;
333  }
334 
335  lp->mm->m_state->timestamp = -1;
336  lp->mm->m_state->is_incremental = false;
337  lp->mm->m_state->dirty_areas = 0;
338  lp->mm->m_state->dirty_bitmap_size = 0;
339  lp->mm->m_state->total_inc_size = 0;
340 
341  statistics_post_data(lp, STAT_RECOVERY_TIME, (double)timer_value_micro(recovery_timer));
342 }
343 
358 void log_restore(struct lp_struct *lp, state_t *state_queue_node)
359 {
360  statistics_post_data(lp, STAT_RECOVERY, 1.0);
361  restore_full(lp, state_queue_node->log);
362 }
363 
374 void log_delete(void *ckpt)
375 {
376  if (likely(ckpt != NULL)) {
377  rsfree(ckpt);
378  }
379 }
#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:374
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
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:358
bool is_incremental
Tells if it is an incremental log or a full one (when used for logging)
Definition: dymelor.h:120
void * log_state(struct lp_struct *lp)
Definition: checkpoints.c:195
Memory Manager main header.
void * log
A pointer to the actual log.
Definition: state.h:57
LP control blocks.
Definition of the memory map.
Definition: dymelor.h:119
LID_t lid
Local ID of the LP.
Definition: process.h:79
size_t get_log_size(malloc_state *logged_state)
Definition: dymelor.c:534
#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:96