~ubuntu-branches/debian/sid/trinity/sid

« back to all changes in this revision

Viewing changes to maps.c

  • Committer: Package Import Robot
  • Author(s): gustavo panizzo
  • Date: 2014-01-17 21:10:15 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20140117211015-k2qbnpu0osa5mlil
Tags: 1.3-1
* New upstream version 1.3.
* Removed wrong dependency on linux-headers. (Closes: #733771).

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
#include <sys/mman.h>
9
9
#include <sys/types.h>
10
10
#include <sys/stat.h>
11
 
#include "trinity.h"    // page_size
12
11
#include "arch.h"
 
12
#include "child.h"
 
13
#include "list.h"
 
14
#include "log.h"
13
15
#include "maps.h"
14
 
#include "log.h"
 
16
#include "random.h"
15
17
#include "shm.h"
16
 
 
17
 
static unsigned int num_mappings = 0;
18
 
static struct map *maps_list;
19
 
 
20
 
char *page_zeros;
21
 
char *page_0xff;
22
 
char *page_rand;
23
 
char *page_allocs;
24
 
 
25
 
void * alloc_shared(unsigned int size)
26
 
{
27
 
        void *ret;
28
 
 
29
 
        ret = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
30
 
        if (ret == MAP_FAILED)
31
 
                return NULL;
32
 
 
33
 
        return ret;
34
 
}
35
 
 
36
 
static struct map * alloc_map(void)
37
 
{
38
 
        struct map *newmap;
39
 
 
40
 
        newmap = malloc(sizeof(struct map));
41
 
        if (!newmap) {
42
 
                printf("Couldn't allocate maps list!\n");
43
 
                exit(EXIT_FAILURE);
44
 
        }
45
 
        memset(newmap, 0, sizeof(struct map));
46
 
        return newmap;
47
 
}
48
 
 
49
 
static void dump_maps(void)
50
 
{
51
 
        struct map *tmpmap = maps_list;
52
 
        unsigned int j;
53
 
 
54
 
        output(2, "There are %d entries in the map table\n", num_mappings);
55
 
 
56
 
        for (j = 0; j < num_mappings; j++) {
57
 
                output(2, " start: %p  name: %s\n", tmpmap->ptr, tmpmap->name);
58
 
                tmpmap = tmpmap->next;
59
 
        }
60
 
}
61
 
 
62
 
static void * alloc_zero_map(struct map *map, int prot, const char *name)
63
 
{
64
 
        struct map *tmpmap = map;
 
18
#include "trinity.h"    // page_size
 
19
#include "utils.h"
 
20
 
 
21
static unsigned int num_global_mappings = 0;
 
22
static struct map *global_mappings = NULL;
 
23
 
 
24
static void dump_global_mappings(void)
 
25
{
 
26
        struct map *m;
 
27
        struct list_head *node;
 
28
 
 
29
        output(2, "There are %d entries in the map table\n", num_global_mappings);
 
30
 
 
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);
 
34
        }
 
35
}
 
36
 
 
37
static void alloc_zero_map(unsigned long size, int prot, const char *name)
 
38
{
 
39
        struct map *newnode;
 
40
        struct list_head *list;
65
41
        int fd;
66
 
        unsigned long size = 0;
67
 
 
68
 
        if (!tmpmap)
69
 
                tmpmap = alloc_map();
70
42
 
71
43
        fd = open("/dev/zero", O_RDWR);
72
 
        if (fd < 0) {
73
 
                printf("open /dev/zero failure. %s\n", strerror(errno));
74
 
                exit(EXIT_FAILURE);
75
 
        }
76
 
 
77
 
        /* Pick a random sized mmap. */
78
 
        switch (rand() % 4) {
79
 
        case 0: size = page_size;
80
 
                break;
81
 
        case 1: size = 1024*1024;
82
 
                break;
83
 
        case 2: size = 2 * (1024*1024);
84
 
                break;
85
 
        case 3: size = 4 * (1024*1024);
86
 
                break;
87
 
        default:
88
 
                break;
89
 
        }
 
44
        if (fd == -1) {
 
45
                outputerr("couldn't open /dev/zero\n");
 
46
                exit(EXIT_FAILURE);
 
47
        }
 
48
 
 
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);
 
58
        }
 
59
 
 
60
        newnode->name = malloc(80);
 
61
        if (!newnode->name) {
 
62
                outputerr("malloc() failed in %s().", __func__);
 
63
                exit(EXIT_FAILURE);
 
64
        }
 
65
 
 
66
        sprintf(newnode->name, "anon(%s)", name);
 
67
 
 
68
        num_global_mappings++;
 
69
 
 
70
        list = &global_mappings->list;
 
71
        list_add_tail(&newnode->list, list);
 
72
 
 
73
        output(2, "mapping[%d]: (zeropage %s) %p (%lu bytes)\n",
 
74
                        num_global_mappings - 1, name, newnode->ptr, size);
 
75
 
 
76
        close(fd);
 
77
}
 
78
 
 
79
void setup_global_mappings(void)
 
80
{
 
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.
 
85
        };
 
86
 
 
87
        global_mappings = zmalloc(sizeof(struct map));
 
88
        INIT_LIST_HEAD(&global_mappings->list);
90
89
 
91
90
        /* page_size * 2, so we have a guard page afterwards.
92
91
         * This is necessary for when we want to test page boundaries.
93
92
         * see end of _get_address() for details.
94
93
         */
95
 
        size *= 2;
96
 
 
97
 
        tmpmap->ptr = mmap(NULL, size, prot, MAP_ANONYMOUS|MAP_SHARED, fd, 0);
98
 
 
99
 
        if (tmpmap->ptr == MAP_FAILED) {
100
 
                printf("mmap /dev/zero failure\n");
101
 
                exit(EXIT_FAILURE);
102
 
        }
103
 
 
104
 
        tmpmap->size = size;
105
 
 
106
 
        tmpmap->name = malloc(80);
107
 
        if (!tmpmap->name) {
108
 
                fprintf(stderr, "malloc() failed in %s().", __func__);
109
 
                exit(EXIT_FAILURE);
110
 
        }
111
 
 
112
 
        sprintf(tmpmap->name, "/dev/zero(%s)", name);
113
 
        num_mappings++;
114
 
 
115
 
        output(2, "mapping[%d]: (zeropage %s) %p (%lu bytes)\n",
116
 
                        num_mappings - 1, name, tmpmap->ptr, size);
117
 
 
118
 
        if (fd >= 0)
119
 
                close(fd);
120
 
        return tmpmap;
121
 
}
122
 
 
123
 
void setup_maps(void)
124
 
{
125
 
        struct map *tmpmap;
126
 
 
127
 
        tmpmap = maps_list = alloc_map();
128
 
 
129
 
        /* Add a bunch of /dev/zero mappings */
130
 
        tmpmap->next = alloc_zero_map(tmpmap, PROT_READ | PROT_WRITE, "PROT_READ | PROT_WRITE");
131
 
        tmpmap = tmpmap->next;
132
 
 
133
 
        tmpmap->next = alloc_zero_map(NULL, PROT_READ, "PROT_READ");
134
 
        tmpmap = tmpmap->next;
135
 
 
136
 
        tmpmap->next = alloc_zero_map(NULL, PROT_WRITE, "PROT_WRITE");
137
 
 
138
 
        output(2, "Added /dev/zero mappings.\n");
139
 
        dump_maps();
140
 
}
141
 
 
142
 
void * get_map(void)
143
 
{
144
 
        struct map *tmpmap = maps_list;
145
 
        unsigned int i, j;
146
 
 
147
 
        i = rand() % num_mappings;
148
 
        for (j = 0; j < i; j++)
149
 
                tmpmap = tmpmap->next;
150
 
 
151
 
        return tmpmap->ptr;
152
 
}
153
 
 
154
 
void destroy_maps(void)
155
 
{
156
 
        unsigned int i;
157
 
        struct map *thismap = maps_list, *next;
158
 
 
159
 
        for (i = 0; i < num_mappings; i++) {
160
 
                next = thismap->next;
161
 
                munmap(thismap->ptr, thismap->size);
162
 
                free(thismap->name);
163
 
                free(thismap);
164
 
                thismap = next;
165
 
        }
166
 
        num_mappings = 0;
167
 
}
168
 
 
169
 
void init_buffers(void)
170
 
{
171
 
        unsigned int i;
172
 
 
173
 
        output(2, "shm is at %p\n", shm);
174
 
 
175
 
        page_zeros = memalign(page_size, page_size * 2);
176
 
        if (!page_zeros)
177
 
                exit(EXIT_FAILURE);
178
 
        memset(page_zeros, 0, page_size);
179
 
        output(2, "page_zeros @ %p\n", page_zeros);
180
 
 
181
 
        page_0xff = memalign(page_size, page_size * 2);
182
 
        if (!page_0xff)
183
 
                exit(EXIT_FAILURE);
184
 
        memset(page_0xff, 0xff, page_size);
185
 
        output(2, "page_0xff @ %p\n", page_0xff);
186
 
 
187
 
        page_rand = memalign(page_size, page_size * 2);
188
 
        if (!page_rand)
189
 
                exit(EXIT_FAILURE);
190
 
        memset(page_rand, 0x55, page_size);     /* overwritten below */
191
 
        output(2, "page_rand @ %p\n", page_rand);
192
 
 
193
 
        page_allocs = memalign(page_size, page_size * 2);
194
 
        if (!page_allocs)
195
 
                exit(EXIT_FAILURE);
196
 
        memset(page_allocs, 0xff, page_size);
197
 
        output(2, "page_allocs @ %p\n", page_allocs);
198
 
 
199
 
        for (i = 0; i < (page_size / sizeof(unsigned long *)); i++)
200
 
                page_allocs[i] = (unsigned long) malloc(page_size);
201
 
 
202
 
        setup_maps();
203
 
 
204
 
        // generate_random_page may end up using maps, so has to be last.
205
 
        generate_random_page(page_rand);
 
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");
 
97
 
 
98
        /*
 
99
         * multi megabyte page mappings.
 
100
         */
 
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");
 
105
        }
 
106
 
 
107
        dump_global_mappings();
 
108
}
 
109
 
 
110
/* Walk the list, get the j'th element */
 
111
static struct map * __get_map(struct list_head *head, unsigned int max)
 
112
{
 
113
        struct map *m;
 
114
        struct list_head *node;
 
115
 
 
116
        unsigned int i, j = 0;
 
117
 
 
118
        i = rand() % max;
 
119
 
 
120
        list_for_each(node, head) {
 
121
                m = (struct map *) node;
 
122
 
 
123
                if (i == j)
 
124
                        return m;
 
125
                j++;
 
126
        }
 
127
        return 0;
 
128
}
 
129
 
 
130
struct map * get_map(void)
 
131
{
 
132
        struct map *map;
 
133
        bool local = FALSE;
 
134
 
 
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);
 
138
 
 
139
        /* Only toss the dice if we actually have local mappings. */
 
140
        if (shm->num_mappings[this_child] > 0)
 
141
                local = rand_bool();
 
142
 
 
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);
 
147
 
 
148
        return map;
 
149
}
 
150
 
 
151
void destroy_global_mappings(void)
 
152
{
 
153
        struct map *m;
 
154
 
 
155
        while (!list_empty(&global_mappings->list)) {
 
156
                m = global_mappings;
 
157
 
 
158
                munmap(m->ptr, m->size);
 
159
                free(m->name);
 
160
 
 
161
                global_mappings = (struct map *) m->list.next;
 
162
 
 
163
                list_del(&m->list);
 
164
                free(m);
 
165
        }
 
166
 
 
167
        num_global_mappings = 0;
 
168
}
 
169
 
 
170
static void delete_local_mapping(int childno, struct map *map)
 
171
{
 
172
        list_del(&map->list);
 
173
        shm->num_mappings[childno]--;
 
174
}
 
175
 
 
176
void delete_mapping(int childno, struct map *map)
 
177
{
 
178
        if (map->type == MAP_LOCAL)
 
179
                delete_local_mapping(childno, map);
 
180
 
 
181
        /* Right now, we don't want to delete MAP_GLOBAL mappings */
 
182
}
 
183
 
 
184
struct map * common_set_mmap_ptr_len(int childno)
 
185
{
 
186
        struct map *map;
 
187
 
 
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;
 
194
        }
 
195
 
 
196
        shm->a1[childno] = (unsigned long) map->ptr;
 
197
        shm->a2[childno] = map->size;           //TODO: Munge this.
 
198
 
 
199
        return map;
 
200
}
 
201
 
 
202
void dirty_mapping(struct map *map)
 
203
{
 
204
        char *p = map->ptr;
 
205
        unsigned int i;
 
206
 
 
207
        /* Check mapping is writable. */
 
208
        if (!(map->prot & PROT_WRITE))
 
209
                return;
 
210
 
 
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;
 
218
        }
 
219
        //TODO: More access patterns.
206
220
}