1 /* -*- mode: C; mode: folding; fill-column: 70; -*- */
2 /* Copyright 2010, Georgia Institute of Technology, USA. */
3 /* See COPYING for license. */
4 #include "compat.h"
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <signal.h>
9 #include <errno.h>
10 #include <limits.h>
11 #include <unistd.h>
12 #include <time.h>
13 #include <fcntl.h>
14 #include <sys/types.h>
15 #include <sys/mman.h>
16
17 #if !defined(MAP_HUGETLB)
18 #define MAP_HUGETLB 0
19 #endif
20 #if !defined(MAP_POPULATE)
21 #define MAP_POPULATE 0
22 #endif
23 #if !defined(MAP_NOSYNC)
24 #define MAP_NOSYNC 0
25 #endif
26
27 #if 0
28 /* Included in the generator. */
29 void *
30 xmalloc (size_t sz)
31 {
32 void *out;
33 if (!(out = malloc (sz))) {
34 perror ("malloc failed");
35 abort ();
36 }
37 return out;
38 }
39 #endif
40
41 #if defined(__MTA__)||defined(USE_MMAP_LARGE)||defined(USE_MMAP_LARGE_EXT)
42 #define MAX_LARGE 32
43 static int n_large_alloc = 0;
44 static struct {
45 void * p;
46 size_t sz;
47 int fd;
48 } large_alloc[MAX_LARGE];
49
50 static int installed_handler = 0;
51 static void (*old_abort_handler)(int);
52
53 static void
exit_handler(void)54 exit_handler (void)
55 {
56 int k;
57 for (k = 0; k < n_large_alloc; ++k) {
58 if (large_alloc[k].p)
59 munmap (large_alloc[k].p, large_alloc[k].sz);
60 if (large_alloc[k].fd >= 0)
61 close (large_alloc[k].fd);
62 large_alloc[k].p = NULL;
63 large_alloc[k].fd = -1;
64 }
65 }
66
67 static void
abort_handler(int passthrough)68 abort_handler (int passthrough)
69 {
70 exit_handler ();
71 if (old_abort_handler) old_abort_handler (passthrough);
72 }
73 #endif
74
75 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
76 #define MAP_ANONYMOUS MAP_ANON
77 #endif
78
79 void *
xmalloc_large(size_t sz)80 xmalloc_large (size_t sz)
81 {
82 #if defined(__MTA__)||defined(USE_MMAP_LARGE)
83 void *out;
84 int which = n_large_alloc++;
85 if (n_large_alloc > MAX_LARGE) {
86 fprintf (stderr, "Too many large allocations. %d %d\n", n_large_alloc, MAX_LARGE);
87 --n_large_alloc;
88 abort ();
89 }
90 large_alloc[which].p = NULL;
91 large_alloc[which].fd = -1;
92 out = mmap (NULL, sz, PROT_READ|PROT_WRITE,
93 MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|MAP_POPULATE, 0, 0);
94 if (out == MAP_FAILED || !out) {
95 perror ("mmap failed");
96 abort ();
97 }
98 large_alloc[which].p = out;
99 large_alloc[which].sz = sz;
100 return out;
101 #else
102 return xmalloc (sz);
103 #endif
104 }
105
106 void
xfree_large(void * p)107 xfree_large (void *p)
108 {
109 #if defined(__MTA__)||defined(USE_MMAP_LARGE)||defined(USE_MMAP_LARGE_EXT)
110 int k, found = 0;
111 for (k = 0; k < n_large_alloc; ++k) {
112 if (p == large_alloc[k].p) {
113 munmap (p, large_alloc[k].sz);
114 large_alloc[k].p = NULL;
115 if (large_alloc[k].fd >= 0) {
116 close (large_alloc[k].fd);
117 large_alloc[k].fd = -1;
118 }
119 found = 1;
120 break;
121 }
122 }
123 if (found) {
124 --n_large_alloc;
125 for (; k < n_large_alloc; ++k)
126 large_alloc[k] = large_alloc[k+1];
127 } else
128 free (p);
129 #else
130 free (p);
131 #endif
132 }
133
134 void *
xmalloc_large_ext(size_t sz)135 xmalloc_large_ext (size_t sz)
136 {
137 #if !defined(__MTA__)&&defined(USE_MMAP_LARGE_EXT)
138 char extname[PATH_MAX+1];
139 char *tmppath;
140 void *out;
141 int fd, which;
142
143 if (getenv ("TMPDIR"))
144 tmppath = getenv ("TMPDIR");
145 else if (getenv ("TEMPDIR"))
146 tmppath = getenv ("TEMPDIR");
147 else
148 tmppath = "/tmp";
149
150 sprintf (extname, "%s/graph500-ext-XXXXXX", tmppath);
151
152 which = n_large_alloc++;
153 if (n_large_alloc > MAX_LARGE) {
154 fprintf (stderr, "Out of large allocations.\n");
155 abort ();
156 }
157 large_alloc[which].p = 0;
158 large_alloc[which].fd = -1;
159
160 fd = mkstemp (extname);
161 if (fd < 0) {
162 perror ("xmalloc_large_ext failed to make a file");
163 abort ();
164 }
165 if (unlink (extname)) {
166 perror ("UNLINK FAILED!");
167 goto errout;
168 }
169
170 #if _XOPEN_SOURCE >= 500
171 if (pwrite (fd, &fd, sizeof (fd), sz - sizeof(fd)) != sizeof (fd)) {
172 perror ("resizing pwrite failed");
173 goto errout;
174 }
175 #else
176 if (lseek (fd, sz - sizeof(fd), SEEK_SET) < 0) {
177 perror ("lseek failed");
178 goto errout;
179 }
180 if (write (fd, &fd, sizeof(fd)) != sizeof (fd)) {
181 perror ("resizing write failed");
182 goto errout;
183 }
184 #endif
185 fcntl (fd, F_SETFD, O_ASYNC);
186
187 out = mmap (NULL, sz, PROT_READ|PROT_WRITE,
188 MAP_SHARED|MAP_POPULATE|MAP_NOSYNC, fd, 0);
189 if (MAP_FAILED == out || !out) {
190 perror ("mmap ext failed");
191 goto errout;
192 }
193
194 if (!installed_handler) {
195 installed_handler = 1;
196 if (atexit (exit_handler)) {
197 perror ("failed to install exit handler");
198 goto errout;
199 }
200
201 old_abort_handler = signal (SIGABRT, abort_handler);
202 if (SIG_ERR == old_abort_handler) {
203 perror ("failed to install cleanup handler");
204 goto errout;
205 }
206 }
207
208 large_alloc[which].p = out;
209 large_alloc[which].sz = sz;
210 large_alloc[which].fd = fd;
211
212 return out;
213
214 errout:
215 if (fd >= 0) close (fd);
216 abort ();
217 #else
218 return xmalloc_large (sz);
219 #endif
220 }
221
222 /*
223 void
224 mark_large_unused (void *p)
225 {
226 #if !defined(__MTA__)
227 int k;
228 for (k = 0; k < n_large_alloc; ++k)
229 if (p == large_alloc[k].p)
230 posix_madvise (large_alloc[k].p, large_alloc[k].sz, POSIX_MADV_DONTNEED);
231 #endif
232 }
233
234 void
235 mark_large_willuse (void *p)
236 {
237 #if !defined(__MTA__)
238 int k;
239 for (k = 0; k < n_large_alloc; ++k)
240 if (p == large_alloc[k].p)
241 posix_madvise (large_alloc[k].p, large_alloc[k].sz, POSIX_MADV_WILLNEED);
242 #endif
243 }
244 */
245