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