2002-04-19 Jeff Johnston <jjohnstn@redhat.com>

*  configure.host: Add support for powerpc-eabialtivec*.
        *  libc/include/malloc.h: Add include of <machine/malloc.h>.
        *  libc/include/stdlib.h: Add include of <machine/stdlib.h>.
        *  libc/include/machine/malloc.h: New file.
        *  libc/include/machine/stdlib.h: Ditto.
        *  libc/include/machine/setjmp.h: Add support for powerpc altivec.
        *  libc/machine/powerpc/Makefile.am: Add conditional objects and
        sources based on configuration.
        *  libc/machine/powerpc/Makefile.in: Regenerated.
        *  libc/machine/powerpc/configure: Ditto.
        *  libc/machine/powerpc/configure.in: Add check for
        powerpc-eabialtivec* in which case add in additional source files.
        *  libc/machine/powerpc/setjmp.S: Add altivec support.
        *  libc/machine/powerpc/vec_calloc.c: New file.
        *  libc/machine/powerpc/vec_free.c: Ditto.
        *  libc/machine/powerpc/vec_malloc.c: Ditto.
        *  libc/machine/powerpc/vec_mallocr.c: Ditto.
        *  libc/machine/powerpc/vec_realloc.c: Ditto.
        *  libc/machine/powerpc/machine/malloc.h: Ditto.
        *  libc/machine/powerpc/machine/stdlib.h: Ditto.
        *  libc/machine/powerpc/vfprintf.c: New file that is vfprintf.c
        with added altivec format specifiers.
        *  libc/machine/powerpc/vfscanf.c: New file that is vfscanf.c with
        added altivec format specifiers.
This commit is contained in:
Jeff Johnston 2002-04-19 19:16:22 +00:00
parent d413aadcaf
commit 0d844014bf
21 changed files with 3350 additions and 6 deletions

View File

@ -1,3 +1,30 @@
2002-04-19 Jeff Johnston <jjohnstn@redhat.com>
* configure.host: Add support for powerpc-eabialtivec*.
* libc/include/malloc.h: Add include of <machine/malloc.h>.
* libc/include/stdlib.h: Add include of <machine/stdlib.h>.
* libc/include/machine/malloc.h: New file.
* libc/include/machine/stdlib.h: Ditto.
* libc/include/machine/setjmp.h: Add support for powerpc altivec.
* libc/machine/powerpc/Makefile.am: Add conditional objects and
sources based on configuration.
* libc/machine/powerpc/Makefile.in: Regenerated.
* libc/machine/powerpc/configure: Ditto.
* libc/machine/powerpc/configure.in: Add check for
powerpc-eabialtivec* in which case add in additional source files.
* libc/machine/powerpc/setjmp.S: Add altivec support.
* libc/machine/powerpc/vec_calloc.c: New file.
* libc/machine/powerpc/vec_free.c: Ditto.
* libc/machine/powerpc/vec_malloc.c: Ditto.
* libc/machine/powerpc/vec_mallocr.c: Ditto.
* libc/machine/powerpc/vec_realloc.c: Ditto.
* libc/machine/powerpc/machine/malloc.h: Ditto.
* libc/machine/powerpc/machine/stdlib.h: Ditto.
* libc/machine/powerpc/vfprintf.c: New file that is vfprintf.c
with added altivec format specifiers.
* libc/machine/powerpc/vfscanf.c: New file that is vfscanf.c with
added altivec format specifiers.
2002-04-19 Joel Sherrill <joel@OARcorp.com>
* libs/sys/rtems/crt0.c: Satisfy gcc's references to libc functions

View File

@ -477,6 +477,9 @@ case "${host}" in
mn10?00-*-*)
syscall_dir=syscalls
;;
powerpc*-*-eabialtivec*)
newlib_cflags="${newlib_cflags} -DMISSING_SYSCALL_NAMES -DWANT_PRINTF_LONG_LONG"
;;
powerpc*-*-eabi* | \
powerpc*-*-elf* | \
powerpc*-*-linux* | \

View File

@ -0,0 +1,8 @@
#ifndef _MACHMALLOC_H_
#define _MACHMALLOC_H_
/* place holder so platforms may add malloc.h extensions */
#endif /* _MACHMALLOC_H_ */

View File

@ -106,7 +106,11 @@ typedef int jmp_buf[_JBLEN];
#endif
#ifdef __PPC__
#ifdef __ALTIVEC__
#define _JBLEN 64
#else
#define _JBLEN 32
#endif
#define _JBTYPE double
#endif

View File

@ -0,0 +1,8 @@
#ifndef _MACHSTDLIB_H_
#define _MACHSTDLIB_H_
/* place holder so platforms may add stdlib.h extensions */
#endif /* _MACHSTDLIB_H_ */

View File

@ -9,6 +9,9 @@
#define __need_size_t
#include <stddef.h>
/* include any machine-specific extensions */
#include <machine/malloc.h>
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -17,7 +17,7 @@ extern "C" {
#include <stddef.h>
#include <sys/reent.h>
#include <machine/stdlib.h>
#ifndef __STRICT_ANSI__
#include <alloca.h>
#endif

View File

@ -7,6 +7,19 @@ INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
noinst_LIBRARIES = lib.a
lib_a_SOURCES = setjmp.S
lib_a_LIBADD = @extra_objs@
EXTRA_lib_a_SOURCES = @extra_sources@
lib_a_DEPENDENCIES = @extra_objs@
ACLOCAL_AMFLAGS = -I ../../..
ACLOCAL_AMFLAGS = -I ../../..
AM_CFLAGS = -I $(srcdir)/../../stdio
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
VEC_MALLOC_COMPILE = $(COMPILE) -DINTERNAL_NEWLIB
vec_reallocr.o: vec_mallocr.c
$(VEC_MALLOC_COMPILE) -DDEFINE_VECREALLOC -c $(srcdir)/vec_mallocr.c -o $@
vec_callocr.o: vec_mallocr.c
$(VEC_MALLOC_COMPILE) -DDEFINE_VECCALLOC -c $(srcdir)/vec_mallocr.c -o $@

View File

@ -72,6 +72,8 @@ PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
aext = @aext@
extra_objs = @extra_objs@
extra_sources = @extra_sources@
libm_machine_dir = @libm_machine_dir@
machine_dir = @machine_dir@
newlib_basedir = @newlib_basedir@
@ -85,9 +87,15 @@ INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
noinst_LIBRARIES = lib.a
lib_a_SOURCES = setjmp.S
lib_a_LIBADD = @extra_objs@
EXTRA_lib_a_SOURCES = @extra_sources@
lib_a_DEPENDENCIES = @extra_objs@
ACLOCAL_AMFLAGS = -I ../../..
ACLOCAL_AMFLAGS = -I ../../..
AM_CFLAGS = -I $(srcdir)/../../stdio
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
VEC_MALLOC_COMPILE = $(COMPILE) -DINTERNAL_NEWLIB
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
CONFIG_CLEAN_FILES =
@ -97,7 +105,6 @@ LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LIBS = @LIBS@
lib_a_LIBADD =
lib_a_OBJECTS = setjmp.o
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@ -110,7 +117,7 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
GZIP_ENV = --best
SOURCES = $(lib_a_SOURCES)
SOURCES = $(lib_a_SOURCES) $(EXTRA_lib_a_SOURCES)
OBJECTS = $(lib_a_OBJECTS)
all: all-redirect
@ -316,6 +323,12 @@ mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
vec_reallocr.o: vec_mallocr.c
$(VEC_MALLOC_COMPILE) -DDEFINE_VECREALLOC -c $(srcdir)/vec_mallocr.c -o $@
vec_callocr.o: vec_mallocr.c
$(VEC_MALLOC_COMPILE) -DDEFINE_VECCALLOC -c $(srcdir)/vec_mallocr.c -o $@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -1440,6 +1440,17 @@ fi
extra_objs=
extra_sources=
case $host in
powerpc*-*altivec*)
extra_objs="vfprintf.o vfscanf.o vec_malloc.o vec_calloc.o vec_free.o vec_realloc.o vec_reallocr.o vec_callocr.o"
extra_sources="vfprintf.c vfscanf.c vec_malloc.c vec_calloc.c vec_free.c vec_realloc.c vec_mallocr.c"
;;
esac
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
@ -1623,6 +1634,8 @@ s%@aext@%$aext%g
s%@libm_machine_dir@%$libm_machine_dir%g
s%@machine_dir@%$machine_dir%g
s%@sys_dir@%$sys_dir%g
s%@extra_objs@%$extra_objs%g
s%@extra_sources@%$extra_sources%g
CEOF
EOF

View File

@ -9,4 +9,15 @@ AC_CONFIG_AUX_DIR(../../../..)
NEWLIB_CONFIGURE(../../..)
extra_objs=
extra_sources=
case $host in
powerpc*-*altivec*)
extra_objs="vfprintf.o vfscanf.o vec_malloc.o vec_calloc.o vec_free.o vec_realloc.o vec_reallocr.o vec_callocr.o"
extra_sources="vfprintf.c vfscanf.c vec_malloc.c vec_calloc.c vec_free.c vec_realloc.c vec_mallocr.c"
;;
esac
AC_SUBST(extra_objs)
AC_SUBST(extra_sources)
AC_OUTPUT(Makefile)

View File

@ -0,0 +1,20 @@
#ifndef _MACHMALLOC_H_
#define _MACHMALLOC_H_
# if defined(__ALTIVEC__)
_PTR _EXFUN(vec_calloc,(size_t __nmemb, size_t __size));
_PTR _EXFUN(_vec_calloc_r,(struct _reent *, size_t __nmemb, size_t __size));
_VOID _EXFUN(vec_free,(_PTR));
#define _vec_freer _freer
_PTR _EXFUN(vec_malloc,(size_t __size));
#define _vec_mallocr _memalign_r
_PTR _EXFUN(vec_realloc,(_PTR __r, size_t __size));
_PTR _EXFUN(_vec_realloc_r,(struct _reent *, _PTR __r, size_t __size));
# endif /* __ALTIVEC__ */
#endif /* _MACHMALLOC_H_ */

View File

@ -0,0 +1,24 @@
#ifndef _MACHSTDLIB_H_
#define _MACHSTDLIB_H_
#ifndef __STRICT_ANSI__
# if defined(__ALTIVEC__)
_PTR _EXFUN(vec_calloc,(size_t __nmemb, size_t __size));
_PTR _EXFUN(_vec_calloc_r,(struct _reent *, size_t __nmemb, size_t __size));
_VOID _EXFUN(vec_free,(_PTR));
#define _vec_freer _freer
_PTR _EXFUN(vec_malloc,(size_t __size));
#define _vec_mallocr _memalign_r
_PTR _EXFUN(vec_realloc,(_PTR __r, size_t __size));
_PTR _EXFUN(_vec_realloc_r,(struct _reent *, _PTR __r, size_t __size));
# endif /* __ALTIVEC__ */
#endif /* !__STRICT_ANSI__ */
#endif /* _MACHSTDLIB_H_ */

View File

@ -1,11 +1,17 @@
/* This is a simple version of setjmp and longjmp for the PowerPC.
Ian Lance Taylor, Cygnus Support, 9 Feb 1994. */
Ian Lance Taylor, Cygnus Support, 9 Feb 1994.
Modified by Jeff Johnston, Red Hat Inc. 2 Oct 2001. */
#include "ppc-asm.h"
FUNC_START(setjmp)
#ifdef __ALTIVEC__
addi 3,3,15 # align Altivec to 16 byte boundary
rlwinm 3,3,0,0,27
#else
addi 3,3,7 # align to 8 byte boundary
rlwinm 3,3,0,0,28
#endif
stw 1,0(3) # offset 0
stwu 2,4(3) # offset 4
stwu 13,4(3) # offset 8
@ -56,14 +62,50 @@ FUNC_START(setjmp)
/* This requires a total of 21 * 4 + 18 * 8 + 4 + 4 + 4
bytes == 60 * 4 bytes == 240 bytes. */
#ifdef __ALTIVEC__
/* save Altivec vrsave and vr20-vr31 registers */
mfspr 4,256 # vrsave register
stwu 4,16(3) # offset 248
addi 3,3,8
stvx 20,0,3 # offset 256
addi 3,3,16
stvx 21,0,3 # offset 272
addi 3,3,16
stvx 22,0,3 # offset 288
addi 3,3,16
stvx 23,0,3 # offset 304
addi 3,3,16
stvx 24,0,3 # offset 320
addi 3,3,16
stvx 25,0,3 # offset 336
addi 3,3,16
stvx 26,0,3 # offset 352
addi 3,3,16
stvx 27,0,3 # offset 368
addi 3,3,16
stvx 28,0,3 # offset 384
addi 3,3,16
stvx 29,0,3 # offset 400
addi 3,3,16
stvx 30,0,3 # offset 416
addi 3,3,16
stvx 31,0,3 # offset 432
/* This requires a total of 240 + 8 + 8 + 12 * 16 == 448 bytes. */
#endif
li 3,0
blr
FUNC_END(setjmp)
FUNC_START(longjmp)
#ifdef __ALTIVEC__
addi 3,3,15 # align Altivec to 16 byte boundary
rlwinm 3,3,0,0,27
#else
addi 3,3,7 # align to 8 byte boundary
rlwinm 3,3,0,0,28
#endif
lwz 1,0(3) # offset 0
lwzu 2,4(3) # offset 4
lwzu 13,4(3) # offset 8
@ -111,6 +153,36 @@ FUNC_START(longjmp)
lfdu 31,8(3) # offset 232
#endif
#ifdef __ALTIVEC__
/* restore Altivec vrsave and v20-v31 registers */
lwzu 5,16(3) # offset 248
mtspr 256,5 # vrsave
addi 3,3,8
lvx 20,0,3 # offset 256
addi 3,3,16
lvx 21,0,3 # offset 272
addi 3,3,16
lvx 22,0,3 # offset 288
addi 3,3,16
lvx 23,0,3 # offset 304
addi 3,3,16
lvx 24,0,3 # offset 320
addi 3,3,16
lvx 25,0,3 # offset 336
addi 3,3,16
lvx 26,0,3 # offset 352
addi 3,3,16
lvx 27,0,3 # offset 368
addi 3,3,16
lvx 28,0,3 # offset 384
addi 3,3,16
lvx 29,0,3 # offset 400
addi 3,3,16
lvx 30,0,3 # offset 416
addi 3,3,16
lvx 31,0,3 # offset 432
#endif
mr. 3,4
bclr+ 4,2
li 3,1

View File

@ -0,0 +1,66 @@
/*
FUNCTION
<<vec_calloc>>---allocate space for arrays
INDEX
vec_calloc
INDEX
_vec_calloc_r
ANSI_SYNOPSIS
#include <stdlib.h>
void *vec_calloc(size_t <[n]>, size_t <[s]>);
void *vec_calloc_r(void *<[reent]>, size_t <n>, <size_t> <[s]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *vec_calloc(<[n]>, <[s]>)
size_t <[n]>, <[s]>;
char *_vec_calloc_r(<[reent]>, <[n]>, <[s]>)
char *<[reent]>;
size_t <[n]>;
size_t <[s]>;
DESCRIPTION
Use <<vec_calloc>> to request a block of memory sufficient to hold an
array of <[n]> elements, each of which has size <[s]>.
The memory allocated by <<vec_calloc>> comes out of the same memory pool
used by <<vec_malloc>>, but the memory block is initialized to all zero
bytes. (To avoid the overhead of initializing the space, use
<<vec_malloc>> instead.)
The alternate function <<_vec_calloc_r>> is reentrant.
The extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
If successful, a pointer to the newly allocated space.
If unsuccessful, <<NULL>>.
PORTABILITY
<<vec_calloc>> is an non-ANSI extension described in the AltiVec Programming
Interface Manual.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
#include <string.h>
#include <stdlib.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (vec_calloc, (n, size),
size_t n _AND
size_t size)
{
return _vec_calloc_r (_REENT, n, size);
}
#endif

View File

@ -0,0 +1,15 @@
/* vec_free.c - a wrapper for _free_r */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#ifndef _REENT_ONLY
void
_DEFUN (vec_free, (aptr),
_PTR aptr)
{
_free_r (_REENT, aptr);
}
#endif /* !_REENT_ONLY */

View File

@ -0,0 +1,132 @@
/*
FUNCTION
<<vec_malloc>>, <<vec_realloc>>, <<vec_free>>---manage vector memory
INDEX
vec_malloc
INDEX
vec_realloc
INDEX
vec_free
INDEX
_vec_malloc_r
INDEX
_vec_realloc_r
INDEX
_vec_free_r
ANSI_SYNOPSIS
#include <stdlib.h>
void *vec_malloc(size_t <[nbytes]>);
void *vec_realloc(void *<[aptr]>, size_t <[nbytes]>);
void vec_free(void *<[aptr]>);
void *_vec_malloc_r(void *<[reent]>, size_t <[nbytes]>);
void *_vec_realloc_r(void *<[reent]>,
void *<[aptr]>, size_t <[nbytes]>);
void _vec_free_r(void *<[reent]>, void *<[aptr]>);
TRAD_SYNOPSIS
#include <stdlib.h>
char *vec_malloc(<[nbytes]>)
size_t <[nbytes]>;
char *vec_realloc(<[aptr]>, <[nbytes]>)
char *<[aptr]>;
size_t <[nbytes]>;
void vec_free(<[aptr]>)
char *<[aptr]>;
char *_vec_malloc_r(<[reent]>,<[nbytes]>)
char *<[reent]>;
size_t <[nbytes]>;
char *_vec_realloc_r(<[reent]>, <[aptr]>, <[nbytes]>)
char *<[reent]>;
char *<[aptr]>;
size_t <[nbytes]>;
void _vec_free_r(<[reent]>, <[aptr]>)
char *<[reent]>;
char *<[aptr]>;
DESCRIPTION
These functions manage a pool of system memory that is 16-byte aligned..
Use <<vec_malloc>> to request allocation of an object with at least
<[nbytes]> bytes of storage available and is 16-byte aligned. If the space is
available, <<vec_malloc>> returns a pointer to a newly allocated block as its result.
If you already have a block of storage allocated by <<vec_malloc>>, but
you no longer need all the space allocated to it, you can make it
smaller by calling <<vec_realloc>> with both the object pointer and the
new desired size as arguments. <<vec_realloc>> guarantees that the
contents of the smaller object match the beginning of the original object.
Similarly, if you need more space for an object, use <<vec_realloc>> to
request the larger size; again, <<vec_realloc>> guarantees that the
beginning of the new, larger object matches the contents of the
original object.
When you no longer need an object originally allocated by <<vec_malloc>>
or <<vec_realloc>> (or the related function <<vec_calloc>>), return it to the
memory storage pool by calling <<vec_free>> with the address of the object
as the argument. You can also use <<vec_realloc>> for this purpose by
calling it with <<0>> as the <[nbytes]> argument.
The alternate functions <<_vec_malloc_r>>, <<_vec_realloc_r>>, <<_vec_free_r>>,
are reentrant versions. The extra argument <[reent]> is a pointer to a reentrancy
structure.
If you have multiple threads of execution which may call any of these
routines, or if any of these routines may be called reentrantly, then
you must provide implementations of the <<__vec_malloc_lock>> and
<<__vec_malloc_unlock>> functions for your system. See the documentation
for those functions.
These functions operate by calling the function <<_sbrk_r>> or
<<sbrk>>, which allocates space. You may need to provide one of these
functions for your system. <<_sbrk_r>> is called with a positive
value to allocate more space, and with a negative value to release
previously allocated space if it is no longer required.
@xref{Stubs}.
RETURNS
<<vec_malloc>> returns a pointer to the newly allocated space, if
successful; otherwise it returns <<NULL>>. If your application needs
to generate empty objects, you may use <<vec_malloc(0)>> for this purpose.
<<vec_realloc>> returns a pointer to the new block of memory, or <<NULL>>
if a new block could not be allocated. <<NULL>> is also the result
when you use `<<vec_realloc(<[aptr]>,0)>>' (which has the same effect as
`<<vec_free(<[aptr]>)>>'). You should always check the result of
<<vec_realloc>>; successful vec_reallocation is not guaranteed even when
you request a smaller object.
<<vec_free>> does not return a result.
PORTABILITY
<<vec_malloc>>, <<vec_realloc>>, and <<vec_free>> are all extensions
specified in the AltiVec Programming Interface Manual.
Supporting OS subroutines required: <<sbrk>>. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (vec_malloc, (nbytes),
size_t nbytes) /* get a block */
{
return _memalign_r (_REENT, 16, nbytes);
}
#endif

View File

@ -0,0 +1,424 @@
/* This code is based on mallocr.c written by Doug Lea which is released
to the public domain. Any changes to libc/stdlib/mallocr.c
should be reflected here as well. */
/* Preliminaries */
#ifndef __STD_C
#ifdef __STDC__
#define __STD_C 1
#else
#if __cplusplus
#define __STD_C 1
#else
#define __STD_C 0
#endif /*__cplusplus*/
#endif /*__STDC__*/
#endif /*__STD_C*/
#ifndef Void_t
#if __STD_C
#define Void_t void
#else
#define Void_t char
#endif
#endif /*Void_t*/
#if __STD_C
#include <stddef.h> /* for size_t */
#else
#include <sys/types.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/config.h>
/*
In newlib, all the publically visible routines take a reentrancy
pointer. We don't currently do anything much with it, but we do
pass it to the lock routine.
*/
#include <reent.h>
#include <string.h>
#include <malloc.h>
#define MALLOC_LOCK __malloc_lock(reent_ptr)
#define MALLOC_UNLOCK __malloc_unlock(reent_ptr)
#ifdef SMALL_MEMORY
#define malloc_getpagesize (128)
#else
#define malloc_getpagesize (4096)
#endif
#if __STD_C
extern void __malloc_lock(struct _reent *);
extern void __malloc_unlock(struct _reent *);
#else
extern void __malloc_lock();
extern void __malloc_unlock();
#endif
#if __STD_C
#define RARG struct _reent *reent_ptr,
#define RONEARG struct _reent *reent_ptr
#else
#define RARG reent_ptr
#define RONEARG reent_ptr
#define RDECL struct _reent *reent_ptr;
#endif
#define RCALL reent_ptr,
#define RONECALL reent_ptr
/*
Define MALLOC_LOCK and MALLOC_UNLOCK to C expressions to run to
lock and unlock the malloc data structures. MALLOC_LOCK may be
called recursively.
*/
#ifndef MALLOC_LOCK
#define MALLOC_LOCK
#endif
#ifndef MALLOC_UNLOCK
#define MALLOC_UNLOCK
#endif
/*
INTERNAL_SIZE_T is the word-size used for internal bookkeeping
of chunk sizes. On a 64-bit machine, you can reduce malloc
overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
at the expense of not being able to handle requests greater than
2^31. This limitation is hardly ever a concern; you are encouraged
to set this. However, the default version is the same as size_t.
*/
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif
/*
Following is needed on implementations whereby long > size_t.
The problem is caused because the code performs subtractions of
size_t values and stores the result in long values. In the case
where long > size_t and the first value is actually less than
the second value, the resultant value is positive. For example,
(long)(x - y) where x = 0 and y is 1 ends up being 0x00000000FFFFFFFF
which is 2*31 - 1 instead of 0xFFFFFFFFFFFFFFFF. This is due to the
fact that assignment from unsigned to signed won't sign extend.
*/
#ifdef SIZE_T_SMALLER_THAN_LONG
#define long_sub_size_t(x, y) ( (x < y) ? -((long)(y - x)) : (x - y) );
#else
#define long_sub_size_t(x, y) ( (long)(x - y) )
#endif
/*
REALLOC_ZERO_BYTES_FREES should be set if a call to
realloc with zero bytes should be the same as a call to free.
Some people think it should. Otherwise, since this malloc
returns a unique pointer for malloc(0), so does realloc(p, 0).
*/
/* The following macros are only invoked with (2n+1)-multiples of
INTERNAL_SIZE_T units, with a positive integer n. This is exploited
for fast inline execution when n is small. */
#define MALLOC_ZERO(charp, nbytes) \
do { \
INTERNAL_SIZE_T mzsz = (nbytes); \
if(mzsz <= 9*sizeof(mzsz)) { \
INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp); \
if(mzsz >= 5*sizeof(mzsz)) { *mz++ = 0; \
*mz++ = 0; \
if(mzsz >= 7*sizeof(mzsz)) { *mz++ = 0; \
*mz++ = 0; \
if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0; \
*mz++ = 0; }}} \
*mz++ = 0; \
*mz++ = 0; \
*mz = 0; \
} else memset((charp), 0, mzsz); \
} while(0)
#define MALLOC_COPY(dest,src,nbytes) \
do { \
INTERNAL_SIZE_T mcsz = (nbytes); \
if(mcsz <= 9*sizeof(mcsz)) { \
INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src); \
INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest); \
if(mcsz >= 5*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; \
if(mcsz >= 7*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; \
if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; }}} \
*mcdst++ = *mcsrc++; \
*mcdst++ = *mcsrc++; \
*mcdst = *mcsrc ; \
} else memcpy(dest, src, mcsz); \
} while(0)
#define vECCALLOc _vec_calloc_r
#define fREe _free_r
#define mEMALIGn _memalign_r
#define vECREALLOc _vec_realloc_r
#
#if __STD_C
Void_t* vECREALLOc(RARG Void_t*, size_t);
Void_t* vECCALLOc(RARG size_t, size_t);
#else
Void_t* vECREALLOc();
Void_t* vECCALLOc();
#endif
#ifdef __cplusplus
}; /* end of extern "C" */
#endif
/*
Type declarations
*/
struct malloc_chunk
{
INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
};
typedef struct malloc_chunk* mchunkptr;
/* sizes, alignments */
#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
#define MALLOC_ALIGN 16
#define MALLOC_ALIGNMENT 16
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
#define MINSIZE (sizeof(struct malloc_chunk))
/* conversion from malloc headers to user pointers, and back */
#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
/* pad request bytes into a usable size */
#define request2size(req) \
(((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \
(long)(MINSIZE + MALLOC_ALIGN_MASK)) ? ((MINSIZE + MALLOC_ALIGN_MASK) & ~(MALLOC_ALIGN_MASK)) : \
(((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))
/* Check if m has acceptable alignment */
#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
/*
Physical chunk operations
*/
/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
#define PREV_INUSE 0x1
/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
#define IS_MMAPPED 0x2
/* Bits to mask off when extracting size */
#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
/* Ptr to next physical malloc_chunk. */
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
/* Ptr to previous physical malloc_chunk */
#define prev_chunk(p)\
((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
/*
Dealing with use bits
*/
/* extract p's inuse bit */
#define inuse(p)\
((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
/* extract inuse bit of previous chunk */
#define prev_inuse(p) ((p)->size & PREV_INUSE)
/* check for mmap()'ed chunk */
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
/* set/clear chunk as in use without otherwise disturbing */
#define set_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
#define clear_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s)\
(((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s)\
(((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s)\
(((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
/*
Dealing with size fields
*/
/* Get size, ignoring use bits */
#define chunksize(p) ((p)->size & ~(SIZE_BITS))
/* Set size at head, without disturbing its use bit */
#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))
/* Set size/use ignoring previous bits in header */
#define set_head(p, s) ((p)->size = (s))
#ifdef DEFINE_VECREALLOC
#if __STD_C
Void_t* vECREALLOc(RARG Void_t* oldmem, size_t bytes)
#else
Void_t* vECREALLOc(RARG oldmem, bytes) RDECL Void_t* oldmem; size_t bytes;
#endif
{
INTERNAL_SIZE_T nb; /* padded request size */
mchunkptr oldp; /* chunk corresponding to oldmem */
INTERNAL_SIZE_T oldsize; /* its size */
mchunkptr newp; /* chunk to return */
INTERNAL_SIZE_T newsize; /* its size */
Void_t* newmem; /* corresponding user mem */
mchunkptr remainder; /* holds split off extra space from newp */
INTERNAL_SIZE_T remainder_size; /* its size */
#ifdef REALLOC_ZERO_BYTES_FREES
if (bytes == 0) { fREe(RCALL oldmem); return 0; }
#endif
/* realloc of null is supposed to be same as malloc */
if (oldmem == 0) return mEMALIGn(RCALL 16, bytes);
MALLOC_LOCK;
newp = oldp = mem2chunk(oldmem);
newsize = oldsize = chunksize(oldp);
nb = request2size(bytes);
if ((long)(oldsize) < (long)(nb))
{
/* Must allocate */
newmem = mEMALIGn (RCALL 16, bytes);
if (newmem == 0) /* propagate failure */
{
MALLOC_UNLOCK;
return 0;
}
/* copy, free, and exit */
MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
fREe(RCALL oldmem);
MALLOC_UNLOCK;
return newmem;
}
remainder_size = long_sub_size_t(newsize, nb);
if (remainder_size >= (long)MINSIZE) /* split off remainder */
{
remainder = chunk_at_offset(newp, nb);
set_head_size(newp, nb);
set_head(remainder, remainder_size | PREV_INUSE);
set_inuse_bit_at_offset(remainder, remainder_size);
fREe(RCALL chunk2mem(remainder)); /* let free() deal with it */
}
else
{
set_head_size(newp, newsize);
set_inuse_bit_at_offset(newp, newsize);
}
MALLOC_UNLOCK;
return chunk2mem(newp);
}
#endif /* DEFINE_VECREALLOC */
#ifdef DEFINE_VECCALLOC
/*
calloc calls malloc, then zeroes out the allocated chunk.
*/
#if __STD_C
Void_t* vECCALLOc(RARG size_t n, size_t elem_size)
#else
Void_t* vECCALLOc(RARG n, elem_size) RDECL size_t n; size_t elem_size;
#endif
{
INTERNAL_SIZE_T sz = n * elem_size;
Void_t* mem;
mem = mEMALIGn (RCALL 16, sz);
if (mem == 0)
{
return 0;
}
MALLOC_ZERO(mem, sz);
return mem;
}
#endif /* DEFINE_VECCALLOC */

View File

@ -0,0 +1,17 @@
/* vec_realloc.c -- a wrapper for _vec_realloc_r. */
#include <_ansi.h>
#include <reent.h>
#include <stdlib.h>
#ifndef _REENT_ONLY
_PTR
_DEFUN (vec_realloc, (ap, nbytes),
_PTR ap _AND
size_t nbytes)
{
return _vec_realloc_r (_REENT, ap, nbytes);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff