Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
33f670c84ec8dbe81d616d1395e561703db1b0f9
[simgrid.git] / src / mc / mc_snapshot.c
1 /* Copyright (c) 2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <stdbool.h>
8
9 #include "mc_private.h"
10 #include "mc_mmu.h"
11
12 mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot)
13 {
14   for (size_t i = 0; i != NB_REGIONS; ++i) {
15     mc_mem_region_t region = snapshot->regions[i];
16     void* start = region->start_addr;
17     void* end = (char*) start + region->size;
18
19     if (addr >= start && addr < end) {
20       return region;
21     }
22   }
23
24   return NULL;
25 }
26
27 void* mc_translate_address_region(uintptr_t addr, mc_mem_region_t region)
28 {
29   xbt_assert(mc_region_contain(region, (void*) addr), "Trying to read out of the region boundary.");
30
31   if (!region) {
32     return (void *) addr;
33   }
34
35   // Flat snapshot:
36   else if (region->data) {
37     uintptr_t offset = addr - (uintptr_t) region->start_addr;
38     return (void *) ((uintptr_t) region->data + offset);
39   }
40
41   // Per-page snapshot:
42   else if (region->page_numbers) {
43     size_t pageno = mc_page_number(region->start_addr, (void*) addr);
44     size_t snapshot_pageno = region->page_numbers[pageno];
45     const void* snapshot_page = mc_page_store_get_page(mc_model_checker->pages, snapshot_pageno);
46     return (char*) snapshot_page + mc_page_offset((void*) addr);
47   }
48
49   else {
50     xbt_die("No data for this memory region");
51   }
52 }
53
54 void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot)
55 {
56
57   // If not in a process state/clone:
58   if (!snapshot) {
59     return (uintptr_t *) addr;
60   }
61
62   mc_mem_region_t region = mc_get_snapshot_region((void*) addr, snapshot);
63   return mc_translate_address_region(addr, region);
64 }
65
66 /** @brief Read memory from a snapshot region broken across fragmented pages
67  *
68  *  @param addr    Process (non-snapshot) address of the data
69  *  @param region  Snapshot memory region where the data is located
70  *  @param target  Buffer to store the value
71  *  @param size    Size of the data to read in bytes
72  *  @return Pointer where the data is located (target buffer of original location)
73  */
74 static void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size)
75 {
76   void* end = (char*) addr + size - 1;
77   size_t page_end = mc_page_number(NULL, end);
78   void* dest = target;
79
80   // Read each page:
81   while (mc_page_number(NULL, addr) != page_end) {
82     void* snapshot_addr = mc_translate_address_region((uintptr_t) addr, region);
83     void* next_page = mc_page_from_number(NULL, mc_page_number(NULL, addr) + 1);
84     size_t readable = (char*) next_page - (char*) addr;
85     memcpy(dest, snapshot_addr, readable);
86     addr = (char*) addr + readable;
87     dest = (char*) dest + readable;
88     size -= readable;
89   }
90
91   // Read the end:
92   void* snapshot_addr = mc_translate_address_region((uintptr_t)addr, region);
93   memcpy(dest, snapshot_addr, size);
94
95   return target;
96 }
97
98 /** @brief Read memory from a snapshot region
99  *
100  *  @param addr    Process (non-snapshot) address of the data
101  *  @param region  Snapshot memory region where the data is located
102  *  @param target  Buffer to store the value
103  *  @param size    Size of the data to read in bytes
104  *  @return Pointer where the data is located (target buffer of original location)
105  */
106 void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target, size_t size)
107 {
108   uintptr_t offset = (uintptr_t) addr - (uintptr_t) region->start_addr;
109
110   xbt_assert(addr >= region->start_addr && (char*) addr+size < (char*)region->start_addr+region->size,
111     "Trying to read out of the region boundary.");
112
113   // Linear memory region:
114   if (region->data) {
115     return (void*) ((uintptr_t) region->data + offset);
116   }
117
118   // Fragmented memory region:
119   else if (region->page_numbers) {
120     void* end = (char*) addr + size - 1;
121     if( mc_same_page(addr, end) ) {
122       // The memory is contained in a single page:
123       return mc_translate_address_region((uintptr_t) addr, region);
124     } else {
125       // The memory spans several pages:
126       return mc_snapshot_read_fragmented(addr, region, target, size);
127     }
128   }
129
130   else {
131     xbt_die("No data available for this region");
132   }
133 }
134
135 /** @brief Read memory from a snapshot
136  *
137  *  @param addr     Process (non-snapshot) address of the data
138  *  @param snapshot Snapshot (or NULL is no snapshot)
139  *  @param target   Buffer to store the value
140  *  @param size     Size of the data to read in bytes
141  *  @return Pointer where the data is located (target buffer of original location)
142  */
143 void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, void* target, size_t size)
144 {
145   if (snapshot) {
146     mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot);
147     return mc_snapshot_read_region(addr, region, target, size);
148   } else {
149     return addr;
150   }
151 }
152
153 /** Compare memory between snapshots (with known regions)
154  *
155  * @param addr1 Address in the first snapshot
156  * @param snapshot2 Region of the address in the first snapshot
157  * @param addr2 Address in the second snapshot
158  * @param snapshot2 Region of the address in the second snapshot
159  * @return same as memcmp
160  * */
161 int mc_snapshot_region_memcp(
162   void* addr1, mc_mem_region_t region1,
163   void* addr2, mc_mem_region_t region2, size_t size)
164 {
165   // Using alloca() for large allocations may trigger stack overflow:
166   // use malloc if the buffer is too big.
167
168   bool stack_alloc = size < 64;
169   void* buffer = stack_alloc ? alloca(2*size) : malloc(2*size);
170   void* buffer1 = mc_snapshot_read_region(addr1, region1, buffer, size);
171   void* buffer2 = mc_snapshot_read_region(addr2, region2, (char*) buffer + size, size);
172   int res;
173   if (buffer1 == buffer2) {
174     res =  0;
175   } else {
176     res = memcmp(buffer1, buffer2, size);
177   }
178   if (!stack_alloc) {
179     free(buffer);
180   }
181   return res;
182 }
183
184 /** Compare memory between snapshots
185  *
186  * @param addr1 Address in the first snapshot
187  * @param snapshot1 First snapshot
188  * @param addr2 Address in the second snapshot
189  * @param snapshot2 Second snapshot
190  * @return same as memcmp
191  * */
192 int mc_snapshot_memcp(
193   void* addr1, mc_snapshot_t snapshot1,
194   void* addr2, mc_snapshot_t snapshot2, size_t size)
195 {
196   mc_mem_region_t region1 = mc_get_snapshot_region(addr1, snapshot1);
197   mc_mem_region_t region2 = mc_get_snapshot_region(addr2, snapshot2);
198   return mc_snapshot_region_memcp(addr1, region1, addr2, region2, size);
199 }