Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic aligned malloc implementation. #643

Closed
wants to merge 1 commit into from

Conversation

smuehlst
Copy link
Contributor

Used for platforms where none of posix_memalign(), memalign() and
_aligned_malloc() is available.

Fix for #642.

Used for platforms where none of posix_memalign(), memalign() and
_aligned_malloc() is available.
@mayeut
Copy link
Collaborator

mayeut commented Oct 20, 2015

@smuehlst, ptrdiff_t can't be used here because it might not hold the whole pointer (i.e. sizeof(ptrdiff_t) <= sizeof(intptr_t), no strict equality, this depends on the platform).
I'll try to get something merged in based on your PR but modified with this in mind.

@smuehlst
Copy link
Contributor Author

@mayeut: I used ptrdiff_t because of the following recommendation on the mailing list by @malaterre:

I do not believe you need the full range of uintptr_t for the mask, since align is typically stored on unsigned char (8, 16, 32...) As for the pointer arithmetic, you can simply use ptrdiff_t.

intptr_t and uintptr_t is not available in C89.

@malaterre
Copy link
Collaborator

I would follow the suggestion from here. Simply use:

#if PTRDIFF_MAX < SIZE_MAX/2
# error "we need an architecture with sufficiently wide ptrdiff_t"
#endif

@mayeut
Copy link
Collaborator

mayeut commented Oct 20, 2015

Why not use this ? Should work on all platforms if I'm not mistaken.

  /*
   * Generic aligned malloc implementation.
   * Uses ptrdiff_t for the integer manipulation of the pointer, as
   * uintptr_t is not available in C89.
   */
  alignment--;
  {
    size_t offset;
    OPJ_UINT8 *mem;

    /* Room for padding and extra pointer stored in front of allocated area */
    size_t overhead = alignment + sizeof(void *);

    /* let's be extra careful */
    assert(alignment <= (SIZE_MAX - sizeof(void *)));

    /* Avoid integer overflow */
    if (size > (SIZE_MAX - overhead)) {
      return NULL;
    }

    mem = (OPJ_UINT8*)malloc(size + overhead);
    if (mem == NULL) {
      return mem;
    }
    /* offset = ((alignment + 1U) - ((size_t)(mem + sizeof(void*)) & alignment)) & alignment; */
    /* Use the fact that alignment + 1U is a power of 2 */
    offset = ((alignment ^ ((size_t)(mem + sizeof(void*)) & alignment)) + 1U) & alignment;
    ptr = (void *)(mem + sizeof(void*) + offset);
    ((void**) ptr)[-1] = mem;
  }

@mayeut
Copy link
Collaborator

mayeut commented Oct 20, 2015

I'd like to point out that the implementation of the realloc assumes that alignment requirement doesn't change between the malloc and realloc.
I think this is fine but should be noted. According to MSDN, _aligned_realloc has the same limitation anyway.
https://msdn.microsoft.com/fr-fr/library/y69db7sx.aspx

@mayeut
Copy link
Collaborator

mayeut commented Oct 20, 2015

Merged in d48be27

@mayeut mayeut closed this Oct 20, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants