1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2016 Advanced Micro Devices, Inc. 3bf215546Sopenharmony_ci * All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 6bf215546Sopenharmony_ci * a copy of this software and associated documentation files (the 7bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 8bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 9bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 10bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 11bf215546Sopenharmony_ci * the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 14bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 15bf215546Sopenharmony_ci * of the Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19bf215546Sopenharmony_ci * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20bf215546Sopenharmony_ci * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 21bf215546Sopenharmony_ci * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * \file 30bf215546Sopenharmony_ci * 31bf215546Sopenharmony_ci * Helper library for carving out smaller allocations (called "(slab) entries") 32bf215546Sopenharmony_ci * from larger buffers (called "slabs"). 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * The library supports maintaining separate heaps (e.g. VRAM vs. GTT). The 35bf215546Sopenharmony_ci * meaning of each heap is treated as opaque by this library. 36bf215546Sopenharmony_ci * 37bf215546Sopenharmony_ci * The library allows delaying the re-use of an entry, i.e. an entry may be 38bf215546Sopenharmony_ci * freed by calling \ref pb_slab_free even while the corresponding buffer 39bf215546Sopenharmony_ci * region is still in use by the GPU. A callback function is called to 40bf215546Sopenharmony_ci * determine when it is safe to allocate the entry again; the user of this 41bf215546Sopenharmony_ci * library is expected to maintain the required fences or similar. 42bf215546Sopenharmony_ci */ 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci#ifndef PB_SLAB_H 45bf215546Sopenharmony_ci#define PB_SLAB_H 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci#include "pb_buffer.h" 48bf215546Sopenharmony_ci#include "util/simple_mtx.h" 49bf215546Sopenharmony_ci#include "util/list.h" 50bf215546Sopenharmony_ci#include "os/os_thread.h" 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_cistruct pb_slab; 53bf215546Sopenharmony_cistruct pb_slabs; 54bf215546Sopenharmony_cistruct pb_slab_group; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci/* Descriptor of a slab entry. 57bf215546Sopenharmony_ci * 58bf215546Sopenharmony_ci * The user of this utility library is expected to embed this in a larger 59bf215546Sopenharmony_ci * structure that describes a buffer object. 60bf215546Sopenharmony_ci */ 61bf215546Sopenharmony_cistruct pb_slab_entry 62bf215546Sopenharmony_ci{ 63bf215546Sopenharmony_ci struct list_head head; 64bf215546Sopenharmony_ci struct pb_slab *slab; /* the slab that contains this buffer */ 65bf215546Sopenharmony_ci unsigned group_index; /* index into pb_slabs::groups */ 66bf215546Sopenharmony_ci unsigned entry_size; 67bf215546Sopenharmony_ci}; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci/* Descriptor of a slab from which many entries are carved out. 70bf215546Sopenharmony_ci * 71bf215546Sopenharmony_ci * The user of this utility library is expected to embed this in a larger 72bf215546Sopenharmony_ci * structure that describes a buffer object. 73bf215546Sopenharmony_ci */ 74bf215546Sopenharmony_cistruct pb_slab 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct list_head head; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci struct list_head free; /* list of free pb_slab_entry structures */ 79bf215546Sopenharmony_ci unsigned num_free; /* number of entries in free list */ 80bf215546Sopenharmony_ci unsigned num_entries; /* total number of entries */ 81bf215546Sopenharmony_ci}; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci/* Callback function that is called when a new slab needs to be allocated 84bf215546Sopenharmony_ci * for fulfilling allocation requests of the given size from the given heap. 85bf215546Sopenharmony_ci * 86bf215546Sopenharmony_ci * The callback must allocate a pb_slab structure and the desired number 87bf215546Sopenharmony_ci * of entries. All entries that belong to the slab must be added to the free 88bf215546Sopenharmony_ci * list. Entries' pb_slab_entry structures must be initialized with the given 89bf215546Sopenharmony_ci * group_index. 90bf215546Sopenharmony_ci * 91bf215546Sopenharmony_ci * The callback may call pb_slab functions. 92bf215546Sopenharmony_ci */ 93bf215546Sopenharmony_citypedef struct pb_slab *(slab_alloc_fn)(void *priv, 94bf215546Sopenharmony_ci unsigned heap, 95bf215546Sopenharmony_ci unsigned entry_size, 96bf215546Sopenharmony_ci unsigned group_index); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci/* Callback function that is called when all entries of a slab have been freed. 99bf215546Sopenharmony_ci * 100bf215546Sopenharmony_ci * The callback must free the slab and all its entries. It must not call any of 101bf215546Sopenharmony_ci * the pb_slab functions, or a deadlock (recursive mutex lock) may occur. 102bf215546Sopenharmony_ci */ 103bf215546Sopenharmony_citypedef void (slab_free_fn)(void *priv, struct pb_slab *); 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci/* Callback function to determine whether a given entry can already be reused. 106bf215546Sopenharmony_ci */ 107bf215546Sopenharmony_citypedef bool (slab_can_reclaim_fn)(void *priv, struct pb_slab_entry *); 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci/* Manager of slab allocations. The user of this utility library should embed 110bf215546Sopenharmony_ci * this in a structure somewhere and call pb_slab_init/deinit at init/shutdown 111bf215546Sopenharmony_ci * time. 112bf215546Sopenharmony_ci */ 113bf215546Sopenharmony_cistruct pb_slabs 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci simple_mtx_t mutex; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci unsigned min_order; 118bf215546Sopenharmony_ci unsigned num_orders; 119bf215546Sopenharmony_ci unsigned num_heaps; 120bf215546Sopenharmony_ci bool allow_three_fourths_allocations; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci /* One group per (heap, order, three_fourth_allocations). */ 123bf215546Sopenharmony_ci struct pb_slab_group *groups; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci /* List of entries waiting to be reclaimed, i.e. they have been passed to 126bf215546Sopenharmony_ci * pb_slab_free, but may not be safe for re-use yet. The tail points at 127bf215546Sopenharmony_ci * the most-recently freed entry. 128bf215546Sopenharmony_ci */ 129bf215546Sopenharmony_ci struct list_head reclaim; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci void *priv; 132bf215546Sopenharmony_ci slab_can_reclaim_fn *can_reclaim; 133bf215546Sopenharmony_ci slab_alloc_fn *slab_alloc; 134bf215546Sopenharmony_ci slab_free_fn *slab_free; 135bf215546Sopenharmony_ci}; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_cistruct pb_slab_entry * 138bf215546Sopenharmony_cipb_slab_alloc_reclaimed(struct pb_slabs *slabs, unsigned size, unsigned heap, bool reclaim_all); 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_cistruct pb_slab_entry * 141bf215546Sopenharmony_cipb_slab_alloc(struct pb_slabs *slabs, unsigned size, unsigned heap); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_civoid 144bf215546Sopenharmony_cipb_slab_free(struct pb_slabs* slabs, struct pb_slab_entry *entry); 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_civoid 147bf215546Sopenharmony_cipb_slabs_reclaim(struct pb_slabs *slabs); 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_cibool 150bf215546Sopenharmony_cipb_slabs_init(struct pb_slabs *slabs, 151bf215546Sopenharmony_ci unsigned min_order, unsigned max_order, 152bf215546Sopenharmony_ci unsigned num_heaps, bool allow_three_fourth_allocations, 153bf215546Sopenharmony_ci void *priv, 154bf215546Sopenharmony_ci slab_can_reclaim_fn *can_reclaim, 155bf215546Sopenharmony_ci slab_alloc_fn *slab_alloc, 156bf215546Sopenharmony_ci slab_free_fn *slab_free); 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_civoid 159bf215546Sopenharmony_cipb_slabs_deinit(struct pb_slabs *slabs); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci#endif 162