1 /*
2  * Copyright (c) 2016-2019, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #ifndef SHAREDEFS_H_
19 #define SHAREDEFS_H_
20 
21 /*
22  * STG_DECLARE(name, datatype, indextype) - declare structure
23  * STG_ALLOC(name, size) - allocate
24  * STG_CLEAR(name) - clear all fields up to stg_avail
25  * STG_DELETE(name) - deallocate
26  * STG_RESET(name) - reset stg_avail
27  * i = STG_NEXT(name) - return next available index (no free list)
28  * i = STG_NEXT_SIZE(name, size) - return next available index, allocate size
29  * i = STG_NEXT_FREELIST(name) - return index from free list
30  * STG_NEED(name) - test avail vs size, realloc if needed
31  * STG_RETURN(name) - return lastest added element
32  * STG_ADD_FREELIST(name, i) - add to free list
33  * STG_ALLOC_SIDECAR(basename, name, datatype)
34  *   allocate name the same size as basename
35  *   register name on the sidecar list of basename
36  * STG_DELETE_SIDECAR(basename, name)
37  *   remove name from the sidecar list of basename
38  *   deallocate name
39  */
40 
41 /* declare:
42  *  struct{
43  *     dt* stg_base;
44  *     unsigned int stg_size, stg_avail, stg_free, stg_cleared,
45  * stg_dtsize;
46  *     void* stg_sidecar; *   }name; */
47 
48 /* declare the stg_ members; useful in a struct that also has other members */
49 #define STG_MEMBERS(dt)                                                \
50   dt *stg_base;                                                        \
51   unsigned int stg_size, stg_avail, stg_free, stg_cleared, stg_dtsize, \
52       stg_freelink_offset, stg_flags;                                  \
53   const char *stg_name;                                                \
54   void *stg_sidecar
55 
56 /* to statically initialize STG_MEMBERS */
57 #define STG_INIT NULL, 0, 0, 0, 0, 0, 0, 0, NULL, NULL
58 
59 /* declare a struct with the stg_members */
60 #define STG_DECLARE(name, dt) \
61   struct {                    \
62     STG_MEMBERS(dt);          \
63   } name
64 
65 typedef STG_DECLARE(STG, void);
66 
67 /* allocate the above structure
68  * clear all fields
69  * allocate stg_base
70  * set stg_size, stg_avail
71  * clear element zero */
72 void stg_alloc(STG *stg, int dtsize, int size, const char *name);
73 #define STG_ALLOC(name, size) \
74   stg_alloc((STG *)&name.stg_base, sizeof(name.stg_base[0]), size, #name)
75 
76 /* clear a single field */
77 void stg_clear(STG *stg, int r, int n);
78 #define STG_CLEAR(name, r) stg_clear((STG *)&name.stg_base, r, 1)
79 
80 /* clear a number of fields */
81 #define STG_CLEAR_N(name, r, n) stg_clear((STG *)&name.stg_base, r, n)
82 
83 /* clear all allocated fields */
84 void stg_clear_all(STG *stg);
85 #define STG_CLEAR_ALL(name) stg_clear_all((STG *)&name.stg_base);
86 
87 /* delete the data structure */
88 void stg_delete(STG *stg);
89 #define STG_DELETE(name) stg_delete((STG *)&name.stg_base);
90 
91 /* reset the data structure */
92 void stg_reset(STG *stg);
93 #define STG_RESET(name) stg_reset((STG *)&name.stg_base);
94 
95 /* allocate one element at stg_avail */
96 int stg_next(STG *stg, int n);
97 #define STG_NEXT(name) stg_next((STG *)&name.stg_base, 1)
98 
99 /* allocate 'size' elements at stg_avail */
100 #define STG_NEXT_SIZE(name, size) stg_next((STG *)&name.stg_base, size)
101 
102 /* check that stg_avail does not overflow stg_size */
103 void stg_need(STG *stg);
104 #define STG_NEED(name) stg_need((STG *)&name.stg_base)
105 
106 /* set free link offset */
107 void stg_set_freelink(STG *stg, int offset);
108 #define STG_SET_FREELINK(name, dt, field) \
109   stg_set_freelink((STG *)&name.stg_base, offsetof(dt, field))
110 
111 /* get the next element from free list, if any, otherwise, from stg_avail */
112 int stg_next_freelist(STG *stg);
113 #define STG_NEXT_FREELIST(name) stg_next_freelist((STG *)&name.stg_base)
114 
115 /* return latest added field */
116 void stg_return(STG *stg);
117 #define STG_RETURN(name) \
118   stg_return((STG *)&name.stg_base)
119 
120 /* put this element on the free list */
121 void stg_add_freelist(STG *stg, int r);
122 #define STG_ADD_FREELIST(name, index) \
123   stg_add_freelist((STG *)&name.stg_base, index)
124 
125 /* allocate sidecar the same size as name */
126 void stg_alloc_sidecar(STG *basestg, STG *stg, int dtsize, const char *name);
127 #define STG_ALLOC_SIDECAR(basename, name)                             \
128   stg_alloc_sidecar((STG *)&basename.stg_base, (STG *)&name.stg_base, \
129                     sizeof(name.stg_base[0]), #name)
130 
131 /* deallocate sidecar */
132 void stg_delete_sidecar(STG *basestg, STG *stg);
133 #define STG_DELETE_SIDECAR(basename, name) \
134   stg_delete_sidecar((STG *)&basename.stg_base, (STG *)&name.stg_base);
135 
136 /* set a flag in stg_flags */
137 #define STG_SETFLAG(name, flag) name.stg_flags |= (1 << (flag))
138 
139 /* test a flag in stg_flags */
140 #define STG_CHECKFLAG(name, flag) (name.stg_flags & (1 << (flag)))
141 
142 /* flags that can be set in stg_flags */
143 #define STG_FLAG_NOCLEAR 0
144 #endif
145