diff --git a/include/sys/file.h b/include/sys/file.h index 6bd16b3..37b026e 100644 --- a/include/sys/file.h +++ b/include/sys/file.h @@ -28,7 +28,7 @@ __Z_EXPORT int flock(int fd, int operation) __asm("__flock"); } #endif #else -#include +#include_next #endif #endif diff --git a/include/time.h b/include/time.h index f5ecd61..93c82db 100644 --- a/include/time.h +++ b/include/time.h @@ -42,12 +42,22 @@ __Z_EXPORT extern int (*nanosleep)(const struct timespec*, struct timespec*); #include_next -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" { diff --git a/include/zos-base.h b/include/zos-base.h index 25e2f89..a0f4aa8 100644 --- a/include/zos-base.h +++ b/include/zos-base.h @@ -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 diff --git a/src/zos.cc b/src/zos.cc index 058d790..b6a1448 100644 --- a/src/zos.cc +++ b/src/zos.cc @@ -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 @@ -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(ptr); + size_t mod = sptr % alignment; + size_t offset = alignment - mod; + assert(offset >= sizeof(void*)); + void **ptr_aligned = reinterpret_cast(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(ptr))[-1]); +#endif +} + #if defined(ZOSLIB_INITIALIZE) __init_zoslib __zoslib; #endif diff --git a/test/test-aligned-malloc.cc b/test/test-aligned-malloc.cc new file mode 100644 index 0000000..763e265 --- /dev/null +++ b/test/test-aligned-malloc.cc @@ -0,0 +1,65 @@ +#include "zos.h" +#include "gtest/gtest.h" + +#include +#include + +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(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(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(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