disk_cache.h revision 01e04c3f
101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2014 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#ifndef DISK_CACHE_H
2501e04c3fSmrg#define DISK_CACHE_H
2601e04c3fSmrg
2701e04c3fSmrg#ifdef HAVE_DLFCN_H
2801e04c3fSmrg#include <dlfcn.h>
2901e04c3fSmrg#include <stdio.h>
3001e04c3fSmrg#include "util/build_id.h"
3101e04c3fSmrg#endif
3201e04c3fSmrg#include <assert.h>
3301e04c3fSmrg#include <stdint.h>
3401e04c3fSmrg#include <stdbool.h>
3501e04c3fSmrg#include <sys/stat.h>
3601e04c3fSmrg#include "util/mesa-sha1.h"
3701e04c3fSmrg
3801e04c3fSmrg#ifdef __cplusplus
3901e04c3fSmrgextern "C" {
4001e04c3fSmrg#endif
4101e04c3fSmrg
4201e04c3fSmrg/* Size of cache keys in bytes. */
4301e04c3fSmrg#define CACHE_KEY_SIZE 20
4401e04c3fSmrg
4501e04c3fSmrg#define CACHE_DIR_NAME "mesa_shader_cache"
4601e04c3fSmrg
4701e04c3fSmrgtypedef uint8_t cache_key[CACHE_KEY_SIZE];
4801e04c3fSmrg
4901e04c3fSmrg/* WARNING: 3rd party applications might be reading the cache item metadata.
5001e04c3fSmrg * Do not change these values without making the change widely known.
5101e04c3fSmrg * Please contact Valve developers and make them aware of this change.
5201e04c3fSmrg */
5301e04c3fSmrg#define CACHE_ITEM_TYPE_UNKNOWN  0x0
5401e04c3fSmrg#define CACHE_ITEM_TYPE_GLSL     0x1
5501e04c3fSmrg
5601e04c3fSmrgtypedef void
5701e04c3fSmrg(*disk_cache_put_cb) (const void *key, signed long keySize,
5801e04c3fSmrg                      const void *value, signed long valueSize);
5901e04c3fSmrg
6001e04c3fSmrgtypedef signed long
6101e04c3fSmrg(*disk_cache_get_cb) (const void *key, signed long keySize,
6201e04c3fSmrg                      void *value, signed long valueSize);
6301e04c3fSmrg
6401e04c3fSmrgstruct cache_item_metadata {
6501e04c3fSmrg   /**
6601e04c3fSmrg    * The cache item type. This could be used to identify a GLSL cache item,
6701e04c3fSmrg    * a certain type of IR (tgsi, nir, etc), or signal that it is the final
6801e04c3fSmrg    * binary form of the shader.
6901e04c3fSmrg    */
7001e04c3fSmrg   uint32_t type;
7101e04c3fSmrg
7201e04c3fSmrg   /** GLSL cache item metadata */
7301e04c3fSmrg   cache_key *keys;   /* sha1 list of shaders that make up the cache item */
7401e04c3fSmrg   uint32_t num_keys;
7501e04c3fSmrg};
7601e04c3fSmrg
7701e04c3fSmrgstruct disk_cache;
7801e04c3fSmrg
7901e04c3fSmrgstatic inline char *
8001e04c3fSmrgdisk_cache_format_hex_id(char *buf, const uint8_t *hex_id, unsigned size)
8101e04c3fSmrg{
8201e04c3fSmrg   static const char hex_digits[] = "0123456789abcdef";
8301e04c3fSmrg   unsigned i;
8401e04c3fSmrg
8501e04c3fSmrg   for (i = 0; i < size; i += 2) {
8601e04c3fSmrg      buf[i] = hex_digits[hex_id[i >> 1] >> 4];
8701e04c3fSmrg      buf[i + 1] = hex_digits[hex_id[i >> 1] & 0x0f];
8801e04c3fSmrg   }
8901e04c3fSmrg   buf[i] = '\0';
9001e04c3fSmrg
9101e04c3fSmrg   return buf;
9201e04c3fSmrg}
9301e04c3fSmrg
9401e04c3fSmrg#ifdef HAVE_DLFCN_H
9501e04c3fSmrgstatic inline bool
9601e04c3fSmrgdisk_cache_get_function_timestamp(void *ptr, uint32_t* timestamp)
9701e04c3fSmrg{
9801e04c3fSmrg   Dl_info info;
9901e04c3fSmrg   struct stat st;
10001e04c3fSmrg   if (!dladdr(ptr, &info) || !info.dli_fname) {
10101e04c3fSmrg      return false;
10201e04c3fSmrg   }
10301e04c3fSmrg   if (stat(info.dli_fname, &st)) {
10401e04c3fSmrg      return false;
10501e04c3fSmrg   }
10601e04c3fSmrg
10701e04c3fSmrg   if (!st.st_mtime) {
10801e04c3fSmrg      fprintf(stderr, "Mesa: The provided filesystem timestamp for the cache "
10901e04c3fSmrg              "is bogus! Disabling On-disk cache.\n");
11001e04c3fSmrg      return false;
11101e04c3fSmrg   }
11201e04c3fSmrg
11301e04c3fSmrg   *timestamp = st.st_mtime;
11401e04c3fSmrg
11501e04c3fSmrg   return true;
11601e04c3fSmrg}
11701e04c3fSmrg
11801e04c3fSmrgstatic inline bool
11901e04c3fSmrgdisk_cache_get_function_identifier(void *ptr, struct mesa_sha1 *ctx)
12001e04c3fSmrg{
12101e04c3fSmrg   uint32_t timestamp;
12201e04c3fSmrg
12301e04c3fSmrg#ifdef HAVE_DL_ITERATE_PHDR
12401e04c3fSmrg   const struct build_id_note *note = NULL;
12501e04c3fSmrg   if ((note = build_id_find_nhdr_for_addr(ptr))) {
12601e04c3fSmrg      _mesa_sha1_update(ctx, build_id_data(note), build_id_length(note));
12701e04c3fSmrg   } else
12801e04c3fSmrg#endif
12901e04c3fSmrg   if (disk_cache_get_function_timestamp(ptr, &timestamp)) {
13001e04c3fSmrg      _mesa_sha1_update(ctx, &timestamp, sizeof(timestamp));
13101e04c3fSmrg   } else
13201e04c3fSmrg      return false;
13301e04c3fSmrg   return true;
13401e04c3fSmrg}
13501e04c3fSmrg#endif
13601e04c3fSmrg
13701e04c3fSmrg/* Provide inlined stub functions if the shader cache is disabled. */
13801e04c3fSmrg
13901e04c3fSmrg#ifdef ENABLE_SHADER_CACHE
14001e04c3fSmrg
14101e04c3fSmrg/**
14201e04c3fSmrg * Create a new cache object.
14301e04c3fSmrg *
14401e04c3fSmrg * This function creates the handle necessary for all subsequent cache_*
14501e04c3fSmrg * functions.
14601e04c3fSmrg *
14701e04c3fSmrg * This cache provides two distinct operations:
14801e04c3fSmrg *
14901e04c3fSmrg *   o Storage and retrieval of arbitrary objects by cryptographic
15001e04c3fSmrg *     name (or "key").  This is provided via disk_cache_put() and
15101e04c3fSmrg *     disk_cache_get().
15201e04c3fSmrg *
15301e04c3fSmrg *   o The ability to store a key alone and check later whether the
15401e04c3fSmrg *     key was previously stored. This is provided via disk_cache_put_key()
15501e04c3fSmrg *     and disk_cache_has_key().
15601e04c3fSmrg *
15701e04c3fSmrg * The put_key()/has_key() operations are conceptually identical to
15801e04c3fSmrg * put()/get() with no data, but are provided separately to allow for
15901e04c3fSmrg * a more efficient implementation.
16001e04c3fSmrg *
16101e04c3fSmrg * In all cases, the keys are sequences of 20 bytes. It is anticipated
16201e04c3fSmrg * that callers will compute appropriate SHA-1 signatures for keys,
16301e04c3fSmrg * (though nothing in this implementation directly relies on how the
16401e04c3fSmrg * names are computed). See mesa-sha1.h and _mesa_sha1_compute for
16501e04c3fSmrg * assistance in computing SHA-1 signatures.
16601e04c3fSmrg */
16701e04c3fSmrgstruct disk_cache *
16801e04c3fSmrgdisk_cache_create(const char *gpu_name, const char *timestamp,
16901e04c3fSmrg                  uint64_t driver_flags);
17001e04c3fSmrg
17101e04c3fSmrg/**
17201e04c3fSmrg * Destroy a cache object, (freeing all associated resources).
17301e04c3fSmrg */
17401e04c3fSmrgvoid
17501e04c3fSmrgdisk_cache_destroy(struct disk_cache *cache);
17601e04c3fSmrg
17701e04c3fSmrg/**
17801e04c3fSmrg * Remove the item in the cache under the name \key.
17901e04c3fSmrg */
18001e04c3fSmrgvoid
18101e04c3fSmrgdisk_cache_remove(struct disk_cache *cache, const cache_key key);
18201e04c3fSmrg
18301e04c3fSmrg/**
18401e04c3fSmrg * Store an item in the cache under the name \key.
18501e04c3fSmrg *
18601e04c3fSmrg * The item can be retrieved later with disk_cache_get(), (unless the item has
18701e04c3fSmrg * been evicted in the interim).
18801e04c3fSmrg *
18901e04c3fSmrg * Any call to disk_cache_put() may cause an existing, random item to be
19001e04c3fSmrg * evicted from the cache.
19101e04c3fSmrg */
19201e04c3fSmrgvoid
19301e04c3fSmrgdisk_cache_put(struct disk_cache *cache, const cache_key key,
19401e04c3fSmrg               const void *data, size_t size,
19501e04c3fSmrg               struct cache_item_metadata *cache_item_metadata);
19601e04c3fSmrg
19701e04c3fSmrg/**
19801e04c3fSmrg * Retrieve an item previously stored in the cache with the name <key>.
19901e04c3fSmrg *
20001e04c3fSmrg * The item must have been previously stored with a call to disk_cache_put().
20101e04c3fSmrg *
20201e04c3fSmrg * If \size is non-NULL, then, on successful return, it will be set to the
20301e04c3fSmrg * size of the object.
20401e04c3fSmrg *
20501e04c3fSmrg * \return A pointer to the stored object if found. NULL if the object
20601e04c3fSmrg * is not found, or if any error occurs, (memory allocation failure,
20701e04c3fSmrg * filesystem error, etc.). The returned data is malloc'ed so the
20801e04c3fSmrg * caller should call free() it when finished.
20901e04c3fSmrg */
21001e04c3fSmrgvoid *
21101e04c3fSmrgdisk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size);
21201e04c3fSmrg
21301e04c3fSmrg/**
21401e04c3fSmrg * Store the name \key within the cache, (without any associated data).
21501e04c3fSmrg *
21601e04c3fSmrg * Later this key can be checked with disk_cache_has_key(), (unless the key
21701e04c3fSmrg * has been evicted in the interim).
21801e04c3fSmrg *
21901e04c3fSmrg * Any call to disk_cache_put_key() may cause an existing, random key to be
22001e04c3fSmrg * evicted from the cache.
22101e04c3fSmrg */
22201e04c3fSmrgvoid
22301e04c3fSmrgdisk_cache_put_key(struct disk_cache *cache, const cache_key key);
22401e04c3fSmrg
22501e04c3fSmrg/**
22601e04c3fSmrg * Test whether the name \key was previously recorded in the cache.
22701e04c3fSmrg *
22801e04c3fSmrg * Return value: True if disk_cache_put_key() was previously called with
22901e04c3fSmrg * \key, (and the key was not evicted in the interim).
23001e04c3fSmrg *
23101e04c3fSmrg * Note: disk_cache_has_key() will only return true for keys passed to
23201e04c3fSmrg * disk_cache_put_key(). Specifically, a call to disk_cache_put() will not cause
23301e04c3fSmrg * disk_cache_has_key() to return true for the same key.
23401e04c3fSmrg */
23501e04c3fSmrgbool
23601e04c3fSmrgdisk_cache_has_key(struct disk_cache *cache, const cache_key key);
23701e04c3fSmrg
23801e04c3fSmrg/**
23901e04c3fSmrg * Compute the name \key from \data of given \size.
24001e04c3fSmrg */
24101e04c3fSmrgvoid
24201e04c3fSmrgdisk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size,
24301e04c3fSmrg                       cache_key key);
24401e04c3fSmrg
24501e04c3fSmrgvoid
24601e04c3fSmrgdisk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put,
24701e04c3fSmrg                         disk_cache_get_cb get);
24801e04c3fSmrg
24901e04c3fSmrg#else
25001e04c3fSmrg
25101e04c3fSmrgstatic inline struct disk_cache *
25201e04c3fSmrgdisk_cache_create(const char *gpu_name, const char *timestamp,
25301e04c3fSmrg                  uint64_t driver_flags)
25401e04c3fSmrg{
25501e04c3fSmrg   return NULL;
25601e04c3fSmrg}
25701e04c3fSmrg
25801e04c3fSmrgstatic inline void
25901e04c3fSmrgdisk_cache_destroy(struct disk_cache *cache) {
26001e04c3fSmrg   return;
26101e04c3fSmrg}
26201e04c3fSmrg
26301e04c3fSmrgstatic inline void
26401e04c3fSmrgdisk_cache_put(struct disk_cache *cache, const cache_key key,
26501e04c3fSmrg               const void *data, size_t size,
26601e04c3fSmrg               struct cache_item_metadata *cache_item_metadata)
26701e04c3fSmrg{
26801e04c3fSmrg   return;
26901e04c3fSmrg}
27001e04c3fSmrg
27101e04c3fSmrgstatic inline void
27201e04c3fSmrgdisk_cache_remove(struct disk_cache *cache, const cache_key key)
27301e04c3fSmrg{
27401e04c3fSmrg   return;
27501e04c3fSmrg}
27601e04c3fSmrg
27701e04c3fSmrgstatic inline uint8_t *
27801e04c3fSmrgdisk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
27901e04c3fSmrg{
28001e04c3fSmrg   return NULL;
28101e04c3fSmrg}
28201e04c3fSmrg
28301e04c3fSmrgstatic inline void
28401e04c3fSmrgdisk_cache_put_key(struct disk_cache *cache, const cache_key key)
28501e04c3fSmrg{
28601e04c3fSmrg   return;
28701e04c3fSmrg}
28801e04c3fSmrg
28901e04c3fSmrgstatic inline bool
29001e04c3fSmrgdisk_cache_has_key(struct disk_cache *cache, const cache_key key)
29101e04c3fSmrg{
29201e04c3fSmrg   return false;
29301e04c3fSmrg}
29401e04c3fSmrg
29501e04c3fSmrgstatic inline void
29601e04c3fSmrgdisk_cache_compute_key(struct disk_cache *cache, const void *data, size_t size,
29701e04c3fSmrg                       const cache_key key)
29801e04c3fSmrg{
29901e04c3fSmrg   return;
30001e04c3fSmrg}
30101e04c3fSmrg
30201e04c3fSmrgstatic inline void
30301e04c3fSmrgdisk_cache_set_callbacks(struct disk_cache *cache, disk_cache_put_cb put,
30401e04c3fSmrg                         disk_cache_get_cb get)
30501e04c3fSmrg{
30601e04c3fSmrg   return;
30701e04c3fSmrg}
30801e04c3fSmrg
30901e04c3fSmrg#endif /* ENABLE_SHADER_CACHE */
31001e04c3fSmrg
31101e04c3fSmrg#ifdef __cplusplus
31201e04c3fSmrg}
31301e04c3fSmrg#endif
31401e04c3fSmrg
31501e04c3fSmrg#endif /* CACHE_H */
316