mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-18 12:29:32 +08:00
2004-08-24 Steven G. Johnson <stevenj@alum.mit.edu>
* mingwex/mingw-aligned-malloc.c: New file. * mingwex/tst-aligned-malloc.c: New file.
This commit is contained in:
parent
45b1139e41
commit
a6c2ea7e7c
@ -1,3 +1,8 @@
|
||||
2004-08-24 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
|
||||
* mingwex/mingw-aligned-malloc.c: New file.
|
||||
* mingwex/tst-aligned-malloc.c: New file.
|
||||
|
||||
2004-08-24 Danny Smith <dannysmith@users.sourceforge.net>
|
||||
|
||||
* crt1.c: (__mingw_CRTStartup): Change return to void. Add
|
||||
|
120
winsup/mingw/mingwex/mingw-aligned-malloc.c
Executable file
120
winsup/mingw/mingwex/mingw-aligned-malloc.c
Executable file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
__mingw_aligned_malloc and friends, implemented using Microsoft's public
|
||||
interfaces and with the help of the algorithm description provided
|
||||
by Wu Yongwei: http://sourceforge.net/mailarchive/message.php?msg_id=3847075
|
||||
|
||||
I hereby place this implementation in the public domain.
|
||||
-- Steven G. Johnson (stevenj@alum.mit.edu)
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <string.h> /* memmove */
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h> /* uintptr_t */
|
||||
#else
|
||||
# define uintptr_t size_t
|
||||
#endif
|
||||
|
||||
#define NOT_POWER_OF_TWO(n) (((n) & ((n) - 1)))
|
||||
#define UI(p) ((uintptr_t) (p))
|
||||
#define CP(p) ((char *) p)
|
||||
|
||||
#define PTR_ALIGN(p0, alignment, offset) \
|
||||
((void *) (((UI(p0) + (alignment + sizeof(void*)) + offset) \
|
||||
& (~UI(alignment - 1))) \
|
||||
- offset))
|
||||
|
||||
/* Pointer must sometimes be aligned; assume sizeof(void*) is a power of two. */
|
||||
#define ORIG_PTR(p) (*(((void **) (UI(p) & (~UI(sizeof(void*) - 1)))) - 1))
|
||||
|
||||
void *
|
||||
__mingw_aligned_offset_malloc (size_t size, size_t alignment, size_t offset)
|
||||
{
|
||||
void *p0, *p;
|
||||
|
||||
if (NOT_POWER_OF_TWO (alignment))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return ((void *) 0);
|
||||
}
|
||||
if (size == 0)
|
||||
return ((void *) 0);
|
||||
if (alignment < sizeof (void *))
|
||||
alignment = sizeof (void *);
|
||||
|
||||
/* Including the extra sizeof(void*) is overkill on a 32-bit
|
||||
machine, since malloc is already 8-byte aligned, as long
|
||||
as we enforce alignment >= 8 ...but oh well. */
|
||||
|
||||
p0 = malloc (size + (alignment + sizeof (void *)));
|
||||
if (!p0)
|
||||
return ((void *) 0);
|
||||
p = PTR_ALIGN (p0, alignment, offset);
|
||||
ORIG_PTR (p) = p0;
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
__mingw_aligned_malloc (size_t size, size_t alignment)
|
||||
{
|
||||
return __mingw_aligned_offset_malloc (size, alignment, 0);
|
||||
}
|
||||
|
||||
void
|
||||
__mingw_aligned_free (void *memblock)
|
||||
{
|
||||
if (memblock)
|
||||
free (ORIG_PTR (memblock));
|
||||
}
|
||||
|
||||
void *
|
||||
__mingw_aligned_offset_realloc (void *memblock, size_t size,
|
||||
size_t alignment, size_t offset)
|
||||
{
|
||||
void *p0, *p;
|
||||
ptrdiff_t shift;
|
||||
|
||||
if (!memblock)
|
||||
return __mingw_aligned_offset_malloc (size, alignment, offset);
|
||||
if (NOT_POWER_OF_TWO (alignment))
|
||||
goto bad;
|
||||
if (size == 0)
|
||||
{
|
||||
__mingw_aligned_free (memblock);
|
||||
return ((void *) 0);
|
||||
}
|
||||
if (alignment < sizeof (void *))
|
||||
alignment = sizeof (void *);
|
||||
|
||||
p0 = ORIG_PTR (memblock);
|
||||
/* It is an error for the alignment to change. */
|
||||
if (memblock != PTR_ALIGN (p0, alignment, offset))
|
||||
goto bad;
|
||||
shift = CP (memblock) - CP (p0);
|
||||
|
||||
p0 = realloc (p0, size + (alignment + sizeof (void *)));
|
||||
if (!p0)
|
||||
return ((void *) 0);
|
||||
p = PTR_ALIGN (p0, alignment, offset);
|
||||
|
||||
/* Relative shift of actual data may be different from before, ugh. */
|
||||
if (shift != CP (p) - CP (p0))
|
||||
/* ugh, moves more than necessary if size is increased. */
|
||||
memmove (CP (p), CP (p0) + shift, size);
|
||||
|
||||
ORIG_PTR (p) = p0;
|
||||
return p;
|
||||
|
||||
bad:
|
||||
errno = EINVAL;
|
||||
return ((void *) 0);
|
||||
}
|
||||
|
||||
void *
|
||||
__mingw_aligned_realloc (void *memblock, size_t size, size_t alignment)
|
||||
{
|
||||
return __mingw_aligned_offset_realloc (memblock, size, alignment, 0);
|
||||
}
|
90
winsup/mingw/mingwex/tst-aligned-malloc.c
Executable file
90
winsup/mingw/mingwex/tst-aligned-malloc.c
Executable file
@ -0,0 +1,90 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h> /* uintptr_t */
|
||||
#else
|
||||
# define uintptr_t size_t
|
||||
#endif
|
||||
|
||||
#define NELEM(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
static int
|
||||
is_aligned (void *p, size_t alignment, size_t offset)
|
||||
{
|
||||
return !((((uintptr_t) p) + offset) & (alignment - 1));
|
||||
}
|
||||
|
||||
#define MAX_SIZE (1 << sizeof(unsigned char))
|
||||
#define NP 1000
|
||||
#define NTST 100000U
|
||||
|
||||
#define ERRMSG fprintf(stderr, "Iteration %u, align = %u, offset = %u, size = %u (oldsize = %u), errno = %d (%s)\n", i, align[j % NELEM(align)], offset[j % NELEM(offset)], size[j], oldsize, errno, strerror(errno))
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
unsigned char *p[NP];
|
||||
size_t size[NP];
|
||||
size_t align[] = { 2, 4, 8, 16, 32, 64 };
|
||||
size_t offset[20];
|
||||
unsigned i;
|
||||
|
||||
srand (time (NULL));
|
||||
|
||||
for (i = 0; i < NELEM (p); ++i)
|
||||
{
|
||||
p[i] = 0;
|
||||
size[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NELEM (offset); ++i)
|
||||
offset[i] = rand () % 512;
|
||||
|
||||
for (i = 0; i < NTST; ++i)
|
||||
{
|
||||
size_t oldsize;
|
||||
unsigned j, k;
|
||||
j = rand () % NELEM (p);
|
||||
oldsize = size[j];
|
||||
p[j] = __mingw_aligned_offset_realloc (p[j],
|
||||
size[j] = rand () % MAX_SIZE,
|
||||
align[j % NELEM (align)],
|
||||
offset[j % NELEM (offset)]);
|
||||
|
||||
if (size[j] && !p[j])
|
||||
{
|
||||
fprintf (stderr, "Returned NULL!\n");
|
||||
ERRMSG;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (size[j] && !is_aligned (p[j],
|
||||
align[j % NELEM (align)],
|
||||
offset[j % NELEM (offset)]))
|
||||
{
|
||||
fprintf (stderr, "Misaligned block!\n");
|
||||
ERRMSG;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (oldsize > size[j])
|
||||
oldsize = size[j];
|
||||
for (k = 0; k < oldsize; ++k)
|
||||
if (p[j][k] != k)
|
||||
{
|
||||
fprintf (stderr, "Miscopied block!\n");
|
||||
ERRMSG;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
for (k = 0; k < size[j]; ++k)
|
||||
p[j][k] = k;
|
||||
}
|
||||
|
||||
for (i = 0; i < NELEM (p); ++i)
|
||||
__mingw_aligned_free (p[i]);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user