/* Copyright (C) 2023-2024 Free Software Foundation, Inc. This file is part of the GNU Offloading and Multi Processing Library (libgomp). Libgomp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ /* The low-latency allocators use space reserved in LDS memory when the kernel is launched. The heap is initialized in gomp_gcn_enter_kernel and all allocations are forgotten when the kernel exits. Allocations to other memory spaces all use the system malloc syscall. The pointers returned are 64-bit "Flat" addresses indistinguishable from regular pointers, but only compatible with the "flat_load/store" instructions. The compiler has been coded to assign default address spaces accordingly. LDS memory is not visible to other teams, and therefore may only be used when the memspace access trait is set accordingly. */ #include "libgomp.h" #include #define BASIC_ALLOC_PREFIX __gcn_lowlat #define BASIC_ALLOC_YIELD asm ("s_sleep 1" ::: "memory") #include "../../basic-allocator.c" /* The low-latency heap is located in LDS memory, but we need the __flat address space for compatibility reasons. */ #define FLAT_HEAP_PTR \ ((void *) (uintptr_t) (void __flat *) (void __lds *) GCN_LOWLAT_HEAP) static void * gcn_memspace_alloc (omp_memspace_handle_t memspace, size_t size) { if (memspace == omp_low_lat_mem_space) { char *shared_pool = FLAT_HEAP_PTR; return __gcn_lowlat_alloc (shared_pool, size); } else return malloc (size); } static void * gcn_memspace_calloc (omp_memspace_handle_t memspace, size_t size) { if (memspace == omp_low_lat_mem_space) { char *shared_pool = FLAT_HEAP_PTR; return __gcn_lowlat_calloc (shared_pool, size); } else return calloc (1, size); } static void gcn_memspace_free (omp_memspace_handle_t memspace, void *addr, size_t size) { if (memspace == omp_low_lat_mem_space) { char *shared_pool = FLAT_HEAP_PTR; __gcn_lowlat_free (shared_pool, addr, size); } else free (addr); } static void * gcn_memspace_realloc (omp_memspace_handle_t memspace, void *addr, size_t oldsize, size_t size) { if (memspace == omp_low_lat_mem_space) { char *shared_pool = FLAT_HEAP_PTR; return __gcn_lowlat_realloc (shared_pool, addr, oldsize, size); } else return realloc (addr, size); } static inline int gcn_memspace_validate (omp_memspace_handle_t memspace, unsigned access) { /* Disallow use of low-latency memory when it must be accessible by all threads. */ return (memspace != omp_low_lat_mem_space || access != omp_atv_all); } #define MEMSPACE_ALLOC(MEMSPACE, SIZE, PIN) \ gcn_memspace_alloc (MEMSPACE, ((void)(PIN), (SIZE))) #define MEMSPACE_CALLOC(MEMSPACE, SIZE, PIN) \ gcn_memspace_calloc (MEMSPACE, ((void)(PIN), (SIZE))) #define MEMSPACE_REALLOC(MEMSPACE, ADDR, OLDSIZE, SIZE, OLDPIN, PIN) \ gcn_memspace_realloc (MEMSPACE, ADDR, OLDSIZE, \ ((void)(PIN), (void)(OLDPIN), (SIZE))) #define MEMSPACE_FREE(MEMSPACE, ADDR, SIZE, PIN) \ gcn_memspace_free (MEMSPACE, ADDR, ((void)(PIN), (SIZE))) #define MEMSPACE_VALIDATE(MEMSPACE, ACCESS, PIN) \ gcn_memspace_validate (MEMSPACE, ((void)(PIN), (ACCESS))) /* The default low-latency memspace implies omp_atv_all, which is incompatible with the LDS memory space. */ #define OMP_LOW_LAT_MEM_ALLOC_INVALID 1 #include "../../allocator.c"