Home | History | Annotate | Line # | Download | only in nvptx
      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