1 /*
2 Copyright (C) 1995 Pascal Haible. All Rights Reserved.
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 PASCAL HAIBLE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
21
22 Except as contained in this notice, the name of Pascal Haible shall
23 not be used in advertising or otherwise to promote the sale, use or other
24 dealings in this Software without prior written authorization from
25 Pascal Haible.
26 */
27
28 /* $XFree86: xc/programs/Xserver/os/xalloc.c,v 3.12.2.1 1997/05/10 07:03:02 hohndel Exp $ */
29
30 /* Only used if INTERNAL_MALLOC is defined
31 * - otherwise xalloc() in utils.c is used
32 */
33 #ifdef INTERNAL_MALLOC
34
35 #if defined(__STDC__) || defined(AMOEBA)
36 #ifndef NOSTDHDRS
37 #include <stdlib.h> /* for malloc() etc. */
38 #endif
39 #else
40 extern char *malloc();
41 extern char *calloc();
42 extern char *realloc();
43 #endif
44
45 #include "Xos.h"
46 #include "misc.h"
47 #include "X.h"
48
49 #ifdef XALLOC_LOG
50 #include <stdio.h>
51 #endif
52
53 extern Bool Must_have_memory;
54
55 /*
56 ***** New malloc approach for the X server *****
57 * Pascal Haible 1995
58 *
59 * Some statistics about memory allocation of the X server
60 * The test session included several clients of different size, including
61 * xv, emacs and xpaint with a new canvas of 3000x2000, zoom 5.
62 * All clients were running together.
63 * A protocolling version of Xalloc recorded 318917 allocating actions
64 * (191573 Xalloc, 85942 XNFalloc, 41438 Xrealloc, 279727 Xfree).
65 * Results grouped by size, excluding the next lower size
66 * (i.e. size=32 means 16<size<=32):
67 *
68 * size nr of alloc max nr of blocks allocated together
69 * 8 1114 287
70 * 16 17341 4104
71 * 32 147352 2068
72 * 64 59053 2518
73 * 128 46882 1230
74 * 256 20544 1217
75 * 512 6808 117
76 * 1024 8254 171
77 * 2048 4841 287
78 * 4096 2429 84
79 * 8192 3364 85
80 * 16384 573 22
81 * 32768 49 7
82 * 65536 45 5
83 * 131072 48 2
84 * 262144 209 2
85 * 524288 7 4
86 * 1048576 2 1
87 * 8388608 2 2
88 *
89 * The most used sizes:
90 * count size
91 * 24 136267
92 * 40 37055
93 * 72 17278
94 * 56 13504
95 * 80 9372
96 * 16 8966
97 * 32 8411
98 * 136 8399
99 * 104 7690
100 * 12 7630
101 * 120 5512
102 * 88 4634
103 * 152 3062
104 * 52 2881
105 * 48 2736
106 * 156 1569
107 * 168 1487
108 * 160 1483
109 * 28 1446
110 * 1608 1379
111 * 184 1305
112 * 552 1270
113 * 64 934
114 * 320 891
115 * 8 754
116 *
117 * Conclusions: more than the half of all allocations are <= 32 bytes.
118 * But of these about 150,000 blocks, only a maximum of about 6,000 are
119 * allocated together (including memory leaks..).
120 * On the other side, only 935 of the 191573 or 0.5% were larger than 8kB
121 * (362 or 0.2% larger than 16k).
122 *
123 * What makes the server really grow is the fragmentation of the heap,
124 * and the fact that it can't shrink.
125 * To cure this, we do the following:
126 * - large blocks (>=11k) are mmapped on xalloc, and unmapped on xfree,
127 * so we don't need any free lists etc.
128 * As this needs 2 system calls, we only do this for the quite
129 * infrequent large (>=11k) blocks.
130 * - instead of reinventing the wheel, we use system malloc for medium
131 * sized blocks (>256, <11k).
132 * - for small blocks (<=256) we use an other approach:
133 * As we need many small blocks, and most ones for a short time,
134 * we don't go through the system malloc:
135 * for each fixed sizes a seperate list of free blocks is kept.
136 * to KISS (Keep it Small and Simple), we don't free them
137 * (not freeing a block of 32 bytes won't be worse than having fragmented
138 * a larger area on allocation).
139 * This way, we (almost) allways have a fitting free block right at hand,
140 * and don't have to walk any lists.
141 */
142
143 /*
144 * structure layout of a allocated block
145 * unsigned long size:
146 * rounded up netto size for small and medium blocks
147 * brutto size == mmap'ed area for large blocks
148 * unsigned long DEBUG ? MAGIC : unused
149 * .... data
150 * ( unsigned long MAGIC2 ) only if SIZE_TAIL defined
151 *
152 */
153
154 /* use otherwise unused long in the header to store a magic */
155 /* shouldn't this be removed for production release ? */
156 #define XALLOC_DEBUG
157
158 #ifdef XALLOC_DEBUG
159 /* Xfree fills the memory with a certain pattern (currently 0xF0) */
160 /* this should really be removed for production release! */
161 #define XFREE_ERASES
162 #endif
163
164 /* this must be a multiple of SIZE_STEPS below */
165 #define MAX_SMALL 264 /* quite many blocks of 264 */
166
167 #define MIN_LARGE (11*1024)
168 /* worst case is 25% loss with a page size of 4k */
169
170 /* SIZE_STEPS defines the granularity of size of small blocks -
171 * this makes blocks align to that, too! */
172 #define SIZE_STEPS (sizeof(double))
173 #define SIZE_HEADER (2*sizeof(long)) /* = sizeof(double) for 32bit */
174 #ifdef XALLOC_DEBUG
175 #if defined(__sparc__) || defined(__hppa__)
176 #define SIZE_TAIL (2*sizeof(long)) /* = sizeof(double) for 32bit */
177 #else
178 #define SIZE_TAIL (sizeof(long))
179 #endif
180 #endif
181
182 #undef TAIL_SIZE
183 #ifdef SIZE_TAIL
184 #define TAIL_SIZE SIZE_TAIL
185 #else
186 #define TAIL_SIZE 0
187 #endif
188
189 #ifdef __alpha__
190 #define MAGIC 0x1404196414071968
191 #define MAGIC2 0x2515207525182079
192 #else
193 #define MAGIC 0x14071968
194 #define MAGIC2 0x25182079
195 #endif
196
197 /* To get some statistics about memory allocation */
198
199 #ifdef XALLOC_LOG
200 #define XALLOC_LOG_FILE "/tmp/Xalloc.log" /* unsecure... */
201 #define LOG_BODY(_body) \
202 { FILE *f; \
203 f = fopen(XALLOC_LOG_FILE, "a"); \
204 if (NULL!=f) { \
205 _body; \
206 fclose(f); \
207 } \
208 }
209 #if defined(linux) && defined(i386)
210 #define LOG_ALLOC(_fun, _size, _ret) \
211 { unsigned long *from; \
212 __asm__("movl %%ebp,%0" : /*OUT*/ "=r" (from) : /*IN*/ ); \
213 LOG_BODY(fprintf(f, "%s\t%i\t%p\t[%lu]\n", _fun, _size, _ret, *(from+1))) \
214 }
215 #else
216 #define LOG_ALLOC(_fun, _size, _ret) \
217 LOG_BODY(fprintf(f, "%s\t%i\t%p\n", _fun, _size, _ret))
218 #endif
219 #define LOG_REALLOC(_fun, _ptr, _size, _ret) \
220 LOG_BODY(fprintf(f, "%s\t%p\t%i\t%p\n", _fun, _ptr, _size, _ret))
221 #define LOG_FREE(_fun, _ptr) \
222 LOG_BODY(fprintf(f, "%s\t%p\n", _fun, _ptr))
223 #else
224 #define LOG_ALLOC(_fun, _size, _ret)
225 #define LOG_REALLOC(_fun, _ptr, _size, _ret)
226 #define LOG_FREE(_fun, _ptr)
227 #endif /* XALLOC_LOG */
228
229 static unsigned long *free_lists[MAX_SMALL/SIZE_STEPS];
230
231 /*
232 * systems that support it should define HAS_MMAP_ANON or MMAP_DEV_ZERO
233 * and include the appropriate header files for
234 * mmap(), munmap(), PROT_READ, PROT_WRITE, MAP_PRIVATE,
235 * PAGE_SIZE or _SC_PAGESIZE (and MAP_ANON for HAS_MMAP_ANON).
236 *
237 * systems that don't support MAP_ANON fall through to the 2 fold behaviour
238 */
239
240 #if defined(linux)
241 #define HAS_MMAP_ANON
242 #include <sys/types.h>
243 #include <sys/mman.h>
244 #include <asm/page.h> /* PAGE_SIZE */
245 #endif /* linux */
246
247 #if defined(CSRG_BASED)
248 #define HAS_MMAP_ANON
249 #define HAS_GETPAGESIZE
250 #include <sys/types.h>
251 #include <sys/mman.h>
252 #endif /* CSRG_BASED */
253
254 #if defined(SVR4)
255 #define MMAP_DEV_ZERO
256 #include <sys/types.h>
257 #include <sys/mman.h>
258 #include <unistd.h>
259 #endif /* SVR4 */
260
261 #if defined(sun) && !defined(SVR4) /* SunOS */
262 #define MMAP_DEV_ZERO /* doesn't SunOS have MAP_ANON ?? */
263 #define HAS_GETPAGESIZE
264 #include <sys/types.h>
265 #include <sys/mman.h>
266 #endif /* sun && !SVR4 */
267
268 #ifdef XNO_SYSCONF
269 #undef _SC_PAGESIZE
270 #endif
271
272 #if defined(HAS_MMAP_ANON) || defined (MMAP_DEV_ZERO)
273 static int pagesize;
274 #endif
275
276 #ifdef MMAP_DEV_ZERO
277 static int devzerofd = -1;
278 #include <errno.h>
279 #ifdef X_NOT_STDC_ENV
280 extern int errno;
281 #endif
282 #endif
283
284
285 unsigned long *
Xalloc(amount)286 Xalloc (amount)
287 unsigned long amount;
288 {
289 register unsigned long *ptr;
290 int indx;
291
292 /* sanity checks */
293
294 /* zero size requested */
295 if (amount == 0) {
296 LOG_ALLOC("Xalloc=0", amount, 0);
297 return (unsigned long *)NULL;
298 }
299 /* negative size (or size > 2GB) - what do we do? */
300 if ((long)amount < 0) {
301 /* Diagnostic */
302 #ifdef FATALERRORS
303 FatalError("Xalloc: Xalloc(<0)\n");
304 #else
305 ErrorF("Xalloc warning: Xalloc(<0) ignored..\n");
306 #endif
307 LOG_ALLOC("Xalloc<0", amount, 0);
308 return (unsigned long *)NULL;
309 }
310
311 /* alignment check */
312 #if defined(__alpha__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__)
313 amount = (amount + (sizeof(long)-1)) & ~(sizeof(long)-1);
314 #endif
315
316 if (amount <= MAX_SMALL) {
317 /*
318 * small block
319 */
320 /* pick a ready to use small chunk */
321 indx = (amount-1) / SIZE_STEPS;
322 ptr = free_lists[indx];
323 if (NULL == ptr) {
324 /* list empty - get 20 or 40 more */
325 /* amount = size rounded up */
326 amount = (indx+1) * SIZE_STEPS;
327 ptr = (unsigned long *)calloc(1,(amount+SIZE_HEADER+TAIL_SIZE)
328 * (amount<100 ? 40 : 20));
329 if (NULL!=ptr) {
330 int i;
331 unsigned long *p1, *p2;
332 p2 = (unsigned long *)((char *)ptr + SIZE_HEADER);
333 for (i=0; i<(amount<100 ? 40 : 20); i++) {
334 p1 = p2;
335 p1[-2] = amount;
336 #ifdef XALLOC_DEBUG
337 p1[-1] = MAGIC;
338 #endif /* XALLOC_DEBUG */
339 #ifdef SIZE_TAIL
340 *(unsigned long *)((unsigned char *)p1 + amount) = MAGIC2;
341 #endif /* SIZE_TAIL */
342 p2 = (unsigned long *)((char *)p1 + SIZE_HEADER + amount + TAIL_SIZE);
343 *(unsigned long **)p1 = p2;
344 }
345 /* last one has no next one */
346 *(unsigned long **)p1 = NULL;
347 /* put the second in the list */
348 free_lists[indx] = (unsigned long *)((char *)ptr + SIZE_HEADER + amount + TAIL_SIZE + SIZE_HEADER);
349 /* take the fist one */
350 ptr = (unsigned long *)((char *)ptr + SIZE_HEADER);
351 LOG_ALLOC("Xalloc-S", amount, ptr);
352 return ptr;
353 } /* else fall through to 'Out of memory' */
354 } else {
355 /* take that piece of mem out of the list */
356 free_lists[indx] = *((unsigned long **)ptr);
357 /* already has size (and evtl. magic) filled in */
358 LOG_ALLOC("Xalloc-S", amount, ptr);
359 return ptr;
360 }
361
362 #if defined(HAS_MMAP_ANON) || defined(MMAP_DEV_ZERO)
363 } else if (amount >= MIN_LARGE) {
364 /*
365 * large block
366 */
367 /* mmapped malloc */
368 /* round up amount */
369 amount += SIZE_HEADER + TAIL_SIZE;
370 /* round up brutto amount to a multiple of the page size */
371 amount = (amount + pagesize-1) & ~(pagesize-1);
372 #ifdef MMAP_DEV_ZERO
373 ptr = (unsigned long *)mmap((caddr_t)0,
374 (size_t)amount,
375 PROT_READ | PROT_WRITE,
376 MAP_PRIVATE,
377 devzerofd,
378 (off_t)0);
379 #else
380 ptr = (unsigned long *)mmap((caddr_t)0,
381 (size_t)amount,
382 PROT_READ | PROT_WRITE,
383 MAP_ANON | MAP_PRIVATE,
384 -1,
385 (off_t)0);
386 #endif
387 if (-1!=(long)ptr) {
388 ptr[0] = amount - SIZE_HEADER - TAIL_SIZE;
389 #ifdef XALLOC_DEBUG
390 ptr[1] = MAGIC;
391 #endif /* XALLOC_DEBUG */
392 #ifdef SIZE_TAIL
393 # ifdef __hppa__
394 /* reserved space for 2 * sizeof(long), so use correct one */
395 /* see SIZE_TAIL macro */
396 ((unsigned long *)((char *)ptr + amount))[-2] = MAGIC2;
397 # else
398 ((unsigned long *)((char *)ptr + amount))[-1] = MAGIC2;
399 # endif /* __hppa__ */
400 #endif /* SIZE_TAIL */
401 ptr = (unsigned long *)((char *)ptr + SIZE_HEADER);
402 LOG_ALLOC("Xalloc-L", amount, ptr);
403 return ptr;
404 } /* else fall through to 'Out of memory' */
405 #endif /* HAS_MMAP_ANON || MMAP_DEV_ZERO */
406 } else {
407 /*
408 * medium sized block
409 */
410 /* 'normal' malloc() */
411 ptr=(unsigned long *)calloc(1,amount+SIZE_HEADER+TAIL_SIZE);
412 if (ptr != (unsigned long *)NULL) {
413 ptr[0] = amount;
414 #ifdef XALLOC_DEBUG
415 ptr[1] = MAGIC;
416 #endif /* XALLOC_DEBUG */
417 #ifdef SIZE_TAIL
418 *(unsigned long *)((char *)ptr + amount + SIZE_HEADER) = MAGIC2;
419 #endif /* SIZE_TAIL */
420 ptr = (unsigned long *)((char *)ptr + SIZE_HEADER);
421 LOG_ALLOC("Xalloc-M", amount, ptr);
422 return ptr;
423 }
424 }
425 if (Must_have_memory)
426 FatalError("Out of memory");
427 LOG_ALLOC("Xalloc-oom", amount, 0);
428 return (unsigned long *)NULL;
429 }
430
431 /*****************
432 * XNFalloc
433 * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory
434 *****************/
435
436 unsigned long *
XNFalloc(amount)437 XNFalloc (amount)
438 unsigned long amount;
439 {
440 register unsigned long *ptr;
441
442 /* zero size requested */
443 if (amount == 0) {
444 LOG_ALLOC("XNFalloc=0", amount, 0);
445 return (unsigned long *)NULL;
446 }
447 /* negative size (or size > 2GB) - what do we do? */
448 if ((long)amount < 0) {
449 /* Diagnostic */
450 #ifdef FATALERRORS
451 FatalError("Xalloc: XNFalloc(<0)\n");
452 #else
453 ErrorF("Xalloc warning: XNFalloc(<0) ignored..\n");
454 #endif
455 LOG_ALLOC("XNFalloc<0", amount, 0);
456 return (unsigned long *)NULL;
457 }
458 ptr = Xalloc(amount);
459 if (!ptr)
460 {
461 FatalError("Out of memory");
462 }
463 return ptr;
464 }
465
466 /*****************
467 * Xcalloc
468 *****************/
469
470 unsigned long *
Xcalloc(amount)471 Xcalloc (amount)
472 unsigned long amount;
473 {
474 unsigned long *ret;
475
476 ret = Xalloc (amount);
477 if (ret
478 #if defined(HAS_MMAP_ANON) || defined(MMAP_DEV_ZERO)
479 && (amount < MIN_LARGE) /* mmaped anonymous mem is already cleared */
480 #endif
481 )
482 bzero ((char *) ret, (int) amount);
483 return ret;
484 }
485
486 /*****************
487 * Xrealloc
488 *****************/
489
490 unsigned long *
Xrealloc(ptr,amount)491 Xrealloc (ptr, amount)
492 register pointer ptr;
493 unsigned long amount;
494 {
495 register unsigned long *new_ptr;
496
497 /* zero size requested */
498 if (amount == 0) {
499 if (ptr)
500 Xfree(ptr);
501 LOG_REALLOC("Xrealloc=0", ptr, amount, 0);
502 return (unsigned long *)NULL;
503 }
504 /* negative size (or size > 2GB) - what do we do? */
505 if ((long)amount < 0) {
506 /* Diagnostic */
507 #ifdef FATALERRORS
508 FatalError("Xalloc: Xrealloc(<0)\n");
509 #else
510 ErrorF("Xalloc warning: Xrealloc(<0) ignored..\n");
511 #endif
512 if (ptr)
513 Xfree(ptr); /* ?? */
514 LOG_REALLOC("Xrealloc<0", ptr, amount, 0);
515 return (unsigned long *)NULL;
516 }
517
518 new_ptr = Xalloc(amount);
519 if ( (new_ptr) && (ptr) ) {
520 unsigned long old_size;
521 old_size = ((unsigned long *)ptr)[-2];
522 #ifdef XALLOC_DEBUG
523 if (MAGIC != ((unsigned long *)ptr)[-1]) {
524 #ifdef FATALERRORS
525 FatalError("Xalloc error: header corrupt in Xrealloc() :-(\n");
526 #else
527 ErrorF("Xalloc error: header corrupt in Xrealloc() :-(\n");
528 #endif
529 LOG_REALLOC("Xalloc error: header corrupt in Xrealloc() :-(",
530 ptr, amount, 0);
531 return (unsigned long *)NULL;
532 }
533 #endif /* XALLOC_DEBUG */
534 /* copy min(old size, new size) */
535 memcpy((char *)new_ptr, (char *)ptr, (amount < old_size ? amount : old_size));
536 }
537 if (ptr)
538 Xfree(ptr);
539 if (new_ptr) {
540 LOG_REALLOC("Xrealloc", ptr, amount, new_ptr);
541 return new_ptr;
542 }
543 if (Must_have_memory)
544 FatalError("Out of memory");
545 LOG_REALLOC("Xrealloc", ptr, amount, 0);
546 return (unsigned long *)NULL;
547 }
548
549 /*****************
550 * XNFrealloc
551 * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory
552 *****************/
553
554 unsigned long *
XNFrealloc(ptr,amount)555 XNFrealloc (ptr, amount)
556 register pointer ptr;
557 unsigned long amount;
558 {
559 if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL)
560 {
561 FatalError( "Out of memory" );
562 }
563 return ((unsigned long *)ptr);
564 }
565
566 /*****************
567 * Xfree
568 * calls free
569 *****************/
570
571 void
Xfree(ptr)572 Xfree(ptr)
573 register pointer ptr;
574 {
575 unsigned long size;
576 unsigned long *pheader;
577
578 /* free(NULL) IS valid :-( - and widely used throughout the server.. */
579 if (!ptr)
580 return;
581
582 pheader = (unsigned long *)((char *)ptr - SIZE_HEADER);
583 #ifdef XALLOC_DEBUG
584 if (MAGIC != pheader[1]) {
585 /* Diagnostic */
586 #ifdef FATALERRORS
587 FatalError("Xalloc error: Header corrupt in Xfree() :-(\n");
588 #else
589 ErrorF("Xalloc error: Header corrupt in Xfree() :-(\n");
590 #endif
591 LOG_FREE("Xalloc error: Header corrupt in Xfree() :-(", ptr);
592 return;
593 }
594 #endif /* XALLOC_DEBUG */
595
596 size = pheader[0];
597 if (size <= MAX_SMALL) {
598 int indx;
599 /*
600 * small block
601 */
602 #ifdef SIZE_TAIL
603 if (MAGIC2 != *(unsigned long *)((char *)ptr + size)) {
604 /* Diagnostic */
605 #ifdef FATALERRORS
606 FatalError("Xalloc error: Tail corrupt in Xfree() for small block (adr=0x%x, val=0x%x)\n",(char *)ptr + size,*(unsigned long *)((char *)ptr + size));
607 #else
608 ErrorF("Xalloc error: Tail corrupt in Xfree() for small block (adr=0x%x, val=0x%x)\n",(char *)ptr + size,*(unsigned long *)((char *)ptr + size));
609 #endif
610 LOG_FREE("Xalloc error: Tail corrupt in Xfree() for small block", ptr);
611 return;
612 }
613 #endif /* SIZE_TAIL */
614
615 #ifdef XFREE_ERASES
616 memset(ptr,0xF0,size);
617 #endif /* XFREE_ERASES */
618
619 /* put this small block at the head of the list */
620 indx = (size-1) / SIZE_STEPS;
621 *(unsigned long **)(ptr) = free_lists[indx];
622 free_lists[indx] = (unsigned long *)ptr;
623 LOG_FREE("Xfree", ptr);
624 return;
625
626 #if defined(HAS_MMAP_ANON) || defined(MMAP_DEV_ZERO)
627 } else if (size >= MIN_LARGE) {
628 /*
629 * large block
630 */
631 #ifdef SIZE_TAIL
632 if (MAGIC2 != ((unsigned long *)((char *)ptr + size))[0]) {
633 /* Diagnostic */
634 #ifdef FATALERRORS
635 FatalError("Xalloc error: Tail corrupt in Xfree() for big block (adr=0x%x, val=0x%x)\n",(char *)ptr+size,((unsigned long *)((char *)ptr + size))[0]);
636 #else
637 ErrorF("Xalloc error: Tail corrupt in Xfree() for big block (adr=0x%x, val=0x%x)\n",(char *)ptr+size,((unsigned long *)((char *)ptr + size))[0]);
638 #endif
639 LOG_FREE("Xalloc error: Tail corrupt in Xfree() for big block", ptr);
640 return;
641 }
642 size += SIZE_TAIL;
643 #endif /* SIZE_TAIL */
644
645 LOG_FREE("Xfree", ptr);
646 size += SIZE_HEADER;
647 munmap((caddr_t)pheader, (size_t)size);
648 /* no need to clear - mem is inaccessible after munmap.. */
649 #endif /* HAS_MMAP_ANON */
650
651 } else {
652 /*
653 * medium sized block
654 */
655 #ifdef SIZE_TAIL
656 if (MAGIC2 != *(unsigned long *)((char *)ptr + size)) {
657 /* Diagnostic */
658 #ifdef FATALERRORS
659 FatalError("Xalloc error: Tail corrupt in Xfree() for medium block (adr=0x%x, val=0x%x)\n",(char *)ptr + size,*(unsigned long *)((char *)ptr + size));
660 #else
661 ErrorF("Xalloc error: Tail corrupt in Xfree() for medium block (adr=0x%x, val=0x%x)\n",(char *)ptr + size,*(unsigned long *)((char *)ptr + size));
662 #endif
663 LOG_FREE("Xalloc error: Tail corrupt in Xfree() for medium block", ptr);
664 return;
665 }
666 #endif /* SIZE_TAIL */
667
668 #ifdef XFREE_ERASES
669 memset(pheader,0xF0,size+SIZE_HEADER);
670 #endif /* XFREE_ERASES */
671
672 LOG_FREE("Xfree", ptr);
673 free((char *)pheader);
674 }
675 }
676
677 void
OsInitAllocator()678 OsInitAllocator ()
679 {
680 static Bool beenhere = FALSE;
681
682 if (beenhere)
683 return;
684 beenhere = TRUE;
685
686 #if defined(HAS_MMAP_ANON) || defined (MMAP_DEV_ZERO)
687 #if defined(_SC_PAGESIZE) /* || defined(linux) */
688 pagesize = sysconf(_SC_PAGESIZE);
689 #else
690 #ifdef HAS_GETPAGESIZE
691 pagesize = getpagesize();
692 #else
693 pagesize = PAGE_SIZE;
694 #endif
695 #endif
696 #endif
697
698 /* set up linked lists of free blocks */
699 bzero ((char *) free_lists, MAX_SMALL/SIZE_STEPS*sizeof(unsigned long *));
700
701 #ifdef MMAP_DEV_ZERO
702 /* open /dev/zero on systems that have mmap, but not MAP_ANON */
703 if (devzerofd < 0) {
704 if ((devzerofd = open("/dev/zero", O_RDWR, 0)) < 0)
705 FatalError("OsInitAllocator: Cannot open /dev/zero (errno=%d)\n",
706 errno);
707 }
708 #endif
709
710 #ifdef XALLOC_LOG
711 /* reset the log file to zero length */
712 {
713 FILE *f;
714 f = fopen(XALLOC_LOG_FILE, "w");
715 if (NULL!=f)
716 fclose(f);
717 }
718 #endif
719 }
720
721 #else /* !INTERNAL_MALLOC */
722 /* This is to avoid an empty .o */
723 static int no_internal_xalloc;
724 #endif /* INTERNAL_MALLOC */
725