source: trunk/libs/newlib/src/newlib/libc/machine/powerpc/vec_mallocr.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 11.5 KB
Line 
1/* This code is based on mallocr.c written by Doug Lea which is released
2   to the public domain.  Any changes to libc/stdlib/mallocr.c
3   should be reflected here as well.    */
4
5/* Preliminaries */
6
7#ifndef __STD_C
8#ifdef __STDC__
9#define __STD_C     1
10#else
11#if __cplusplus
12#define __STD_C     1
13#else
14#define __STD_C     0
15#endif /*__cplusplus*/
16#endif /*__STDC__*/
17#endif /*__STD_C*/
18
19#ifndef Void_t
20#if __STD_C
21#define Void_t      void
22#else
23#define Void_t      char
24#endif
25#endif /*Void_t*/
26
27#if __STD_C
28#include <stddef.h>   /* for size_t */
29#else
30#include <sys/types.h>
31#endif
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37#include <sys/config.h>
38
39/*
40  In newlib, all the publically visible routines take a reentrancy
41  pointer.  We don't currently do anything much with it, but we do
42  pass it to the lock routine.
43 */
44
45#include <reent.h>
46#include <string.h>
47#include <malloc.h>
48
49#define MALLOC_LOCK __malloc_lock(reent_ptr)
50#define MALLOC_UNLOCK __malloc_unlock(reent_ptr)
51
52#ifdef SMALL_MEMORY
53#define malloc_getpagesize (128)
54#else
55#define malloc_getpagesize (4096)
56#endif
57
58#if __STD_C
59extern void __malloc_lock(struct _reent *);
60extern void __malloc_unlock(struct _reent *);
61#else
62extern void __malloc_lock();
63extern void __malloc_unlock();
64#endif
65
66#if __STD_C
67#define RARG struct _reent *reent_ptr,
68#define RONEARG struct _reent *reent_ptr
69#else
70#define RARG reent_ptr
71#define RONEARG reent_ptr
72#define RDECL struct _reent *reent_ptr;
73#endif
74
75#define RCALL reent_ptr,
76#define RONECALL reent_ptr
77
78/*
79   Define MALLOC_LOCK and MALLOC_UNLOCK to C expressions to run to
80   lock and unlock the malloc data structures.  MALLOC_LOCK may be
81   called recursively.
82 */
83
84#ifndef MALLOC_LOCK
85#define MALLOC_LOCK
86#endif
87
88#ifndef MALLOC_UNLOCK
89#define MALLOC_UNLOCK
90#endif
91
92/*
93  INTERNAL_SIZE_T is the word-size used for internal bookkeeping
94  of chunk sizes. On a 64-bit machine, you can reduce malloc
95  overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
96  at the expense of not being able to handle requests greater than
97  2^31. This limitation is hardly ever a concern; you are encouraged
98  to set this. However, the default version is the same as size_t.
99*/
100
101#ifndef INTERNAL_SIZE_T
102#define INTERNAL_SIZE_T size_t
103#endif
104
105/*
106  Following is needed on implementations whereby long > size_t.
107  The problem is caused because the code performs subtractions of
108  size_t values and stores the result in long values.  In the case
109  where long > size_t and the first value is actually less than
110  the second value, the resultant value is positive.  For example,
111  (long)(x - y) where x = 0 and y is 1 ends up being 0x00000000FFFFFFFF
112  which is 2*31 - 1 instead of 0xFFFFFFFFFFFFFFFF.  This is due to the
113  fact that assignment from unsigned to signed won't sign extend.
114*/
115
116#ifdef SIZE_T_SMALLER_THAN_LONG
117#define long_sub_size_t(x, y) ( (x < y) ? -((long)(y - x)) : (x - y) );
118#else
119#define long_sub_size_t(x, y) ( (long)(x - y) )
120#endif
121
122/*
123  REALLOC_ZERO_BYTES_FREES should be set if a call to
124  realloc with zero bytes should be the same as a call to free.
125  Some people think it should. Otherwise, since this malloc
126  returns a unique pointer for malloc(0), so does realloc(p, 0).
127*/
128
129/* The following macros are only invoked with (2n+1)-multiples of
130   INTERNAL_SIZE_T units, with a positive integer n. This is exploited
131   for fast inline execution when n is small. */
132
133#define MALLOC_ZERO(charp, nbytes)                                            \
134do {                                                                          \
135  INTERNAL_SIZE_T mzsz = (nbytes);                                            \
136  if(mzsz <= 9*sizeof(mzsz)) {                                                \
137    INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp);                         \
138    if(mzsz >= 5*sizeof(mzsz)) {     *mz++ = 0;                               \
139                                     *mz++ = 0;                               \
140      if(mzsz >= 7*sizeof(mzsz)) {   *mz++ = 0;                               \
141                                     *mz++ = 0;                               \
142        if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0;                               \
143                                     *mz++ = 0; }}}                           \
144                                     *mz++ = 0;                               \
145                                     *mz++ = 0;                               \
146                                     *mz   = 0;                               \
147  } else memset((charp), 0, mzsz);                                            \
148} while(0)
149
150#define MALLOC_COPY(dest,src,nbytes)                                          \
151do {                                                                          \
152  INTERNAL_SIZE_T mcsz = (nbytes);                                            \
153  if(mcsz <= 9*sizeof(mcsz)) {                                                \
154    INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src);                        \
155    INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest);                       \
156    if(mcsz >= 5*sizeof(mcsz)) {     *mcdst++ = *mcsrc++;                     \
157                                     *mcdst++ = *mcsrc++;                     \
158      if(mcsz >= 7*sizeof(mcsz)) {   *mcdst++ = *mcsrc++;                     \
159                                     *mcdst++ = *mcsrc++;                     \
160        if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++;                     \
161                                     *mcdst++ = *mcsrc++; }}}                 \
162                                     *mcdst++ = *mcsrc++;                     \
163                                     *mcdst++ = *mcsrc++;                     \
164                                     *mcdst   = *mcsrc  ;                     \
165  } else memcpy(dest, src, mcsz);                                             \
166} while(0)
167
168#define vECCALLOc       _vec_calloc_r
169#define fREe            _free_r
170#define mEMALIGn        _memalign_r
171#define vECREALLOc      _vec_realloc_r
172#
173#if __STD_C
174
175Void_t* vECREALLOc(RARG Void_t*, size_t);
176Void_t* vECCALLOc(RARG size_t, size_t);
177#else
178Void_t* vECREALLOc();
179Void_t* vECCALLOc();
180#endif
181
182
183#ifdef __cplusplus
184};  /* end of extern "C" */
185#endif
186
187/*
188  Type declarations
189*/
190
191struct malloc_chunk
192{
193  INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
194  INTERNAL_SIZE_T size;      /* Size in bytes, including overhead. */
195  struct malloc_chunk* fd;   /* double links -- used only if free. */
196  struct malloc_chunk* bk;
197};
198
199typedef struct malloc_chunk* mchunkptr;
200
201/*  sizes, alignments */
202
203#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
204#define MALLOC_ALIGN           16
205#define MALLOC_ALIGNMENT       16
206#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)
207#define MINSIZE                (sizeof(struct malloc_chunk))
208
209/* conversion from malloc headers to user pointers, and back */
210
211#define chunk2mem(p)   ((Void_t*)((char*)(p) + 2*SIZE_SZ))
212#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
213/* pad request bytes into a usable size */
214
215#define request2size(req) \
216 (((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \
217  (long)(MINSIZE + MALLOC_ALIGN_MASK)) ? ((MINSIZE + MALLOC_ALIGN_MASK) & ~(MALLOC_ALIGN_MASK)) : \
218   (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))
219
220
221/* Check if m has acceptable alignment */
222
223#define aligned_OK(m)    (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
224
225/*
226  Physical chunk operations 
227*/
228
229
230/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
231
232#define PREV_INUSE 0x1
233
234/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
235
236#define IS_MMAPPED 0x2
237
238/* Bits to mask off when extracting size */
239
240#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
241
242
243/* Ptr to next physical malloc_chunk. */
244
245#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
246
247/* Ptr to previous physical malloc_chunk */
248
249#define prev_chunk(p)\
250   ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
251
252
253/* Treat space at ptr + offset as a chunk */
254
255#define chunk_at_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
256
257
258
259
260/*
261  Dealing with use bits
262*/
263
264/* extract p's inuse bit */
265
266#define inuse(p)\
267((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
268
269/* extract inuse bit of previous chunk */
270
271#define prev_inuse(p)  ((p)->size & PREV_INUSE)
272
273/* check for mmap()'ed chunk */
274
275#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
276
277/* set/clear chunk as in use without otherwise disturbing */
278
279#define set_inuse(p)\
280((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
281
282#define clear_inuse(p)\
283((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
284
285/* check/set/clear inuse bits in known places */
286
287#define inuse_bit_at_offset(p, s)\
288 (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
289
290#define set_inuse_bit_at_offset(p, s)\
291 (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
292
293#define clear_inuse_bit_at_offset(p, s)\
294 (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
295
296
297
298/*
299  Dealing with size fields
300*/
301
302/* Get size, ignoring use bits */
303
304#define chunksize(p)          ((p)->size & ~(SIZE_BITS))
305
306/* Set size at head, without disturbing its use bit */
307
308#define set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
309
310/* Set size/use ignoring previous bits in header */
311
312#define set_head(p, s)        ((p)->size = (s))
313
314
315
316#ifdef DEFINE_VECREALLOC
317
318
319#if __STD_C
320Void_t* vECREALLOc(RARG Void_t* oldmem, size_t bytes)
321#else
322Void_t* vECREALLOc(RARG oldmem, bytes) RDECL Void_t* oldmem; size_t bytes;
323#endif
324{
325  INTERNAL_SIZE_T    nb;      /* padded request size */
326
327  mchunkptr oldp;             /* chunk corresponding to oldmem */
328  INTERNAL_SIZE_T    oldsize; /* its size */
329
330  mchunkptr newp;             /* chunk to return */
331  INTERNAL_SIZE_T    newsize; /* its size */
332  Void_t*   newmem;           /* corresponding user mem */
333
334  mchunkptr remainder;        /* holds split off extra space from newp */
335  INTERNAL_SIZE_T  remainder_size;   /* its size */
336
337#ifdef REALLOC_ZERO_BYTES_FREES
338  if (bytes == 0) { fREe(RCALL oldmem); return 0; }
339#endif
340
341
342  /* realloc of null is supposed to be same as malloc */
343  if (oldmem == 0) return mEMALIGn(RCALL 16, bytes);
344
345  MALLOC_LOCK;
346
347  newp    = oldp    = mem2chunk(oldmem);
348  newsize = oldsize = chunksize(oldp);
349
350  nb = request2size(bytes);
351
352  if ((long)(oldsize) < (long)(nb)) 
353  {
354    /* Must allocate */
355
356    newmem = mEMALIGn (RCALL 16, bytes);
357
358    if (newmem == 0)  /* propagate failure */
359    {
360      MALLOC_UNLOCK;
361      return 0;
362    }
363
364    /* copy, free, and exit */
365    MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
366    fREe(RCALL oldmem);
367    MALLOC_UNLOCK;
368    return newmem;
369  }
370
371  remainder_size = long_sub_size_t(newsize, nb);
372
373  if (remainder_size >= (long)MINSIZE) /* split off remainder */
374  {
375    remainder = chunk_at_offset(newp, nb);
376    set_head_size(newp, nb);
377    set_head(remainder, remainder_size | PREV_INUSE);
378    set_inuse_bit_at_offset(remainder, remainder_size);
379    fREe(RCALL chunk2mem(remainder)); /* let free() deal with it */
380  }
381  else
382  {
383    set_head_size(newp, newsize);
384    set_inuse_bit_at_offset(newp, newsize);
385  }
386
387  MALLOC_UNLOCK;
388  return chunk2mem(newp);
389}
390
391#endif /* DEFINE_VECREALLOC */
392
393
394#ifdef DEFINE_VECCALLOC
395
396/*
397
398  calloc calls malloc, then zeroes out the allocated chunk.
399
400*/
401
402#if __STD_C
403Void_t* vECCALLOc(RARG size_t n, size_t elem_size)
404#else
405Void_t* vECCALLOc(RARG n, elem_size) RDECL size_t n; size_t elem_size;
406#endif
407{
408  INTERNAL_SIZE_T sz = n * elem_size;
409
410  Void_t* mem;
411
412  mem = mEMALIGn (RCALL 16, sz);
413
414  if (mem == 0) 
415  {
416    return 0;
417  }
418
419  MALLOC_ZERO(mem, sz);
420  return mem;
421}
422
423#endif /* DEFINE_VECCALLOC */
424
Note: See TracBrowser for help on using the repository browser.