Ticket #32: spagefile.c

File spagefile.c, 3.7 KB (added by john, 13 years ago)

Test case

Line 
1#include <sys/param.h>
2#include <sys/mman.h>
3#include <sys/stat.h>
4#include <assert.h>
5#include <err.h>
6#include <fcntl.h>
7#include <libutil.h>
8#include <stdbool.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13
14size_t pagesize[2];
15
16static void
17check_region(char *start, size_t len, const char *msg)
18{
19        size_t offset;
20        int i, leading, trailing, pages, super, small;
21
22        offset = (uintptr_t)start % pagesize[0];
23        if (offset != 0) {
24                printf("%s: start address is not page aligned!\n", msg);
25                len += offset;
26                start -= offset;
27        }
28        offset = (uintptr_t)start % pagesize[1];
29        if (offset != 0) {
30                printf("%s: start address is not super aligned\n", msg);
31                leading = (pagesize[1] - offset) / pagesize[0];
32        } else
33                leading = 0;
34        len = roundup2(len, pagesize[0]);
35        trailing = (len - leading * pagesize[0]) % pagesize[1] / pagesize[0];
36
37        small = super = 0;
38        pages = len / pagesize[0];
39        char *info = malloc(pages);
40        if (mincore(start, len, info) < 0)
41                err(1, "%s: mincore", msg);
42        for (i = 0; i < pages; i++) {
43                if (info[i] & MINCORE_SUPER)
44                        super++;
45                else if (info[i] & MINCORE_INCORE)
46                        small++;
47        }
48        assert(super % (pagesize[1] / pagesize[0]) == 0);
49        if (small != (leading + trailing))
50                printf("%s: expected %d super / %d small, found %d / %d\n",
51                    msg, pages - (leading + trailing), leading + trailing,
52                    super, small);
53}
54
55static int
56create_shm(size_t size)
57{
58        int fd;
59
60        fd = shm_open(SHM_ANON, O_RDWR, 0644);
61        if (fd < 0)
62                err(1, "shm_open(SHM_ANON)");
63        if (ftruncate(fd, size) < 0)
64                err(1, "ftruncate");
65        return (fd);
66}
67
68static int
69create_file(const char *path)
70{
71        int fd;
72
73        fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
74        if (fd < 0)
75                err(1, "open(%s)", path);
76        return (fd);
77}
78
79static void
80zero_file(int fd, size_t size)
81{
82        ssize_t nwritten;
83        size_t towrite;
84        char buffer[64 * 1024];
85
86        memset(buffer, 0, sizeof(buffer));
87        if (ftruncate(fd, 0) < 0)
88                err(1, "ftruncate");
89        while (size > 0) {
90                towrite = size;
91                if (towrite > sizeof(buffer))
92                        towrite = sizeof(buffer);
93                nwritten = write(fd, buffer, towrite);
94                if (nwritten < 0)
95                        err(1, "write");
96                if ((size_t)nwritten != towrite)
97                        errx(1, "short write");
98                size -= towrite;
99        }
100}
101
102static void
103map_file(int fd, bool prefault, const char *msg)
104{
105        struct stat sb;
106        char *cp, *p;
107        int sum;
108
109        if (fstat(fd, &sb) < 0)
110                err(1, "fstat");
111        p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED | MAP_PREFAULT_READ,
112            fd, 0);
113        if (p == MAP_FAILED)
114                err(1, "mmap");
115        if (prefault) {
116                sum = 0;
117                for (cp = p; cp < p + sb.st_size; cp += pagesize[0])
118                        sum += *cp;
119                usleep(sum);
120        }
121        check_region(p, sb.st_size, msg);
122}
123
124int
125main(int ac, char **av)
126{
127        char buf[5];
128        int retval;
129        int fd;
130
131        retval = getpagesizes(pagesize, 2);
132        if (retval < 0)
133                err(1, "getpagesizes");
134        if (retval != 2)
135                errx(1, "getpagesizes returned %d sizes", retval);
136        (void)humanize_number(buf, sizeof(buf), pagesize[0], "", HN_AUTOSCALE,
137            HN_NOSPACE);
138        printf("Normal page size: %s\n", buf);
139        (void)humanize_number(buf, sizeof(buf), pagesize[1], "", HN_AUTOSCALE,
140            HN_NOSPACE);
141        printf("Super page size: %s\n", buf);
142
143        /* First, a super-page sized shm. */
144        map_file(create_shm(pagesize[1] * 4), true, "super page sized shm");
145
146        /*
147         * Now, try a shm that isn't an even multiple followed by one
148         * that is.
149         */
150        map_file(create_shm(pagesize[1] * 2 + pagesize[1] / 2), true,
151            "odd sized shm");
152        map_file(create_shm(pagesize[1] * 2), true, "super page sized shm (2)");
153
154        /*
155         * Create a new file on disk and map it without pre-zeroing.
156         */
157        fd = create_file("/usr/scratch/spagefile");
158        if (ftruncate(fd, pagesize[1] * 32) < 0)
159                err(1, "ftruncate");
160        map_file(fd, true, "truncated file");
161
162        /* Truncate and zero the file and then map it. */
163        zero_file(fd, pagesize[1] * 64);
164        map_file(fd, true, "zeroed file");
165
166        return (0);
167}