Skip to content

Commit

Permalink
Merge pull request #636 from uclouvain/opj_malloc-625
Browse files Browse the repository at this point in the history
Update allocation functions
Fix #625 
Fix #624
Fix #635
  • Loading branch information
mayeut committed Oct 18, 2015
2 parents b1a8e1a + e1122a8 commit 05b3afd
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 114 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,16 @@ CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H)
include(TestLargeFiles)
OPJ_TEST_LARGE_FILES(OPJ_HAVE_LARGEFILES)

# Allocating Aligned Memory Blocks
include(CheckIncludeFiles)
check_include_files(malloc.h HAVE_MALLOC_H)
include(CheckSymbolExists)
# _aligned_alloc https://msdn.microsoft.com/en-us/library/8z34s9c6.aspx
check_symbol_exists(_aligned_malloc malloc.h HAVE__ALIGNED_MALLOC)
# posix_memalign
check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN)
# memalign (obsolete)
check_symbol_exists(memalign malloc.h HAVE_MEMALIGN)
#-----------------------------------------------------------------------------
# Build Library
if(BUILD_JPIP_SERVER)
Expand Down
1 change: 1 addition & 0 deletions src/lib/openjp2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ set(OPENJPEG_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/opj_codec.h
${CMAKE_CURRENT_SOURCE_DIR}/opj_includes.h
${CMAKE_CURRENT_SOURCE_DIR}/opj_intmath.h
${CMAKE_CURRENT_SOURCE_DIR}/opj_malloc.c
${CMAKE_CURRENT_SOURCE_DIR}/opj_malloc.h
${CMAKE_CURRENT_SOURCE_DIR}/opj_stdint.h
)
Expand Down
8 changes: 5 additions & 3 deletions src/lib/openjp2/dwt.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,9 +567,11 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres
OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - tr->y0); /* height of the resolution level computed */

OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0);

h.mem = (OPJ_INT32*)
opj_aligned_malloc(opj_dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32));

if (numres == 1U) {
return OPJ_TRUE;
}
h.mem = (OPJ_INT32*)opj_aligned_malloc(opj_dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32));
if (! h.mem){
/* FIXME event manager error callback */
return OPJ_FALSE;
Expand Down
16 changes: 14 additions & 2 deletions src/lib/openjp2/j2k.c
Original file line number Diff line number Diff line change
Expand Up @@ -9947,6 +9947,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
OPJ_UINT32 l_nb_tiles;
OPJ_UINT32 l_max_tile_size = 0, l_current_tile_size;
OPJ_BYTE * l_current_data = 00;
OPJ_BOOL l_reuse_data = OPJ_FALSE;
opj_tcd_t* p_tcd = 00;

/* preconditions */
Expand All @@ -9957,6 +9958,17 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
p_tcd = p_j2k->m_tcd;

l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
if (l_nb_tiles == 1) {
l_reuse_data = OPJ_TRUE;
#ifdef __SSE__
for (j=0;j<p_j2k->m_tcd->image->numcomps;++j) {
opj_image_comp_t * l_img_comp = p_tcd->image->comps + j;
if (((size_t)l_img_comp->data & 0xFU) != 0U) { /* tile data shall be aligned on 16 bytes */
l_reuse_data = OPJ_FALSE;
}
}
#endif
}
for (i=0;i<l_nb_tiles;++i) {
if (! opj_j2k_pre_write_tile(p_j2k,i,p_stream,p_manager)) {
if (l_current_data) {
Expand All @@ -9969,7 +9981,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
/* otherwise, allocate the data */
for (j=0;j<p_j2k->m_tcd->image->numcomps;++j) {
opj_tcd_tilecomp_t* l_tilec = p_tcd->tcd_image->tiles->comps + j;
if (l_nb_tiles == 1) {
if (l_reuse_data) {
opj_image_comp_t * l_img_comp = p_tcd->image->comps + j;
l_tilec->data = l_img_comp->data;
l_tilec->ownsData = OPJ_FALSE;
Expand All @@ -9984,7 +9996,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
}
}
l_current_tile_size = opj_tcd_get_encoded_tile_size(p_j2k->m_tcd);
if (l_nb_tiles > 1) {
if (!l_reuse_data) {
if (l_current_tile_size > l_max_tile_size) {
OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_current_tile_size);
if (! l_new_current_data) {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/openjp2/mct.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ void opj_mct_encode(
{
OPJ_SIZE_T i;
const OPJ_SIZE_T len = n;
/* buffer are aligned on 16 bytes */
assert( ((size_t)c0 & 0xf) == 0 );
assert( ((size_t)c1 & 0xf) == 0 );
assert( ((size_t)c2 & 0xf) == 0 );

for(i = 0; i < (len & ~3U); i += 4) {
__m128i y, u, v;
Expand Down
13 changes: 12 additions & 1 deletion src/lib/openjp2/opj_config_private.h.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@
#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@
#cmakedefine OPJ_HAVE_FSEEKO @OPJ_HAVE_FSEEKO@

/* find whether or not have <malloc.h> */
#cmakedefine HAVE_MALLOC_H
/* check if function `aligned_alloc` exists */
#cmakedefine HAVE_ALIGNED_ALLOC
/* check if function `_aligned_malloc` exists */
#cmakedefine HAVE__ALIGNED_MALLOC
/* check if function `memalign` exists */
#cmakedefine HAVE_MEMALIGN
/* check if function `posix_memalign` exists */
#cmakedefine HAVE_POSIX_MEMALIGN

/* Byte order. */
/* All compilers that support Mac OS X define either __BIG_ENDIAN__ or
__LITTLE_ENDIAN__ to match the endianness of the architecture being
Expand All @@ -28,4 +39,4 @@ On other platforms we use the result of the TRY_RUN. */
#cmakedefine OPJ_BIG_ENDIAN
#elif defined(__BIG_ENDIAN__)
# define OPJ_BIG_ENDIAN
#endif
#endif
149 changes: 149 additions & 0 deletions src/lib/openjp2/opj_malloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2015, Mathieu Malaterre <[email protected]>
* Copyright (c) 2015, Matthieu Darbois
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define OPJ_SKIP_POISON
#include "opj_includes.h"

static INLINE void *opj_aligned_alloc_n(size_t alignment, size_t size)
{
void* ptr;

/* alignment shall be power of 2 */
assert( (alignment != 0U) && ((alignment & (alignment - 1U)) == 0U));

if (size == 0U) { /* prevent implementation defined behavior of realloc */
return NULL;
}

#if defined(HAVE_POSIX_MEMALIGN)
/* aligned_alloc requires c11, restrict to posix_memalign for now. Quote:
* This function was introduced in POSIX 1003.1d. Although this function is
* superseded by aligned_alloc, it is more portable to older POSIX systems
* that do not support ISO C11. */
if (posix_memalign (&ptr, alignment, size))
{
ptr = NULL;
}
/* older linux */
#elif defined(HAVE_MEMALIGN)
ptr = memalign( alignment, size );
/* _MSC_VER */
#elif defined(HAVE__ALIGNED_MALLOC)
ptr = _aligned_malloc(size, alignment);
#else
/* TODO: _mm_malloc(x,y) */
#error missing aligned alloc function
#endif
return ptr;
}
static INLINE void *opj_aligned_realloc_n(void *ptr, size_t alignment, size_t new_size)
{
void *r_ptr;

/* alignment shall be power of 2 */
assert( (alignment != 0U) && ((alignment & (alignment - 1U)) == 0U));

if (new_size == 0U) { /* prevent implementation defined behavior of realloc */
return NULL;
}

/* no portable aligned realloc */
#if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)
/* glibc doc states one can mixed aligned malloc with realloc */
r_ptr = realloc( ptr, new_size ); /* fast path */
/* we simply use `size_t` to cast, since we are only interest in binary AND
* operator */
if( ((size_t)r_ptr & (alignment - 1U)) != 0U ) {
/* this is non-trivial to implement a portable aligned realloc, so use a
* simple approach where we do not need a function that return the size of an
* allocated array (eg. _msize on Windows, malloc_size on MacOS,
* malloc_usable_size on systems with glibc) */
void *a_ptr = opj_aligned_alloc_n(alignment, new_size);
if (a_ptr != NULL) {
memcpy(a_ptr, r_ptr, new_size);
}
free( r_ptr );
r_ptr = a_ptr;
}
/* _MSC_VER */
#elif defined(HAVE__ALIGNED_MALLOC)
r_ptr = _aligned_realloc( ptr, new_size, alignment );
#else
/* TODO: _mm_malloc(x,y) */
#error missing aligned realloc function
#endif
return r_ptr;
}
void * opj_malloc(size_t size)
{
if (size == 0U) { /* prevent implementation defined behavior of realloc */
return NULL;
}
return malloc(size);
}
void * opj_calloc(size_t num, size_t size)
{
if (size == 0U) { /* prevent implementation defined behavior of realloc */
return NULL;
}
/* according to C89 standard, num == 0 shall return a valid pointer */
return calloc(num, size);
}

void *opj_aligned_malloc(size_t size)
{
return opj_aligned_alloc_n(16U, size);
}
void * opj_aligned_realloc(void *ptr, size_t size)
{
return opj_aligned_realloc_n(ptr, 16U, size);
}

void opj_aligned_free(void* ptr)
{
#ifdef HAVE__ALIGNED_MALLOC
_aligned_free( ptr );
#else
free( ptr );
#endif
}

void * opj_realloc(void *ptr, size_t new_size)
{
if (new_size == 0U) { /* prevent implementation defined behavior of realloc */
return NULL;
}
return realloc(ptr, new_size);
}
void opj_free(void *ptr)
{
free(ptr);
}
Loading

0 comments on commit 05b3afd

Please sign in to comment.