1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "luni/src/main/native/libcore_io_Memory.cpp" 18 19 #include <stdlib.h> 20 21 #include <functional> 22 23 #include <gtest/gtest.h> 24 25 #define ALIGNMENT 8 26 27 template<typename T, size_t NUM_ELEMENTS> 28 void swap_align_test(void (*swap_func)(T*, const T*, size_t), 29 std::function<void (T*, T*, uint64_t)> init_func) { 30 uint8_t* dst = nullptr; 31 uint8_t* src = nullptr; 32 ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&dst), ALIGNMENT, 33 sizeof(T) * NUM_ELEMENTS + ALIGNMENT)); 34 ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&src), ALIGNMENT, 35 sizeof(T) * NUM_ELEMENTS + ALIGNMENT)); 36 37 T src_buf[NUM_ELEMENTS]; 38 T dst_buf[NUM_ELEMENTS]; 39 for (uint64_t i = 0; i < NUM_ELEMENTS; i++) { 40 init_func(&src_buf[i], &dst_buf[i], i); 41 } 42 43 // Vary a few alignments. 44 for (size_t dst_align = 0; dst_align < ALIGNMENT; dst_align++) { 45 T* dst_aligned = reinterpret_cast<T*>(&dst[dst_align]); 46 for (size_t src_align = 0; src_align < ALIGNMENT; src_align++) { 47 T* src_aligned = reinterpret_cast<T*>(&src[src_align]); 48 memset(dst_aligned, 0, sizeof(T) * NUM_ELEMENTS); 49 memcpy(src_aligned, src_buf, sizeof(T) * NUM_ELEMENTS); 50 swap_func(dst_aligned, src_aligned, NUM_ELEMENTS); 51 ASSERT_EQ(0, memcmp(dst_buf, dst_aligned, sizeof(T) * NUM_ELEMENTS)) 52 << "Failed at dst align " << dst_align << " src align " << src_align; 53 } 54 } 55 free(dst); 56 free(src); 57 } 58 59 TEST(libcore, swapShorts_align_test) { 60 // Use an odd number to guarantee that the last 16-bit swap code 61 // is executed. 62 swap_align_test<jshort, 9> (swapShorts, [] (jshort* src, jshort* dst, uint64_t i) { 63 *src = ((2*i) << 8) | (2*(i+1)); 64 *dst = (2*i) | ((2*(i+1)) << 8); 65 }); 66 } 67 68 TEST(libcore, swapInts_align_test) { 69 swap_align_test<jint, 10> (swapInts, [] (jint* src, jint* dst, uint64_t i) { 70 *src = ((4*i) << 24) | ((4*(i+1)) << 16) | ((4*(i+2)) << 8) | (4*(i+3)); 71 *dst = (4*i) | ((4*(i+1)) << 8) | ((4*(i+2)) << 16) | ((4*(i+3)) << 24); 72 }); 73 } 74 75 TEST(libcore, swapLongs_align_test) { 76 swap_align_test<jlong, 10> (swapLongs, [] (jlong* src, jlong* dst, uint64_t i) { 77 *src = ((8*i) << 56) | ((8*(i+1)) << 48) | ((8*(i+2)) << 40) | ((8*(i+3)) << 32) | 78 ((8*(i+4)) << 24) | ((8*(i+5)) << 16) | ((8*(i+6)) << 8) | (8*(i+7)); 79 *dst = (8*i) | ((8*(i+1)) << 8) | ((8*(i+2)) << 16) | ((8*(i+3)) << 24) | 80 ((8*(i+4)) << 32) | ((8*(i+5)) << 40) | ((8*(i+6)) << 48) | ((8*(i+7)) << 56); 81 }); 82 } 83 84 template<typename T> 85 void memory_peek_test(T (*peek_func)(JNIEnv*, jclass, jlong), T value) { 86 T* src = nullptr; 87 ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&src), ALIGNMENT, 88 sizeof(T) + ALIGNMENT)); 89 for (size_t i = 0; i < ALIGNMENT; i++) { 90 jlong src_aligned = reinterpret_cast<jlong>(src) + i; 91 memcpy(reinterpret_cast<void*>(src_aligned), &value, sizeof(T)); 92 T result = peek_func(nullptr, nullptr, src_aligned); 93 ASSERT_EQ(value, result); 94 } 95 free(src); 96 } 97 98 TEST(libcore, Memory_peekShortNative_align_check) { 99 memory_peek_test<jshort>(Memory_peekShortNative, 0x0102); 100 } 101 102 TEST(libcore, Memory_peekIntNative_align_check) { 103 memory_peek_test<jint>(Memory_peekIntNative, 0x01020304); 104 } 105 106 TEST(libcore, Memory_peekLongNative_align_check) { 107 memory_peek_test<jlong>(Memory_peekLongNative, 0x01020405060708ULL); 108 } 109 110 template<typename T> 111 void memory_poke_test(void (*poke_func)(JNIEnv*, jclass, jlong, T), T value) { 112 T* dst = nullptr; 113 ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&dst), ALIGNMENT, 114 sizeof(T) + ALIGNMENT)); 115 for(size_t i = 0; i < ALIGNMENT; i++) { 116 memset(dst, 0, sizeof(T) + ALIGNMENT); 117 jlong dst_aligned = reinterpret_cast<jlong>(dst) + i; 118 poke_func(nullptr, nullptr, dst_aligned, value); 119 ASSERT_EQ(0, memcmp(reinterpret_cast<void*>(dst_aligned), &value, sizeof(T))); 120 } 121 free(dst); 122 } 123 124 TEST(libcore, Memory_pokeShortNative_align_check) { 125 memory_poke_test<jshort>(Memory_pokeShortNative, 0x0102); 126 } 127 128 TEST(libcore, Memory_pokeIntNative_align_check) { 129 memory_poke_test<jint>(Memory_pokeIntNative, 0x01020304); 130 } 131 132 TEST(libcore, Memory_pokeLongNative_align_check) { 133 memory_poke_test<jlong>(Memory_pokeLongNative, 0x0102030405060708ULL); 134 } 135