1 1.1 mrg /* Copyright (C) 2023-2024 Free Software Foundation, Inc. 2 1.1 mrg 3 1.1 mrg This file is part of the GNU Offloading and Multi Processing Library 4 1.1 mrg (libgomp). 5 1.1 mrg 6 1.1 mrg Libgomp is free software; you can redistribute it and/or modify it 7 1.1 mrg under the terms of the GNU General Public License as published by 8 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg any later version. 10 1.1 mrg 11 1.1 mrg Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 1.1 mrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 1.1 mrg more details. 15 1.1 mrg 16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg You should have received a copy of the GNU General Public License and 21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg <http://www.gnu.org/licenses/>. */ 24 1.1 mrg 25 1.1 mrg /* The low-latency allocators use space reserved in .shared memory when the 26 1.1 mrg kernel is launched. The heap is initialized in gomp_nvptx_main and all 27 1.1 mrg allocations are forgotten when the kernel exits. Allocations to other 28 1.1 mrg memory spaces all use the system malloc syscall. 29 1.1 mrg 30 1.1 mrg The root heap descriptor is stored elsewhere in shared memory, and each 31 1.1 mrg free chunk contains a similar descriptor for the next free chunk in the 32 1.1 mrg chain. 33 1.1 mrg 34 1.1 mrg The descriptor is two 16-bit values: offset and size, which describe the 35 1.1 mrg location of a chunk of memory available for allocation. The offset is 36 1.1 mrg relative to the base of the heap. The special value 0xffff, 0xffff 37 1.1 mrg indicates that the heap is locked. The descriptor is encoded into a 38 1.1 mrg single 32-bit integer so that it may be easily accessed atomically. 39 1.1 mrg 40 1.1 mrg Memory is allocated to the first free chunk that fits. The free chain 41 1.1 mrg is always stored in order of the offset to assist coalescing adjacent 42 1.1 mrg chunks. */ 43 1.1 mrg 44 1.1 mrg #include "libgomp.h" 45 1.1 mrg #include <stdlib.h> 46 1.1 mrg 47 1.1 mrg #define BASIC_ALLOC_PREFIX __nvptx_lowlat 48 1.1 mrg #include "../../basic-allocator.c" 49 1.1 mrg 50 1.1 mrg /* There should be some .shared space reserved for us. There's no way to 51 1.1 mrg express this magic extern sizeless array in C so use asm. */ 52 1.1 mrg asm (".extern .shared .u8 __nvptx_lowlat_pool[];\n"); 53 1.1 mrg 54 1.1 mrg static void * 55 1.1 mrg nvptx_memspace_alloc (omp_memspace_handle_t memspace, size_t size) 56 1.1 mrg { 57 1.1 mrg if (memspace == omp_low_lat_mem_space) 58 1.1 mrg { 59 1.1 mrg char *shared_pool; 60 1.1 mrg asm ("cvta.shared.u64\t%0, __nvptx_lowlat_pool;" : "=r" (shared_pool)); 61 1.1 mrg 62 1.1 mrg return __nvptx_lowlat_alloc (shared_pool, size); 63 1.1 mrg } 64 1.1 mrg else 65 1.1 mrg return malloc (size); 66 1.1 mrg } 67 1.1 mrg 68 1.1 mrg static void * 69 1.1 mrg nvptx_memspace_calloc (omp_memspace_handle_t memspace, size_t size) 70 1.1 mrg { 71 1.1 mrg if (memspace == omp_low_lat_mem_space) 72 1.1 mrg { 73 1.1 mrg char *shared_pool; 74 1.1 mrg asm ("cvta.shared.u64\t%0, __nvptx_lowlat_pool;" : "=r" (shared_pool)); 75 1.1 mrg 76 1.1 mrg return __nvptx_lowlat_calloc (shared_pool, size); 77 1.1 mrg } 78 1.1 mrg else 79 1.1 mrg return calloc (1, size); 80 1.1 mrg } 81 1.1 mrg 82 1.1 mrg static void 83 1.1 mrg nvptx_memspace_free (omp_memspace_handle_t memspace, void *addr, size_t size) 84 1.1 mrg { 85 1.1 mrg if (memspace == omp_low_lat_mem_space) 86 1.1 mrg { 87 1.1 mrg char *shared_pool; 88 1.1 mrg asm ("cvta.shared.u64\t%0, __nvptx_lowlat_pool;" : "=r" (shared_pool)); 89 1.1 mrg 90 1.1 mrg __nvptx_lowlat_free (shared_pool, addr, size); 91 1.1 mrg } 92 1.1 mrg else 93 1.1 mrg free (addr); 94 1.1 mrg } 95 1.1 mrg 96 1.1 mrg static void * 97 1.1 mrg nvptx_memspace_realloc (omp_memspace_handle_t memspace, void *addr, 98 1.1 mrg size_t oldsize, size_t size) 99 1.1 mrg { 100 1.1 mrg if (memspace == omp_low_lat_mem_space) 101 1.1 mrg { 102 1.1 mrg char *shared_pool; 103 1.1 mrg asm ("cvta.shared.u64\t%0, __nvptx_lowlat_pool;" : "=r" (shared_pool)); 104 1.1 mrg 105 1.1 mrg return __nvptx_lowlat_realloc (shared_pool, addr, oldsize, size); 106 1.1 mrg } 107 1.1 mrg else 108 1.1 mrg return realloc (addr, size); 109 1.1 mrg } 110 1.1 mrg 111 1.1 mrg static inline int 112 1.1 mrg nvptx_memspace_validate (omp_memspace_handle_t memspace, unsigned access) 113 1.1 mrg { 114 1.1 mrg #if __PTX_ISA_VERSION_MAJOR__ > 4 \ 115 1.1 mrg || (__PTX_ISA_VERSION_MAJOR__ == 4 && __PTX_ISA_VERSION_MINOR >= 1) 116 1.1 mrg /* Disallow use of low-latency memory when it must be accessible by 117 1.1 mrg all threads. */ 118 1.1 mrg return (memspace != omp_low_lat_mem_space 119 1.1 mrg || access != omp_atv_all); 120 1.1 mrg #else 121 1.1 mrg /* Low-latency memory is not available before PTX 4.1. */ 122 1.1 mrg return (memspace != omp_low_lat_mem_space); 123 1.1 mrg #endif 124 1.1 mrg } 125 1.1 mrg 126 1.1 mrg #define MEMSPACE_ALLOC(MEMSPACE, SIZE, PIN) \ 127 1.1 mrg nvptx_memspace_alloc (MEMSPACE, ((void)(PIN), (SIZE))) 128 1.1 mrg #define MEMSPACE_CALLOC(MEMSPACE, SIZE, PIN) \ 129 1.1 mrg nvptx_memspace_calloc (MEMSPACE, ((void)(PIN), (SIZE))) 130 1.1 mrg #define MEMSPACE_REALLOC(MEMSPACE, ADDR, OLDSIZE, SIZE, OLDPIN, PIN) \ 131 1.1 mrg nvptx_memspace_realloc (MEMSPACE, ADDR, OLDSIZE, \ 132 1.1 mrg ((void)(OLDPIN), (void)(PIN), (SIZE))) 133 1.1 mrg #define MEMSPACE_FREE(MEMSPACE, ADDR, SIZE, PIN) \ 134 1.1 mrg nvptx_memspace_free (MEMSPACE, ADDR, ((void)(PIN), (SIZE))) 135 1.1 mrg #define MEMSPACE_VALIDATE(MEMSPACE, ACCESS, PIN) \ 136 1.1 mrg nvptx_memspace_validate (MEMSPACE, ((void)(PIN), (ACCESS))) 137 1.1 mrg 138 1.1 mrg /* The default low-latency memspace implies omp_atv_all, which is incompatible 139 1.1 mrg with the .shared memory space. */ 140 1.1 mrg #define OMP_LOW_LAT_MEM_ALLOC_INVALID 1 141 1.1 mrg 142 1.1 mrg #include "../../allocator.c" 143