mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 10:50:10 +00:00
Add aligned allocator functions to GSK
The code is mostly stolen from graphene. Allocators support any alignment, but their implementation only calls system aligned allocator functions if malloc() is not aligned to 16-byte boundaries. If it is aligned, the implementation just calls malloc() regardless of which alignment is requested by the caller. This can be fixed by saving the result of meson malloc() alignment check and adding a few conditions to the implementation, but right now GSK and GTK only need 16-byte alignment either way.
This commit is contained in:
parent
bd2e3f5b9b
commit
8e74eb382f
130
gsk/gskalloc.c
Normal file
130
gsk/gskalloc.c
Normal file
@ -0,0 +1,130 @@
|
||||
#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);
|
||||
}
|
18
gsk/gskallocprivate.h
Normal file
18
gsk/gskallocprivate.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __GSK_ALLOC_PRIVATE_H__
|
||||
#define __GSK_ALLOC_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gpointer gsk_aligned_alloc (gsize size,
|
||||
gsize number,
|
||||
gsize alignment);
|
||||
gpointer gsk_aligned_alloc0 (gsize size,
|
||||
gsize number,
|
||||
gsize alignment);
|
||||
void gsk_aligned_free (gpointer mem);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_ALLOC_PRIVATE_H__ */
|
@ -30,6 +30,7 @@ gsk_public_sources = files([
|
||||
])
|
||||
|
||||
gsk_private_sources = files([
|
||||
'gskalloc.c',
|
||||
'gskcairoblur.c',
|
||||
'gskcairorenderer.c',
|
||||
'gskdebug.c',
|
||||
|
Loading…
Reference in New Issue
Block a user