change sockaddr generation to pass around correct types.
[trinity.git] / maps.c
blob27467e180879acf1f8095ed75096233beff379f0
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <malloc.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/mman.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include "arch.h"
12 #include "child.h"
13 #include "list.h"
14 #include "log.h"
15 #include "maps.h"
16 #include "random.h"
17 #include "shm.h"
18 #include "trinity.h" // page_size
19 #include "utils.h"
21 static unsigned int num_global_mappings = 0;
22 static struct map *global_mappings = NULL;
24 static void dump_global_mappings(void)
26 struct map *m;
27 struct list_head *node;
29 output(2, "There are %d entries in the map table\n", num_global_mappings);
31 list_for_each(node, &global_mappings->list) {
32 m = (struct map *) node;
33 output(2, " start: %p name: %s\n", m->ptr, m->name);
37 static void alloc_zero_map(unsigned long size, int prot, const char *name)
39 struct map *newnode;
40 struct list_head *list;
41 int fd;
43 fd = open("/dev/zero", O_RDWR);
44 if (fd == -1) {
45 outputerr("couldn't open /dev/zero\n");
46 exit(EXIT_FAILURE);
49 newnode = zmalloc(sizeof(struct map));
50 newnode->name = strdup(name);
51 newnode->size = size;
52 newnode->prot = prot;
53 newnode->type = MAP_GLOBAL;
54 newnode->ptr = mmap(NULL, size, prot, MAP_ANONYMOUS | MAP_SHARED, fd, 0);
55 if (newnode->ptr == MAP_FAILED) {
56 outputerr("mmap failure\n");
57 exit(EXIT_FAILURE);
60 newnode->name = malloc(80);
61 if (!newnode->name) {
62 outputerr("malloc() failed in %s().", __func__);
63 exit(EXIT_FAILURE);
66 sprintf(newnode->name, "anon(%s)", name);
68 num_global_mappings++;
70 list = &global_mappings->list;
71 list_add_tail(&newnode->list, list);
73 output(2, "mapping[%d]: (zeropage %s) %p (%lu bytes)\n",
74 num_global_mappings - 1, name, newnode->ptr, size);
76 close(fd);
79 void setup_global_mappings(void)
81 unsigned int i;
82 const unsigned long sizes[] = {
83 1 * MB, 2 * MB, 4 * MB, 10 * MB,
84 // 1 * GB, // disabled for now, due to OOM.
87 global_mappings = zmalloc(sizeof(struct map));
88 INIT_LIST_HEAD(&global_mappings->list);
90 /* page_size * 2, so we have a guard page afterwards.
91 * This is necessary for when we want to test page boundaries.
92 * see end of _get_address() for details.
94 alloc_zero_map(page_size * 2, PROT_READ | PROT_WRITE, "PROT_READ | PROT_WRITE");
95 alloc_zero_map(page_size * 2, PROT_READ, "PROT_READ");
96 alloc_zero_map(page_size * 2, PROT_WRITE, "PROT_WRITE");
99 * multi megabyte page mappings.
101 for (i = 0; i < ARRAY_SIZE(sizes); i++) {
102 alloc_zero_map(sizes[i], PROT_READ | PROT_WRITE, "PROT_READ | PROT_WRITE");
103 alloc_zero_map(sizes[i], PROT_READ, "PROT_READ");
104 alloc_zero_map(sizes[i], PROT_WRITE, "PROT_WRITE");
107 dump_global_mappings();
110 /* Walk the list, get the j'th element */
111 static struct map * __get_map(struct list_head *head, unsigned int max)
113 struct map *m;
114 struct list_head *node;
116 unsigned int i, j = 0;
118 i = rand() % max;
120 list_for_each(node, head) {
121 m = (struct map *) node;
123 if (i == j)
124 return m;
125 j++;
127 return 0;
130 struct map * get_map(void)
132 struct map *map;
133 bool local = FALSE;
135 /* If we're not running in child context, just do global. */
136 if (this_child == 0)
137 return __get_map(&global_mappings->list, num_global_mappings);
139 /* Only toss the dice if we actually have local mappings. */
140 if (shm->num_mappings[this_child] > 0)
141 local = rand_bool();
143 if (local == TRUE)
144 map = __get_map(&shm->mappings[this_child]->list, shm->num_mappings[this_child]);
145 else
146 map = __get_map(&global_mappings->list, num_global_mappings);
148 return map;
151 void destroy_global_mappings(void)
153 struct map *m;
155 while (!list_empty(&global_mappings->list)) {
156 m = global_mappings;
158 munmap(m->ptr, m->size);
159 free(m->name);
161 global_mappings = (struct map *) m->list.next;
163 list_del(&m->list);
164 free(m);
167 num_global_mappings = 0;
170 static void delete_local_mapping(int childno, struct map *map)
172 list_del(&map->list);
173 shm->num_mappings[childno]--;
176 void delete_mapping(int childno, struct map *map)
178 if (map->type == MAP_LOCAL)
179 delete_local_mapping(childno, map);
181 /* Right now, we don't want to delete MAP_GLOBAL mappings */
184 struct map * common_set_mmap_ptr_len(int childno)
186 struct map *map;
188 map = (struct map *) shm->a1[childno];
189 shm->scratch[childno] = (unsigned long) map; /* Save this for ->post */
190 if (map == NULL) {
191 shm->a1[childno] = 0;
192 shm->a2[childno] = 0;
193 return NULL;
196 shm->a1[childno] = (unsigned long) map->ptr;
197 shm->a2[childno] = map->size; //TODO: Munge this.
199 return map;
202 void dirty_mapping(struct map *map)
204 char *p = map->ptr;
205 unsigned int i;
207 /* Check mapping is writable. */
208 if (!(map->prot & PROT_WRITE))
209 return;
211 if (rand_bool()) {
212 /* Just fault in one page. */
213 p[rand() % page_size] = 1;
214 } else {
215 /* fault in the whole mapping */
216 for (i = 0; i < map->size; i += page_size)
217 p[i] = 1;
219 //TODO: More access patterns.