Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Partial integration of per-page snapshot address translation (wip)
[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 "mc_private.h"
8 #include "mc_mmu.h"
9
10 static mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot)
11 {
12   for (size_t i = 0; i != NB_REGIONS; ++i) {
13     mc_mem_region_t region = snapshot->regions[i];
14     void* start = region->start_addr;
15     void* end = (char*) start + region->size;
16
17     if (addr >= start && addr < end) {
18       return region;
19     }
20   }
21
22   return NULL;
23 }
24
25 void* mc_translate_address_region(uintptr_t addr, mc_mem_region_t region)
26 {
27   if (!region) {
28     return (void *) addr;
29   }
30
31   // Flat snapshot:
32   else if (region->data) {
33     uintptr_t offset = addr - (uintptr_t) region->start_addr;
34     return (void *) ((uintptr_t) region->data + offset);
35   }
36
37   // Per-page snapshot:
38   else if (region->page_numbers) {
39     size_t pageno = mc_page_number(region->data, (void*) addr);
40     return (char*) region->page_numbers[pageno] + mc_page_offset((void*) addr);
41   }
42
43   else {
44     xbt_die("No data for this memory region");
45   }
46 }
47
48 void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot)
49 {
50
51   // If not in a process state/clone:
52   if (!snapshot) {
53     return (uintptr_t *) addr;
54   }
55
56   mc_mem_region_t region = mc_get_snapshot_region((void*) addr, snapshot);
57   return mc_translate_address_region(addr, region);
58
59 }
60
61 uintptr_t mc_untranslate_address(void *addr, mc_snapshot_t snapshot)
62 {
63   if (!snapshot) {
64     return (uintptr_t) addr;
65   }
66
67   for (size_t i = 0; i != NB_REGIONS; ++i) {
68     mc_mem_region_t region = snapshot->regions[i];
69     if (region->page_numbers) {
70       xbt_die("Does not work for per-page snapshot.");
71     }
72     if (addr >= region->data
73         && addr <= (void *) (((char *) region->data) + region->size)) {
74       size_t offset = (size_t) ((char *) addr - (char *) region->data);
75       return ((uintptr_t) region->start_addr) + offset;
76     }
77   }
78
79   return (uintptr_t) addr;
80 }
81
82 /** @brief Read memory from a snapshot region broken across fragmented pages
83  *
84  *  @param addr    Process (non-snapshot) address of the data
85  *  @param region  Snapshot memory region where the data is located
86  *  @param target  Buffer to store the value
87  *  @param size    Size of the data to read in bytes
88  *  @return Pointer where the data is located (target buffer of original location)
89  */
90 static void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size)
91 {
92   void* end = (char*) addr + size - 1;
93   size_t page_end = mc_page_number(NULL, end);
94
95   // Read each page:
96   while (mc_page_number(NULL, addr) != page_end) {
97     void* snapshot_addr = mc_translate_address_region((uintptr_t) addr, region);
98     void* next_page = mc_page_from_number(NULL, mc_page_number(NULL, addr) + 1);
99     size_t readable = (char*) next_page - (char*) addr;
100     memcpy(target, snapshot_addr, readable);
101     target = (char*) target + readable;
102     size -= readable;
103   }
104
105   // Read the end:
106   void* snapshot_addr = mc_translate_address_region((uintptr_t)addr, region);
107   memcpy(target, snapshot_addr, size);
108
109   return target;
110 }
111
112 /** @brief Read memory from a snapshot region
113  *
114  *  @param addr    Process (non-snapshot) address of the data
115  *  @param region  Snapshot memory region where the data is located
116  *  @param target  Buffer to store the value
117  *  @param size    Size of the data to read in bytes
118  *  @return Pointer where the data is located (target buffer of original location)
119  */
120 void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target, size_t size)
121 {
122   uintptr_t offset = (uintptr_t) addr - (uintptr_t) region->start_addr;
123
124   if (addr < region->start_addr || offset+size > region->size) {
125     xbt_die("Trying to read out of the region boundary.");
126   }
127
128   // Linear memory region:
129   if (region->data) {
130     return (void*) ((uintptr_t) region->data + offset);
131   }
132
133   // Fragmented memory region:
134   else if (region->page_numbers) {
135     void* end = (char*) addr + size - 1;
136     if( mc_same_page(addr, end) ) {
137       // The memory is contained in a single page:
138       return mc_translate_address_region((uintptr_t) addr, region);
139     } else {
140       // The memory spans several pages:
141       return mc_snapshot_read_fragmented(addr, region, target, size);
142     }
143   }
144
145   else {
146     xbt_die("No data available for this region");
147   }
148 }
149
150 /** @brief Read memory from a snapshot
151  *
152  *  @param addr     Process (non-snapshot) address of the data
153  *  @param snapshot Snapshot (or NULL is no snapshot)
154  *  @param target   Buffer to store the value
155  *  @param size     Size of the data to read in bytes
156  *  @return Pointer where the data is located (target buffer of original location)
157  */
158 void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, void* target, size_t size)
159 {
160   if (snapshot) {
161     mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot);
162     return mc_snapshot_read_region(addr, region, target, size);
163   } else {
164     return target;
165   }
166 }