229 lines · c
1// RUN: %libomp-compile -Wl,--export-dynamic && %libomp-run2 3// REQUIRES: linux4 5// Test OpenMP 6.0 memory management routines.6// Test host runtime's basic support with an emulated offload runtime.7 8#include <stdlib.h>9#include <omp.h>10 11#define NUM_DEVICES 412 13//14// Required offload runtime interfaces15//16extern int __tgt_get_num_devices(void) { return NUM_DEVICES; }17 18extern int __tgt_get_mem_resources(int num_devices, const int *devices,19 int host, omp_memspace_handle_t memspace,20 int *resources) {21 int i;22 // We expect valid inputs within this test.23 int num_resources = num_devices;24 if (resources) {25 // Simple resouce ID mapping example in the backend (=device ID).26 // This does not represent any real backend.27 for (i = 0; i < num_devices; i++)28 resources[i] = devices[i];29 }30 return num_resources;31}32 33extern void *__tgt_omp_alloc(size_t size, omp_allocator_handle_t allocator) {34 return malloc(size);35}36 37extern void __tgt_omp_free(void *ptr, omp_allocator_handle_t allocator) {38 free(ptr);39}40 41// Code above is also used by the corresponding Fortran test42 43#define CHECK_OR_RET_FAIL(Expr) \44 do { \45 if (!(Expr)) \46 return EXIT_FAILURE; \47 } while (0)48 49// Test user-initialized allocator with the given memory space50static int test_user_allocator(omp_memspace_handle_t ms) {51 omp_allocator_handle_t al = omp_null_allocator;52 al = omp_init_allocator(ms, 0, NULL);53 CHECK_OR_RET_FAIL(al != omp_null_allocator);54 void *m = omp_alloc(1024, al);55 CHECK_OR_RET_FAIL(m != NULL);56 omp_free(m, al);57 omp_destroy_allocator(al);58 return EXIT_SUCCESS;59}60 61static int test_allocator(omp_allocator_handle_t al) {62 void *m = omp_alloc(1024, al);63 CHECK_OR_RET_FAIL(m != NULL);64 omp_free(m, al);65 omp_destroy_allocator(al);66 return EXIT_SUCCESS;67}68 69static int test_mem_space(void) {70 int i, count;71 int num_devices = omp_get_num_devices();72 CHECK_OR_RET_FAIL(num_devices == NUM_DEVICES);73 74 int *all_devices = (int *)malloc(sizeof(int) * num_devices);75 for (i = 0; i < num_devices; i++)76 all_devices[i] = i;77 78 omp_memspace_handle_t predef = omp_default_mem_space;79 omp_memspace_handle_t ms1 = omp_null_mem_space;80 omp_memspace_handle_t ms2 = omp_null_mem_space;81 82 // Test the following API routines.83 // * omp_get_device_memspace84 // * omp_get_device_and_host_memspace85 // * omp_get_devices_memspace86 // * omp_get_devices_and_host_memspace87 // Test if runtime returns the same memory space handle for the same input.88 // Test if we can use the memory space to intialize allocator.89 for (i = 0; i < num_devices; i++) {90 ms1 = omp_get_device_memspace(i, predef);91 CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);92 ms2 = omp_get_device_memspace(i, predef);93 CHECK_OR_RET_FAIL(ms1 == ms2);94 CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);95 ms1 = ms2 = omp_null_mem_space;96 97 ms1 = omp_get_device_and_host_memspace(i, predef);98 CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);99 ms2 = omp_get_device_and_host_memspace(i, predef);100 CHECK_OR_RET_FAIL(ms1 == ms2);101 CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);102 ms1 = ms2 = omp_null_mem_space;103 104 for (count = 1; i + count <= num_devices; count++) {105 int *devices = &all_devices[i];106 ms1 = omp_get_devices_memspace(count, devices, predef);107 CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);108 ms2 = omp_get_devices_memspace(count, devices, predef);109 CHECK_OR_RET_FAIL(ms1 == ms2);110 CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);111 ms1 = ms2 = omp_null_mem_space;112 113 ms1 = omp_get_devices_and_host_memspace(count, devices, predef);114 CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);115 ms2 = omp_get_devices_and_host_memspace(count, devices, predef);116 CHECK_OR_RET_FAIL(ms1 == ms2);117 CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);118 ms1 = ms2 = omp_null_mem_space;119 }120 }121 122 // Test the following API routines.123 // * omp_get_devices_all_memspace124 // Test if runtime returns the same memory space handle for the same input.125 ms1 = omp_get_devices_all_memspace(predef);126 CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);127 ms2 = omp_get_devices_all_memspace(predef);128 CHECK_OR_RET_FAIL(ms1 == ms2);129 130 free(all_devices);131 132 return EXIT_SUCCESS;133}134 135static int test_mem_allocator(void) {136 int i, count;137 int num_devices = omp_get_num_devices();138 CHECK_OR_RET_FAIL(num_devices == NUM_DEVICES);139 140 int *all_devices = (int *)malloc(sizeof(int) * num_devices);141 for (i = 0; i < num_devices; i++)142 all_devices[i] = i;143 144 omp_memspace_handle_t predef = omp_default_mem_space;145 omp_allocator_handle_t al = omp_null_allocator;146 147 // Test the following API routines.148 // * omp_get_device_allocator149 // * omp_get_device_and_host_allocator150 // * omp_get_devices_allocator151 // * omp_get_devices_and_host_allocator152 for (i = 0; i < num_devices; i++) {153 al = omp_get_device_allocator(i, predef);154 CHECK_OR_RET_FAIL(al != omp_null_allocator);155 CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);156 al = omp_null_allocator;157 158 al = omp_get_device_and_host_allocator(i, predef);159 CHECK_OR_RET_FAIL(al != omp_null_allocator);160 CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);161 al = omp_null_allocator;162 163 for (count = 1; i + count <= num_devices; count++) {164 int *devices = &all_devices[i];165 al = omp_get_devices_allocator(count, devices, predef);166 CHECK_OR_RET_FAIL(al != omp_null_allocator);167 CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);168 al = omp_null_allocator;169 170 al = omp_get_devices_and_host_allocator(count, devices, predef);171 CHECK_OR_RET_FAIL(al != omp_null_allocator);172 CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);173 al = omp_null_allocator;174 }175 }176 177 // Test the following API routines.178 // * omp_get_devices_all_allocator179 al = omp_get_devices_all_allocator(predef);180 CHECK_OR_RET_FAIL(al != omp_null_allocator);181 CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);182 183 free(all_devices);184 185 return EXIT_SUCCESS;186}187 188// Just test what we can expect from the emulated backend.189static int test_sub_mem_space(void) {190 int i;191 omp_memspace_handle_t ms = omp_null_mem_space;192 ms = omp_get_devices_all_memspace(omp_default_mem_space);193 CHECK_OR_RET_FAIL(ms != omp_null_mem_space);194 int num_resources = omp_get_memspace_num_resources(ms);195 CHECK_OR_RET_FAIL(num_resources == NUM_DEVICES);196 197 // Check if single-resource sub memspace is correctly returned.198 for (i = 0; i < num_resources; i++) {199 omp_memspace_handle_t sub = omp_get_submemspace(ms, 1, &i);200 CHECK_OR_RET_FAIL(sub != omp_null_mem_space);201 CHECK_OR_RET_FAIL(sub != ms);202 int num_sub_resources = omp_get_memspace_num_resources(sub);203 CHECK_OR_RET_FAIL(num_sub_resources == 1);204 }205 206 // Check if all-resrouce sub memspace is correctly returned.207 int *resources = (int *)malloc(sizeof(int) * num_resources);208 for (i = 0; i < num_resources; i++)209 resources[i] = i;210 omp_memspace_handle_t sub = omp_get_submemspace(ms, num_resources, resources);211 CHECK_OR_RET_FAIL(sub != omp_null_mem_space);212 CHECK_OR_RET_FAIL(sub == ms);213 214 return EXIT_SUCCESS;215}216 217int main() {218 int rc = test_mem_space();219 CHECK_OR_RET_FAIL(rc == EXIT_SUCCESS);220 221 rc = test_mem_allocator();222 CHECK_OR_RET_FAIL(rc == EXIT_SUCCESS);223 224 rc = test_sub_mem_space();225 CHECK_OR_RET_FAIL(rc == EXIT_SUCCESS);226 227 return rc;228}229