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