Skip to content

Commit

Permalink
implement __aligned_malloc() and __aligned_free() and fixes on LE3.1(#59
Browse files Browse the repository at this point in the history
)

* implement __aligned_malloc() and __aligned_free()

Call posix_memalign() if building with `-mzos-target=zosv3r1` on z/OS 3.1,
in which case `__aligned_free()` calls `free()`. Otherwise use a local
implementation to align memory from `malloc()`.

* fix include_next typo

On LE 3.1 zos-io.cc fails to pick up LOCK_* definitions from the
system's sys/file.h.

* fix conflicts with system's time.h

__clockid_t is defined in sys/types.h if >= v2r5,
CLOCK_REALTIME and CLOCK_MONOTONIC are already defined
in the system's time.h if >= v2r5.
  • Loading branch information
gabylb authored May 9, 2024
1 parent f54bb5b commit 52679a3
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 8 deletions.
2 changes: 1 addition & 1 deletion include/sys/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ __Z_EXPORT int flock(int fd, int operation) __asm("__flock");
}
#endif
#else
#include <sys/file.h>
#include_next <sys/file.h>
#endif

#endif
22 changes: 16 additions & 6 deletions include/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,22 @@ __Z_EXPORT extern int (*nanosleep)(const struct timespec*, struct timespec*);

#include_next <time.h>

typedef enum {
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_HIGHRES,
CLOCK_THREAD_CPUTIME_ID
} clockid_t;
// __clockid_t is defined in sys/types.h #if __EDC_TARGET >= __EDC_LE4205 as
#ifndef __clockid_t
#define __clockid_t 1
typedef unsigned int clockid_t;
#endif

// These are defined in the system's time.h #if __EDC_TARGET >= __EDC_LE4205
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 1
#endif
// These are not defined anywhere as of LE 3.1:
#define CLOCK_HIGHRES 2
#define CLOCK_THREAD_CPUTIME_ID 3

#if defined(__cplusplus)
extern "C" {
Expand Down
14 changes: 14 additions & 0 deletions include/zos-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,20 @@ __Z_EXPORT void __mainTerminating();
*/
__Z_EXPORT char* __getprogramdir();

/**
* Reserve aligned storage block
* \param [in] alignment - must be a power of two and a multiple of
* sizeof(void*)
* \param [in] size - number of bytes to allocate
* \return pointer to the beginning of newly allocated memory
*/
__Z_EXPORT void *__aligned_malloc(size_t size, size_t alignment);

/**
* \param [in] ptr - pointer to the memory to deallocate
*/
__Z_EXPORT void __aligned_free(void *ptr);

#ifdef __cplusplus
}
#endif
Expand Down
36 changes: 35 additions & 1 deletion src/zos.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// US Government Users Restricted Rights - Use, duplication
// or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
///////////////////////////////////////////////////////////////////////////////

#define _AE_BIMODAL 1
#undef _ENHANCED_ASCII_EXT
#define _ENHANCED_ASCII_EXT 0xFFFFFFFF
Expand Down Expand Up @@ -3098,6 +3097,41 @@ extern "C" char* __getprogramdir() {
return NULL;
}

extern "C" void *__aligned_malloc(size_t size, size_t alignment) {
#if (__TARGET_LIB__ >= 0x43010000)
void *ptr;
if (posix_memalign(&ptr, alignment, size) == 0)
return ptr;
return nullptr;
#else
if (size == 0)
return nullptr;
if (alignment % 8 != 0 || (alignment & (alignment - 1)) != 0) {
errno = EINVAL;
return nullptr;
}
size_t req_size = size + alignment;
void *ptr = malloc(req_size);
if (ptr == nullptr || alignment == 0)
return ptr;
size_t sptr = reinterpret_cast<size_t>(ptr);
size_t mod = sptr % alignment;
size_t offset = alignment - mod;
assert(offset >= sizeof(void*));
void **ptr_aligned = reinterpret_cast<void**>(sptr + offset);
ptr_aligned[-1] = ptr;
return ptr_aligned;
#endif
}

extern "C" void __aligned_free(void *ptr) {
#if (__TARGET_LIB__ >= 0x43010000)
free(ptr);
#else
free((reinterpret_cast<void**>(ptr))[-1]);
#endif
}

#if defined(ZOSLIB_INITIALIZE)
__init_zoslib __zoslib;
#endif
65 changes: 65 additions & 0 deletions test/test-aligned-malloc.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "zos.h"
#include "gtest/gtest.h"

#include <math.h>
#include <unistd.h>

namespace {

constexpr int KB = 1024;
constexpr int MB = KB * 1024;

#if (__TARGET_LIB__ >= 0x43010000)
#define AlignedAlloc posix_memalign
#else
#define AlignedAlloc AlignedAlloc
#endif

TEST(AlignedAlloc, TestOne) {
size_t alignment = sysconf(_SC_PAGESIZE);
size_t size = 123;
void *ptr = __aligned_malloc(size, alignment);
ASSERT_NE(ptr, nullptr);
ASSERT_EQ(reinterpret_cast<size_t>(ptr) % alignment, 0);
__aligned_free(ptr);
}

TEST(AlignedAlloc, TestTwo) {
size_t alignment;
size_t size = 4096;
void *ptr;
for (int i=3; i<=30; i++) {
alignment = powl(2, i);
ASSERT_EQ(alignment % sizeof(void*), 0);
ptr = __aligned_malloc(size, alignment);
ASSERT_NE(ptr, nullptr);
ASSERT_EQ(reinterpret_cast<size_t>(ptr) % alignment, 0);
__aligned_free(ptr);
}
}

TEST(AlignedAlloc, TestThree) {
size_t alignment;
void *ptr;
for (int i=3; i<=20; i++) {
alignment = powl(2, i);
ASSERT_EQ(alignment % sizeof(void*), 0);
for (size_t size=1; size <= MB; size+=10) {
ptr = __aligned_malloc(size, alignment);
ASSERT_NE(ptr, nullptr);
ASSERT_EQ(reinterpret_cast<size_t>(ptr) % alignment, 0);
__aligned_free(ptr);
}
}
}

TEST(AlignedAlloc, TestFour) {
size_t alignment = 0;
size_t size = 4096;
void *ptr;
ptr = __aligned_malloc(size, alignment);
ASSERT_NE(ptr, nullptr);
__aligned_free(ptr);
}

} // namespace

0 comments on commit 52679a3

Please sign in to comment.