aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--src/byte_sink.h4
-rw-r--r--src/byte_source.c5
-rw-r--r--src/system.c49
-rw-r--r--src/system.h17
-rw-r--r--wscript7
6 files changed, 72 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index 2b37bc58..057a9994 100644
--- a/NEWS
+++ b/NEWS
@@ -3,8 +3,9 @@ serd (0.30.7) unstable;
* Fix potential memory error when serialising URIs
* Move headers to an include directory
* Split up and reorganize unit tests
+ * Use aligned allocation via C11 or Windows API where possible
- -- David Robillard <d@drobilla.net> Tue, 10 Nov 2020 21:04:06 +0000
+ -- David Robillard <d@drobilla.net> Thu, 12 Nov 2020 19:18:33 +0000
serd (0.30.6) stable;
diff --git a/src/byte_sink.h b/src/byte_sink.h
index f39bc2ba..876add2b 100644
--- a/src/byte_sink.h
+++ b/src/byte_sink.h
@@ -42,7 +42,7 @@ serd_byte_sink_new(SerdSink sink, void* stream, size_t block_size)
bsink.size = 0;
bsink.block_size = block_size;
bsink.buf = ((block_size > 1)
- ? (uint8_t*)serd_bufalloc(block_size)
+ ? (uint8_t*)serd_allocate_buffer(block_size)
: NULL);
return bsink;
}
@@ -60,7 +60,7 @@ static inline void
serd_byte_sink_free(SerdByteSink* bsink)
{
serd_byte_sink_flush(bsink);
- free(bsink->buf);
+ serd_free_aligned(bsink->buf);
bsink->buf = NULL;
}
diff --git a/src/byte_source.c b/src/byte_source.c
index d783959c..5c0404a7 100644
--- a/src/byte_source.c
+++ b/src/byte_source.c
@@ -22,7 +22,6 @@
#include <stdbool.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
SerdStatus
@@ -63,7 +62,7 @@ serd_byte_source_open_source(SerdByteSource* source,
source->read_func = read_func;
if (page_size > 1) {
- source->file_buf = (uint8_t*)serd_bufalloc(page_size);
+ source->file_buf = (uint8_t*)serd_allocate_buffer(page_size);
source->read_buf = source->file_buf;
memset(source->file_buf, '\0', page_size);
} else {
@@ -102,7 +101,7 @@ SerdStatus
serd_byte_source_close(SerdByteSource* source)
{
if (source->page_size > 1) {
- free(source->file_buf);
+ serd_free_aligned(source->file_buf);
}
memset(source, '\0', sizeof(*source));
return SERD_SUCCESS;
diff --git a/src/system.c b/src/system.c
index 0a6a5561..fbff8806 100644
--- a/src/system.c
+++ b/src/system.c
@@ -25,11 +25,19 @@
# include <fcntl.h>
#endif
+#ifdef _WIN32
+# include <malloc.h>
+#endif
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#define SERD_HAVE_ALIGNED_ALLOCATION \
+ defined(_WIN32) || defined(HAVE_ALIGNED_ALLOC) || \
+ defined(HAVE_POSIX_MEMALIGN)
+
FILE*
serd_fopen(const char* path, const char* mode)
{
@@ -46,14 +54,49 @@ serd_fopen(const char* path, const char* mode)
}
void*
-serd_bufalloc(size_t size)
+serd_malloc_aligned(const size_t alignment, const size_t size)
{
-#ifdef HAVE_POSIX_MEMALIGN
+#if defined(_WIN32)
+ return _aligned_malloc(size, alignment);
+#elif defined(HAVE_ALIGNED_ALLOC)
+ return aligned_alloc(alignment, size);
+#elif defined(HAVE_POSIX_MEMALIGN)
void* ptr = NULL;
- const int ret = posix_memalign(&ptr, SERD_PAGE_SIZE, size);
+ const int ret = posix_memalign(&ptr, alignment, size);
return ret ? NULL : ptr;
#else
+ (void)alignment;
return malloc(size);
#endif
}
+void*
+serd_calloc_aligned(const size_t alignment, const size_t size)
+{
+#ifdef SERD_HAVE_ALIGNED_ALLOCATION
+ void* const ptr = serd_malloc_aligned(alignment, size);
+ if (ptr) {
+ memset(ptr, 0, size);
+ }
+ return ptr;
+#else
+ (void)alignment;
+ return calloc(1, size);
+#endif
+}
+
+void*
+serd_allocate_buffer(const size_t size)
+{
+ return serd_malloc_aligned(SERD_PAGE_SIZE, size);
+}
+
+void
+serd_free_aligned(void* const ptr)
+{
+#ifdef _WIN32
+ _aligned_free(ptr);
+#else
+ free(ptr);
+#endif
+}
diff --git a/src/system.h b/src/system.h
index 0f6a0e0b..60095a5b 100644
--- a/src/system.h
+++ b/src/system.h
@@ -21,10 +21,19 @@
#include <stdio.h>
-FILE*
-serd_fopen(const char* path, const char* mode);
+/// Open a file configured for fast sequential reading
+FILE* serd_fopen(const char* path, const char* mode);
-SERD_MALLOC_FUNC void*
-serd_bufalloc(size_t size);
+/// Allocate a buffer aligned to `alignment` bytes
+SERD_MALLOC_FUNC void* serd_malloc_aligned(size_t alignment, size_t size);
+
+/// Allocate a zeroed buffer aligned to `alignment` bytes
+SERD_MALLOC_FUNC void* serd_calloc_aligned(size_t alignment, size_t size);
+
+/// Allocate an aligned buffer for I/O
+SERD_MALLOC_FUNC void* serd_allocate_buffer(size_t size);
+
+/// Free a buffer allocated with an aligned allocation function
+void serd_free_aligned(void* ptr);
#endif // SERD_SYSTEM_H
diff --git a/wscript b/wscript
index cca050b5..b9767563 100644
--- a/wscript
+++ b/wscript
@@ -120,6 +120,13 @@ def configure(conf):
if Options.options.largefile:
conf.env.append_unique('DEFINES', ['_FILE_OFFSET_BITS=64'])
+ conf.check_function('c', 'aligned_alloc',
+ header_name = 'stdlib.h',
+ return_type = 'void*',
+ arg_types = 'size_t,size_t',
+ define_name = 'HAVE_ALIGNED_ALLOC',
+ mandatory = False)
+
if not Options.options.no_posix:
funcs = {'posix_memalign': ('stdlib.h', 'int', 'void**,size_t,size_t'),
'posix_fadvise': ('fcntl.h', 'int', 'int,off_t,off_t,int'),