OSDN Git Service

just drop all of the debug code
[uclinux-h8/uClibc.git] / libc / stdlib / malloc-standard / memalign.c
1 /*
2   This is a version (aka dlmalloc) of malloc/free/realloc written by
3   Doug Lea and released to the public domain.  Use, modify, and
4   redistribute this code without permission or acknowledgement in any
5   way you wish.  Send questions, comments, complaints, performance
6   data, etc to dl@cs.oswego.edu
7
8   VERSION 2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
9
10   Note: There may be an updated version of this malloc obtainable at
11            ftp://gee.cs.oswego.edu/pub/misc/malloc.c
12   Check before installing!
13
14   Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
15 */
16
17 #include <features.h>
18 #include <stddef.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <string.h>
22 #include "malloc.h"
23
24
25 /* ------------------------------ memalign ------------------------------ */
26 void* memalign(size_t alignment, size_t bytes)
27 {
28     size_t nb;             /* padded  request size */
29     char*           m;              /* memory returned by malloc call */
30     mchunkptr       p;              /* corresponding chunk */
31     char*           _brk;            /* alignment point within p */
32     mchunkptr       newp;           /* chunk to return */
33     size_t newsize;        /* its size */
34     size_t leadsize;       /* leading space before alignment point */
35     mchunkptr       remainder;      /* spare room at end to split off */
36     unsigned long    remainder_size; /* its size */
37     size_t size;
38
39     /* If need less alignment than we give anyway, just relay to malloc */
40
41     if (alignment <= MALLOC_ALIGNMENT) return malloc(bytes);
42
43     /* Otherwise, ensure that it is at least a minimum chunk size */
44
45     if (alignment <  MINSIZE) alignment = MINSIZE;
46
47     /* Make sure alignment is power of 2 (in case MINSIZE is not).  */
48     if ((alignment & (alignment - 1)) != 0) {
49         size_t a = MALLOC_ALIGNMENT * 2;
50         while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
51         alignment = a;
52     }
53
54     LOCK;
55     checked_request2size(bytes, nb);
56
57     /* Strategy: find a spot within that chunk that meets the alignment
58      * request, and then possibly free the leading and trailing space.  */
59
60
61     /* Call malloc with worst case padding to hit alignment. */
62
63     m  = (char*)(malloc(nb + alignment + MINSIZE));
64
65     if (m == 0) {
66         UNLOCK;
67         return 0; /* propagate failure */
68     }
69
70     p = mem2chunk(m);
71
72     if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */
73
74         /*
75            Find an aligned spot inside chunk.  Since we need to give back
76            leading space in a chunk of at least MINSIZE, if the first
77            calculation places us at a spot with less than MINSIZE leader,
78            we can move to the next aligned spot -- we've allocated enough
79            total room so that this is always possible.
80            */
81
82         _brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) &
83                     -((signed long) alignment)));
84         if ((unsigned long)(_brk - (char*)(p)) < MINSIZE)
85             _brk += alignment;
86
87         newp = (mchunkptr)_brk;
88         leadsize = _brk - (char*)(p);
89         newsize = chunksize(p) - leadsize;
90
91         /* For mmapped chunks, just adjust offset */
92         if (chunk_is_mmapped(p)) {
93             newp->prev_size = p->prev_size + leadsize;
94             set_head(newp, newsize|IS_MMAPPED);
95             UNLOCK;
96             return chunk2mem(newp);
97         }
98
99         /* Otherwise, give back leader, use the rest */
100         set_head(newp, newsize | PREV_INUSE);
101         set_inuse_bit_at_offset(newp, newsize);
102         set_head_size(p, leadsize);
103         free(chunk2mem(p));
104         p = newp;
105
106         assert (newsize >= nb &&
107                 (((unsigned long)(chunk2mem(p))) % alignment) == 0);
108     }
109
110     /* Also give back spare room at the end */
111     if (!chunk_is_mmapped(p)) {
112         size = chunksize(p);
113         if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
114             remainder_size = size - nb;
115             remainder = chunk_at_offset(p, nb);
116             set_head(remainder, remainder_size | PREV_INUSE);
117             set_head_size(p, nb);
118             free(chunk2mem(remainder));
119         }
120     }
121
122     check_inuse_chunk(p);
123     UNLOCK;
124     return chunk2mem(p);
125 }
126