~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/os/xalloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

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