forked from AuroraMiddleware/gtk
c02bc22cc5
Any data that is later fed to graphene must be allocated with proper alignment, if graphene uses SSE2 or GCC vector instructions. This adds custom array code (a streamlined copy of GArray with all unnecessary bells and whistles removed), which is then used for the state_stack instead of GArray. There's also a runtime check for the size of GtkSnapshotState itself being a multiple of 16. If that is not so, any array elements past the 0th element will lose alignment. There are probably struct attributes that can make GtkSnapshotState always have size that is a multiple of 16, but we'll burn that bridge if we cross it.
131 lines
3.2 KiB
C
131 lines
3.2 KiB
C
#include "config.h"
|
|
|
|
#if defined(HAVE_POSIX_MEMALIGN) && !defined(_XOPEN_SOURCE)
|
|
# define _XOPEN_SOURCE 600
|
|
#endif
|
|
|
|
#include "gskallocprivate.h"
|
|
|
|
#if defined(HAVE_MEMALIGN) || defined(HAVE__ALIGNED_MALLOC)
|
|
/* Required for _aligned_malloc() and _aligned_free() on Windows */
|
|
#include <malloc.h>
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#ifdef HAVE__ALIGNED_MALLOC
|
|
/* _aligned_malloc() takes parameters of aligned_alloc() in reverse order */
|
|
# define aligned_alloc(alignment, size) _aligned_malloc (size, alignment)
|
|
|
|
/* _aligned_malloc()'ed memory must be freed by _align_free() on Windows */
|
|
# define aligned_free(x) _aligned_free (x)
|
|
#else
|
|
# define aligned_free(x) free (x)
|
|
#endif
|
|
|
|
/*
|
|
* gsk_aligned_alloc:
|
|
* @size: the size of the memory to allocate
|
|
* @number: the multiples of @size to allocate
|
|
* @alignment: the alignment to be enforced, as a power of 2
|
|
*
|
|
* Allocates @number times @size memory, with the given @alignment.
|
|
*
|
|
* If the total requested memory overflows %G_MAXSIZE, this function
|
|
* will abort.
|
|
*
|
|
* If allocation fails, this function will abort, in line with
|
|
* the behaviour of GLib.
|
|
*
|
|
* Returns: (transfer full): the allocated memory
|
|
*/
|
|
gpointer
|
|
gsk_aligned_alloc (gsize size,
|
|
gsize number,
|
|
gsize alignment)
|
|
{
|
|
gpointer res = NULL;
|
|
gsize real_size;
|
|
|
|
if (G_UNLIKELY (number > G_MAXSIZE / size))
|
|
{
|
|
#ifndef G_DISABLE_ASSERT
|
|
g_error ("%s: overflow in the allocation of (%"G_GSIZE_FORMAT" x %"G_GSIZE_FORMAT") bytes",
|
|
G_STRLOC, size, number);
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
real_size = size * number;
|
|
|
|
#ifndef G_DISABLE_ASSERT
|
|
errno = 0;
|
|
#endif
|
|
|
|
#if defined(HAVE_POSIX_MEMALIGN) && !defined (MALLOC_IS_ALIGNED16)
|
|
errno = posix_memalign (&res, alignment, real_size);
|
|
#elif (defined(HAVE_ALIGNED_ALLOC) || defined(HAVE__ALIGNED_MALLOC)) && !defined (MALLOC_IS_ALIGNED16)
|
|
/* real_size must be a multiple of alignment */
|
|
if (real_size % alignment != 0)
|
|
{
|
|
gsize offset = real_size % alignment;
|
|
real_size += (alignment - offset);
|
|
}
|
|
|
|
res = aligned_alloc (alignment, real_size);
|
|
#elif defined(HAVE_MEMALIGN) && !defined (MALLOC_IS_ALIGNED16)
|
|
res = memalign (alignment, real_size);
|
|
#else
|
|
res = malloc (real_size);
|
|
#endif
|
|
|
|
#ifndef G_DISABLE_ASSERT
|
|
if (errno != 0 || res == NULL)
|
|
{
|
|
g_error ("%s: error in the allocation of (%"G_GSIZE_FORMAT" x %"G_GSIZE_FORMAT") bytes: %s",
|
|
G_STRLOC, size, number, strerror (errno));
|
|
}
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
* gsk_aligned_alloc0:
|
|
* @size: the size of the memory to allocate
|
|
* @number: the multiples of @size to allocate
|
|
* @alignment: the alignment to be enforced, as a power of 2
|
|
*
|
|
* Allocates @number times @size memory, with the given @alignment,
|
|
* like gsk_aligned_alloc(), but it also clears the memory.
|
|
*
|
|
* Returns: (transfer full): the allocated, cleared memory
|
|
*/
|
|
gpointer
|
|
gsk_aligned_alloc0 (gsize size,
|
|
gsize number,
|
|
gsize alignment)
|
|
{
|
|
gpointer mem;
|
|
|
|
mem = gsk_aligned_alloc (size, number, alignment);
|
|
|
|
if (mem)
|
|
memset (mem, 0, size * number);
|
|
|
|
return mem;
|
|
}
|
|
|
|
/*
|
|
* gsk_aligned_free:
|
|
* @mem: the memory to deallocate
|
|
*
|
|
* Frees the memory allocated by gsk_aligned_alloc().
|
|
*/
|
|
void
|
|
gsk_aligned_free (gpointer mem)
|
|
{
|
|
aligned_free (mem);
|
|
}
|