OSDN Git Service

util: Add power-of-two divisor support to compute_fast_udiv_info
[android-x86/external-mesa.git] / src / util / disk_cache.h
1 /*
2  * Copyright © 2014 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23
24 #ifndef DISK_CACHE_H
25 #define DISK_CACHE_H
26
27 #ifdef HAVE_DLFCN_H
28 #include <dlfcn.h>
29 #include <stdio.h>
30 #include "util/build_id.h"
31 #endif
32 #include <assert.h>
33 #include <stdint.h>
34 #include <stdbool.h>
35 #include <sys/stat.h>
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40
41 /* Size of cache keys in bytes. */
42 #define CACHE_KEY_SIZE 20
43
44 #define CACHE_DIR_NAME "mesa_shader_cache"
45
46 typedef uint8_t cache_key[CACHE_KEY_SIZE];
47
48 /* WARNING: 3rd party applications might be reading the cache item metadata.
49  * Do not change these values without making the change widely known.
50  * Please contact Valve developers and make them aware of this change.
51  */
52 #define CACHE_ITEM_TYPE_UNKNOWN  0x0
53 #define CACHE_ITEM_TYPE_GLSL     0x1
54
55 typedef void
56 (*disk_cache_put_cb) (const void *key, signed long keySize,
57                       const void *value, signed long valueSize);
58
59 typedef signed long
60 (*disk_cache_get_cb) (const void *key, signed long keySize,
61                       void *value, signed long valueSize);
62
63 struct cache_item_metadata {
64    /**
65     * The cache item type. This could be used to identify a GLSL cache item,
66     * a certain type of IR (tgsi, nir, etc), or signal that it is the final
67     * binary form of the shader.
68     */
69    uint32_t type;
70
71    /** GLSL cache item metadata */
72    cache_key *keys;   /* sha1 list of shaders that make up the cache item */
73    uint32_t num_keys;
74 };
75
76 struct disk_cache;
77
78 static inline char *
79 disk_cache_format_hex_id(char *buf, const uint8_t *hex_id, unsigned size)
80 {
81    static const char hex_digits[] = "0123456789abcdef";
82    unsigned i;
83
84    for (i = 0; i < size; i += 2) {
85       buf[i] = hex_digits[hex_id[i >> 1] >> 4];
86       buf[i + 1] = hex_digits[hex_id[i >> 1] & 0x0f];
87    }
88    buf[i] = '\0';
89
90    return buf;
91 }
92
93 #ifdef HAVE_DLFCN_H
94 static inline bool
95 disk_cache_get_function_timestamp(void *ptr, uint32_t* timestamp)
96 {
97    Dl_info info;
98    struct stat st;
99    if (!dladdr(ptr, &info) || !info.dli_fname) {
100       return false;
101    }
102    if (stat(info.dli_fname, &st)) {
103       return false;
104    }
105
106    if (!st.st_mtime) {
107       fprintf(stderr, "Mesa: The provided filesystem timestamp for the cache "
108               "is bogus! Disabling On-disk cache.\n");
109       return false;
110    }
111
112    *timestamp = st.st_mtime;
113
114    return true;
115 }
116
117 static inline bool
118 disk_cache_get_function_identifier(void *ptr, uint32_t *id)
119 {
120 #ifdef HAVE_DL_ITERATE_PHDR
121    const struct build_id_note *note = NULL;
122    if ((note = build_id_find_nhdr_for_addr(ptr))) {
123       const uint8_t *id_sha1 = build_id_data(note);
124       assert(id_sha1);
125       *id = *id_sha1;
126       return true;
127    } else
128 #endif
129    return disk_cache_get_function_timestamp(ptr, id);
130 }
131 #endif
132
133 /* Provide inlined stub functions if the shader cache is disabled. */
134
135 #ifdef ENABLE_SHADER_CACHE
136
137 /**
138  * Create a new cache object.
139  *
140  * This function creates the handle necessary for all subsequent cache_*
141  * functions.
142  *
143  * This cache provides two distinct operations:
144  *
145  *   o Storage and retrieval of arbitrary objects by cryptographic
146  *     name (or "key").  This is provided via disk_cache_put() and
147  *     disk_cache_get().
148  *
149  *   o The ability to store a key alone and check later whether the
150  *     key was previously stored. This is provided via disk_cache_put_key()
151  *     and disk_cache_has_key().
152  *
153  * The put_key()/has_key() operations are conceptually identical to
154  * put()/get() with no data, but are provided separately to allow for
155  * a more efficient implementation.
156  *
157  * In all cases, the keys are sequences of 20 bytes. It is anticipated
158  * that callers will compute appropriate SHA-1 signatures for keys,
159  * (though nothing in this implementation directly relies on how the
160  * names are computed). See mesa-sha1.h and _mesa_sha1_compute for
161  * assistance in computing SHA-1 signatures.
162  */
163 struct disk_cache *
164 disk_cache_create(const char *gpu_name, const char *timestamp,
165                   uint64_t driver_flags);
166
167 /**
168  * Destroy a cache object, (freeing all associated resources).
169  */
170 void
171 disk_cache_destroy(struct disk_cache *cache);
172
173 /**
174  * Remove the item in the cache under the name \key.
175  */
176 void
177 disk_cache_remove(struct disk_cache *cache, const cache_key key);
178
179 /**
180  * Store an item in the cache under the name \key.
181  *
182  * The item can be retrieved later with disk_cache_get(), (unless the item has
183  * been evicted in the interim).
184  *
185  * Any call to disk_cache_put() may cause an existing, random item to be
186  * evicted from the cache.
187  */
188 void
189 disk_cache_put(struct disk_cache *cache, const cache_key key,
190                const void *data, size_t size,
191                struct cache_item_metadata *cache_item_metadata);
192
193 /**
194  * Retrieve an item previously stored in the cache with the name <key>.
195  *
196  * The item must have been previously stored with a call to disk_cache_put().
197  *
198  * If \size is non-NULL, then, on successful return, it will be set to the
199  * size of the object.
200  *
201  * \return A pointer to the stored object if found. NULL if the object
202  * is not found, or if any error occurs, (memory allocation failure,
203  * filesystem error, etc.). The returned data is malloc'ed so the
204  * caller should call free() it when finished.
205  */
206 void *
207 disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size);
208
209 /**
210  * Store the name \key within the cache, (without any associated data).
211  *
212  * Later this key can be checked with disk_cache_has_key(), (unless the key
213  * has been evicted in the interim).
214  *
215  * Any call to disk_cache_put_key() may cause an existing, random key to be
216  * evicted from the cache.
217  */
218 void
219 disk_cache_put_key(struct disk_cache *cache, const cache_key key);
220
221 /**
222  * Test whether the name \key was previously recorded in the cache.
223  *
224  * Return value: True if disk_cache_put_key() was previously called with
225  * \key, (and the key was not evicted in the interim).
226  *
227  * Note: disk_cache_has_key() will only return true for keys passed to
228  * disk_cache_put_key(). Specifically, a call to disk_cache_put() will not cause
229  * disk_cache_has_key() to return true for the same key.
230  */
231 bool
232 disk_cache_has_key(struct disk_cache *cache, const cache_key key);
233
234 /**
235  * Compute the name \key from \data of given \size.
236  */
237 void
238 disk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size,
239                        cache_key key);
240
241 void
242 disk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put,
243                          disk_cache_get_cb get);
244
245 #else
246
247 static inline struct disk_cache *
248 disk_cache_create(const char *gpu_name, const char *timestamp,
249                   uint64_t driver_flags)
250 {
251    return NULL;
252 }
253
254 static inline void
255 disk_cache_destroy(struct disk_cache *cache) {
256    return;
257 }
258
259 static inline void
260 disk_cache_put(struct disk_cache *cache, const cache_key key,
261                const void *data, size_t size,
262                struct cache_item_metadata *cache_item_metadata)
263 {
264    return;
265 }
266
267 static inline void
268 disk_cache_remove(struct disk_cache *cache, const cache_key key)
269 {
270    return;
271 }
272
273 static inline uint8_t *
274 disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
275 {
276    return NULL;
277 }
278
279 static inline void
280 disk_cache_put_key(struct disk_cache *cache, const cache_key key)
281 {
282    return;
283 }
284
285 static inline bool
286 disk_cache_has_key(struct disk_cache *cache, const cache_key key)
287 {
288    return false;
289 }
290
291 static inline void
292 disk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size,
293                        const cache_key key)
294 {
295    return;
296 }
297
298 static inline void
299 disk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put,
300                          disk_cache_get_cb get)
301 {
302    return;
303 }
304
305 #endif /* ENABLE_SHADER_CACHE */
306
307 #ifdef __cplusplus
308 }
309 #endif
310
311 #endif /* CACHE_H */