summaryrefslogtreecommitdiff
path: root/lib/mesa/src/util
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2024-04-02 10:42:24 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2024-04-02 10:42:24 +0000
commita3f73acb9d2cdc62692af7ff93c51f910dff2d0d (patch)
tree303d205e8e6ed9676bdcbe006a402c23bf668f6c /lib/mesa/src/util
parentf54e142455cb3c9d1662dae7e096a32a47e5409b (diff)
Merge Mesa 23.3.6
Diffstat (limited to 'lib/mesa/src/util')
-rw-r--r--lib/mesa/src/util/bitscan.h27
-rw-r--r--lib/mesa/src/util/compiler.h24
-rw-r--r--lib/mesa/src/util/disk_cache.c39
-rw-r--r--lib/mesa/src/util/disk_cache.h15
-rw-r--r--lib/mesa/src/util/hash_table.c74
-rw-r--r--lib/mesa/src/util/macros.h34
-rw-r--r--lib/mesa/src/util/mesa-sha1.c18
-rw-r--r--lib/mesa/src/util/mesa-sha1.h3
-rw-r--r--lib/mesa/src/util/meson.build57
-rw-r--r--lib/mesa/src/util/os_misc.c4
-rw-r--r--lib/mesa/src/util/ralloc.c479
-rw-r--r--lib/mesa/src/util/ralloc.h156
-rw-r--r--lib/mesa/src/util/sha1/sha1.c4
-rw-r--r--lib/mesa/src/util/sha1/sha1.h2
-rw-r--r--lib/mesa/src/util/u_cpu_detect.c77
-rw-r--r--lib/mesa/src/util/u_debug.h370
-rw-r--r--lib/mesa/src/util/u_debug_describe.c109
-rw-r--r--lib/mesa/src/util/u_debug_describe.h53
-rw-r--r--lib/mesa/src/util/u_debug_refcnt.c200
-rw-r--r--lib/mesa/src/util/u_debug_refcnt.h69
-rw-r--r--lib/mesa/src/util/u_dynarray.h2
-rw-r--r--lib/mesa/src/util/u_queue.c10
-rw-r--r--lib/mesa/src/util/u_queue.h2
-rw-r--r--lib/mesa/src/util/u_string.h9
-rw-r--r--lib/mesa/src/util/u_vector.c2
-rw-r--r--lib/mesa/src/util/u_vector.h8
-rw-r--r--lib/mesa/src/util/xmlconfig.c20
-rw-r--r--lib/mesa/src/util/xmlconfig.h1
28 files changed, 879 insertions, 989 deletions
diff --git a/lib/mesa/src/util/bitscan.h b/lib/mesa/src/util/bitscan.h
index 53cbb91e9..3da2e9639 100644
--- a/lib/mesa/src/util/bitscan.h
+++ b/lib/mesa/src/util/bitscan.h
@@ -42,6 +42,8 @@
#include <popcntintrin.h>
#endif
+#include "macros.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -120,15 +122,15 @@ u_bit_scan64(uint64_t *mask)
((b) = ffsll(__dword) - 1, __dword); \
__dword &= ~(1ull << (b)))
-/* Determine if an unsigned value is a power of two.
+/* Determine if an uint32_t value is a power of two.
*
* \note
* Zero is treated as a power of two.
*/
static inline bool
-util_is_power_of_two_or_zero(unsigned v)
+util_is_power_of_two_or_zero(uint32_t v)
{
- return (v & (v - 1)) == 0;
+ return IS_POT(v);
}
/* Determine if an uint64_t value is a power of two.
@@ -139,16 +141,16 @@ util_is_power_of_two_or_zero(unsigned v)
static inline bool
util_is_power_of_two_or_zero64(uint64_t v)
{
- return (v & (v - 1)) == 0;
+ return IS_POT(v);
}
-/* Determine if an unsigned value is a power of two.
+/* Determine if an uint32_t value is a power of two.
*
* \note
* Zero is \b not treated as a power of two.
*/
static inline bool
-util_is_power_of_two_nonzero(unsigned v)
+util_is_power_of_two_nonzero(uint32_t v)
{
/* __POPCNT__ is different from HAVE___BUILTIN_POPCOUNT. The latter
* indicates the existence of the __builtin_popcount function. The former
@@ -162,10 +164,21 @@ util_is_power_of_two_nonzero(unsigned v)
#ifdef __POPCNT__
return _mm_popcnt_u32(v) == 1;
#else
- return v != 0 && (v & (v - 1)) == 0;
+ return v != 0 && IS_POT(v);
#endif
}
+/* Determine if an uint64_t value is a power of two.
+ *
+ * \note
+ * Zero is \b not treated as a power of two.
+ */
+static inline bool
+util_is_power_of_two_nonzero64(uint64_t v)
+{
+ return v != 0 && IS_POT(v);
+}
+
/* For looping over a bitmask when you want to loop over consecutive bits
* manually, for example:
*
diff --git a/lib/mesa/src/util/compiler.h b/lib/mesa/src/util/compiler.h
index 20190cbf1..906c36feb 100644
--- a/lib/mesa/src/util/compiler.h
+++ b/lib/mesa/src/util/compiler.h
@@ -35,10 +35,16 @@
#include <assert.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "util/detect.h"
#include "util/macros.h"
-#include "util/u_endian.h"
-#include "util/detect_arch.h"
/**
* Define CPU_TO_LE32
@@ -101,4 +107,18 @@
#define FALLTHROUGH do { } while(0)
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(__HAIKU__) && !defined(__USE_MISC)
+#if !DETECT_OS_ANDROID
+typedef unsigned int uint;
+#endif
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
#endif /* COMPILER_H */
diff --git a/lib/mesa/src/util/disk_cache.c b/lib/mesa/src/util/disk_cache.c
index c4872e59e..1d23b92af 100644
--- a/lib/mesa/src/util/disk_cache.c
+++ b/lib/mesa/src/util/disk_cache.c
@@ -87,7 +87,6 @@ disk_cache_init_queue(struct disk_cache *cache)
* doesn't stall.
*/
return util_queue_init(&cache->cache_queue, "disk$", 32, 4,
- UTIL_QUEUE_INIT_SCALE_THREADS |
UTIL_QUEUE_INIT_RESIZE_IF_FULL |
UTIL_QUEUE_INIT_USE_MINIMUM_PRIORITY |
UTIL_QUEUE_INIT_SET_FULL_THREAD_AFFINITY, NULL);
@@ -107,9 +106,6 @@ disk_cache_type_create(const char *gpu_name,
uint8_t cache_version = CACHE_VERSION;
size_t cv_size = sizeof(cache_version);
- if (!disk_cache_enabled())
- return NULL;
-
/* A ralloc context for transient data during this invocation. */
local = ralloc_context(NULL);
if (local == NULL)
@@ -123,13 +119,8 @@ disk_cache_type_create(const char *gpu_name,
cache->path_init_failed = true;
cache->type = DISK_CACHE_NONE;
-#ifdef ANDROID
- /* Android needs the "disk cache" to be enabled for
- * EGL_ANDROID_blob_cache's callbacks to be called, but it doesn't actually
- * want any storing to disk to happen inside of the driver.
- */
- goto path_fail;
-#endif
+ if (!disk_cache_enabled())
+ goto path_fail;
char *path = disk_cache_generate_cache_dir(local, gpu_name, driver_id,
cache_type);
@@ -445,7 +436,7 @@ cache_put(void *job, void *gdata, int thread_index)
disk_cache_write_item_to_disk_foz(dc_job);
} else if (dc_job->cache->type == DISK_CACHE_DATABASE) {
disk_cache_db_write_item_to_disk(dc_job);
- } else {
+ } else if (dc_job->cache->type == DISK_CACHE_MULTI_FILE) {
filename = disk_cache_get_cache_filename(dc_job->cache, dc_job->key);
if (filename == NULL)
goto done;
@@ -482,17 +473,17 @@ blob_put_compressed(struct disk_cache *cache, const cache_key key,
entry->uncompressed_size = size;
- MESA_TRACE_BEGIN("deflate");
size_t compressed_size =
util_compress_deflate(data, size, entry->compressed_data, max_buf);
- MESA_TRACE_END();
if (!compressed_size)
goto out;
unsigned entry_size = compressed_size + sizeof(*entry);
- MESA_TRACE_BEGIN("blob_put");
- cache->blob_put_cb(key, CACHE_KEY_SIZE, entry, entry_size);
- MESA_TRACE_END();
+ // The curly brackets are here to only trace the blob_put_cb call
+ {
+ MESA_TRACE_SCOPE("blob_put");
+ cache->blob_put_cb(key, CACHE_KEY_SIZE, entry, entry_size);
+ }
out:
free(entry);
@@ -512,10 +503,12 @@ blob_get_compressed(struct disk_cache *cache, const cache_key key,
if (!entry)
return NULL;
- MESA_TRACE_BEGIN("blob_get");
- signed long entry_size =
- cache->blob_get_cb(key, CACHE_KEY_SIZE, entry, max_blob_size);
- MESA_TRACE_END();
+ signed long entry_size;
+ // The curly brackets are here to only trace the blob_get_cb call
+ {
+ MESA_TRACE_SCOPE("blob_get");
+ entry_size = cache->blob_get_cb(key, CACHE_KEY_SIZE, entry, max_blob_size);
+ }
if (!entry_size) {
free(entry);
@@ -529,10 +522,8 @@ blob_get_compressed(struct disk_cache *cache, const cache_key key,
}
unsigned compressed_size = entry_size - sizeof(*entry);
- MESA_TRACE_BEGIN("inflate");
bool ret = util_compress_inflate(entry->compressed_data, compressed_size,
data, entry->uncompressed_size);
- MESA_TRACE_END();
if (!ret) {
free(data);
free(entry);
@@ -603,7 +594,7 @@ disk_cache_get(struct disk_cache *cache, const cache_key key, size_t *size)
buf = disk_cache_load_item_foz(cache, key, size);
} else if (cache->type == DISK_CACHE_DATABASE) {
buf = disk_cache_db_load_item(cache, key, size);
- } else {
+ } else if (cache->type == DISK_CACHE_MULTI_FILE) {
char *filename = disk_cache_get_cache_filename(cache, key);
if (filename)
buf = disk_cache_load_item(cache, filename, size);
diff --git a/lib/mesa/src/util/disk_cache.h b/lib/mesa/src/util/disk_cache.h
index 5cb3b6a94..76a46f7ea 100644
--- a/lib/mesa/src/util/disk_cache.h
+++ b/lib/mesa/src/util/disk_cache.h
@@ -79,21 +79,6 @@ struct cache_item_metadata {
struct disk_cache;
-static inline char *
-disk_cache_format_hex_id(char *buf, const uint8_t *hex_id, unsigned size)
-{
- static const char hex_digits[] = "0123456789abcdef";
- unsigned i;
-
- for (i = 0; i < size; i += 2) {
- buf[i] = hex_digits[hex_id[i >> 1] >> 4];
- buf[i + 1] = hex_digits[hex_id[i >> 1] & 0x0f];
- }
- buf[i] = '\0';
-
- return buf;
-}
-
#ifdef HAVE_DLADDR
static inline bool
disk_cache_get_function_timestamp(void *ptr, uint32_t* timestamp)
diff --git a/lib/mesa/src/util/hash_table.c b/lib/mesa/src/util/hash_table.c
index dc00b2de8..a76ebbc03 100644
--- a/lib/mesa/src/util/hash_table.c
+++ b/lib/mesa/src/util/hash_table.c
@@ -427,8 +427,7 @@ _mesa_hash_table_rehash(struct hash_table *ht, unsigned new_size_index)
}
static struct hash_entry *
-hash_table_insert(struct hash_table *ht, uint32_t hash,
- const void *key, void *data)
+hash_table_get_entry(struct hash_table *ht, uint32_t hash, const void *key)
{
struct hash_entry *available_entry = NULL;
@@ -469,11 +468,8 @@ hash_table_insert(struct hash_table *ht, uint32_t hash,
*/
if (!entry_is_deleted(ht, entry) &&
entry->hash == hash &&
- ht->key_equals_function(key, entry->key)) {
- entry->key = key;
- entry->data = data;
+ ht->key_equals_function(key, entry->key))
return entry;
- }
hash_address += double_hash;
if (hash_address >= size)
@@ -484,8 +480,6 @@ hash_table_insert(struct hash_table *ht, uint32_t hash,
if (entry_is_deleted(ht, available_entry))
ht->deleted_entries--;
available_entry->hash = hash;
- available_entry->key = key;
- available_entry->data = data;
ht->entries++;
return available_entry;
}
@@ -496,6 +490,20 @@ hash_table_insert(struct hash_table *ht, uint32_t hash,
return NULL;
}
+static struct hash_entry *
+hash_table_insert(struct hash_table *ht, uint32_t hash,
+ const void *key, void *data)
+{
+ struct hash_entry *entry = hash_table_get_entry(ht, hash, key);
+
+ if (entry) {
+ entry->key = key;
+ entry->data = data;
+ }
+
+ return entry;
+}
+
/**
* Inserts the key with the given hash into the table.
*
@@ -769,6 +777,13 @@ key_u64_equals(const void *a, const void *b)
#define FREED_KEY_VALUE 0
+static void _mesa_hash_table_u64_delete_keys(void *data)
+{
+ struct hash_table_u64 *ht = ralloc_parent(data);
+
+ _mesa_hash_table_u64_clear(ht);
+}
+
struct hash_table_u64 *
_mesa_hash_table_u64_create(void *mem_ctx)
{
@@ -785,6 +800,31 @@ _mesa_hash_table_u64_create(void *mem_ctx)
} else {
ht->table = _mesa_hash_table_create(ht, key_u64_hash,
key_u64_equals);
+
+ /* Allocate a ralloc sub-context which takes the u64 hash table
+ * as a parent and attach a destructor to it so we can free the
+ * hash_key_u64 objects that were allocated by
+ * _mesa_hash_table_u64_insert().
+ *
+ * The order of creation of this sub-context is crucial: it needs
+ * to happen after the _mesa_hash_table_create() call to guarantee
+ * that the destructor is called before ht->table and its children
+ * are freed, otherwise the _mesa_hash_table_u64_clear() call in the
+ * destructor leads to a use-after-free situation.
+ */
+ if (ht->table) {
+ void *dummy_ctx = ralloc_context(ht);
+
+ /* If we can't allocate a sub-context, free the hash table
+ * immediately and return NULL to avoid future leaks.
+ */
+ if (!dummy_ctx) {
+ ralloc_free(ht);
+ return NULL;
+ }
+
+ ralloc_set_destructor(dummy_ctx, _mesa_hash_table_u64_delete_keys);
+ }
}
if (ht->table)
@@ -802,7 +842,7 @@ _mesa_hash_table_u64_delete_key(struct hash_entry *entry)
struct hash_key_u64 *_key = (struct hash_key_u64 *)entry->key;
if (_key)
- free(_key);
+ FREE(_key);
}
void
@@ -847,7 +887,19 @@ _mesa_hash_table_u64_insert(struct hash_table_u64 *ht, uint64_t key,
return;
_key->value = key;
- _mesa_hash_table_insert(ht->table, _key, data);
+ struct hash_entry *entry =
+ hash_table_get_entry(ht->table, key_u64_hash(_key), _key);
+
+ if (!entry) {
+ FREE(_key);
+ return;
+ }
+
+ entry->data = data;
+ if (!entry_is_present(ht->table, entry))
+ entry->key = _key;
+ else
+ FREE(_key);
}
}
@@ -905,6 +957,6 @@ _mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key)
struct hash_key *_key = (struct hash_key *)entry->key;
_mesa_hash_table_remove(ht->table, entry);
- free(_key);
+ FREE(_key);
}
}
diff --git a/lib/mesa/src/util/macros.h b/lib/mesa/src/util/macros.h
index 580fc8dcc..cfcda53ac 100644
--- a/lib/mesa/src/util/macros.h
+++ b/lib/mesa/src/util/macros.h
@@ -122,17 +122,17 @@
#if defined(HAVE___BUILTIN_UNREACHABLE) || __has_builtin(__builtin_unreachable)
#define unreachable(str) \
do { \
- assert(!str); \
+ assert(!"" str); \
__builtin_unreachable(); \
} while (0)
#elif defined (_MSC_VER)
#define unreachable(str) \
do { \
- assert(!str); \
+ assert(!"" str); \
__assume(0); \
} while (0)
#else
-#define unreachable(str) assert(!str)
+#define unreachable(str) assert(!"" str)
#endif
/**
@@ -204,9 +204,15 @@ do { \
* packed, to trade off performance for space.
*/
#ifdef HAVE_FUNC_ATTRIBUTE_PACKED
-#define PACKED __attribute__((__packed__))
+# if defined(__MINGW32__) || defined(__MINGW64__)
+# define PACKED __attribute__((gcc_struct,__packed__))
+# else
+# define PACKED __attribute__((__packed__))
+# endif
+# define ENUM_PACKED __attribute__((packed))
#else
#define PACKED
+#define ENUM_PACKED
#endif
/* Attribute pure is used for functions that have no effects other than their
@@ -344,7 +350,11 @@ do { \
/** Compute ceiling of integer quotient of A divided by B. */
#define DIV_ROUND_UP( A, B ) ( ((A) + (B) - 1) / (B) )
-/** Clamp X to [MIN,MAX]. Turn NaN into MIN, arbitrarily. */
+/**
+ * Clamp X to [MIN, MAX].
+ * This is a macro to allow float, int, unsigned, etc. types.
+ * We arbitrarily turn NaN into MIN.
+ */
#define CLAMP( X, MIN, MAX ) ( (X)>(MIN) ? ((X)>(MAX) ? (MAX) : (X)) : (MIN) )
/* Syntax sugar occuring frequently in graphics code */
@@ -356,10 +366,18 @@ do { \
/** Maximum of two values: */
#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
-/** Minimum and maximum of three values: */
+/** Minimum of three values: */
#define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C))
+
+/** Maximum of three values: */
#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C))
+/** Minimum of four values: */
+#define MIN4( A, B, C, D ) ((A) < (B) ? MIN3(A, C, D) : MIN3(B, C, D))
+
+/** Maximum of four values: */
+#define MAX4( A, B, C, D ) ((A) > (B) ? MAX3(A, C, D) : MAX3(B, C, D))
+
/** Align a value to a power of two */
#define ALIGN_POT(x, pot_align) (((x) + (pot_align) - 1) & ~((pot_align) - 1))
@@ -370,7 +388,7 @@ do { \
#define BITFIELD_BIT(b) (1u << (b))
/** Set all bits up to excluding bit b */
#define BITFIELD_MASK(b) \
- ((b) == 32 ? (~0u) : BITFIELD_BIT((b) % 32) - 1)
+ ((b) == 32 ? (~0u) : BITFIELD_BIT((b) & 31) - 1)
/** Set count bits starting from bit b */
#define BITFIELD_RANGE(b, count) \
(BITFIELD_MASK((b) + (count)) & ~BITFIELD_MASK(b))
@@ -379,7 +397,7 @@ do { \
#define BITFIELD64_BIT(b) (1ull << (b))
/** Set all bits up to excluding bit b */
#define BITFIELD64_MASK(b) \
- ((b) == 64 ? (~0ull) : BITFIELD64_BIT(b) - 1)
+ ((b) == 64 ? (~0ull) : BITFIELD64_BIT((b) & 63) - 1)
/** Set count bits starting from bit b */
#define BITFIELD64_RANGE(b, count) \
(BITFIELD64_MASK((b) + (count)) & ~BITFIELD64_MASK(b))
diff --git a/lib/mesa/src/util/mesa-sha1.c b/lib/mesa/src/util/mesa-sha1.c
index bdca1233a..eed6e34fa 100644
--- a/lib/mesa/src/util/mesa-sha1.c
+++ b/lib/mesa/src/util/mesa-sha1.c
@@ -26,6 +26,7 @@
#include "sha1/sha1.h"
#include "mesa-sha1.h"
+#include "hex.h"
#include <string.h>
#include <inttypes.h>
@@ -42,14 +43,7 @@ _mesa_sha1_compute(const void *data, size_t size, unsigned char result[20])
void
_mesa_sha1_format(char *buf, const unsigned char *sha1)
{
- static const char hex_digits[] = "0123456789abcdef";
- int i;
-
- for (i = 0; i < 40; i += 2) {
- buf[i] = hex_digits[sha1[i >> 1] >> 4];
- buf[i + 1] = hex_digits[sha1[i >> 1] & 0x0f];
- }
- buf[i] = '\0';
+ mesa_bytes_to_hex(buf, sha1, SHA1_DIGEST_LENGTH);
}
/* Convert a hashs string hexidecimal representation into its more compact
@@ -58,13 +52,7 @@ _mesa_sha1_format(char *buf, const unsigned char *sha1)
void
_mesa_sha1_hex_to_sha1(unsigned char *buf, const char *hex)
{
- for (unsigned i = 0; i < 20; i++) {
- char tmp[3];
- tmp[0] = hex[i * 2];
- tmp[1] = hex[(i * 2) + 1];
- tmp[2] = '\0';
- buf[i] = strtol(tmp, NULL, 16);
- }
+ mesa_hex_to_bytes(buf, hex, SHA1_DIGEST_LENGTH);
}
static void
diff --git a/lib/mesa/src/util/mesa-sha1.h b/lib/mesa/src/util/mesa-sha1.h
index 809fabc52..c264927d5 100644
--- a/lib/mesa/src/util/mesa-sha1.h
+++ b/lib/mesa/src/util/mesa-sha1.h
@@ -44,7 +44,8 @@ _mesa_sha1_init(struct mesa_sha1 *ctx)
static inline void
_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, size_t size)
{
- SHA1Update(ctx, (const unsigned char *)data, size);
+ if (size)
+ SHA1Update(ctx, (const unsigned char *)data, size);
}
static inline void
diff --git a/lib/mesa/src/util/meson.build b/lib/mesa/src/util/meson.build
index e74b187ed..eb88f235c 100644
--- a/lib/mesa/src/util/meson.build
+++ b/lib/mesa/src/util/meson.build
@@ -23,7 +23,11 @@
# util is self contained.
inc_util = [inc_include, include_directories('..')]
-subdir('format')
+if with_platform_android
+subdir('u_gralloc')
+endif
+
+subdir('blake3')
files_mesa_util = files(
'anon_file.h',
@@ -32,6 +36,7 @@ files_mesa_util = files(
'bitscan.c',
'bitscan.h',
'bitset.h',
+ 'blend.h',
'blob.c',
'blob.h',
'build_id.c',
@@ -64,6 +69,7 @@ files_mesa_util = files(
'half_float.h',
'hash_table.c',
'hash_table.h',
+ 'hex.h',
'u_idalloc.c',
'u_idalloc.h',
'list.h',
@@ -73,6 +79,8 @@ files_mesa_util = files(
'memstream.h',
'mesa-sha1.c',
'mesa-sha1.h',
+ 'mesa-blake3.c',
+ 'mesa-blake3.h',
'os_time.c',
'os_time.h',
'os_file.c',
@@ -119,18 +127,18 @@ files_mesa_util = files(
'strndup.h',
'strtod.c',
'strtod.h',
- 'texcompress_rgtc_tmp.h',
+ 'texcompress_astc_luts.cpp',
+ 'texcompress_astc_luts.h',
+ 'texcompress_astc_luts_wrap.cpp',
+ 'texcompress_astc_luts_wrap.h',
'timespec.h',
'u_atomic.c',
'u_atomic.h',
'u_call_once.c',
'u_call_once.h',
- 'u_debug_describe.c',
- 'u_debug_describe.h',
- 'u_debug_refcnt.c',
- 'u_debug_refcnt.h',
'u_dl.c',
'u_dl.h',
+ 'u_dynarray.c',
'u_dynarray.h',
'u_endian.h',
'u_hash_table.c',
@@ -148,6 +156,7 @@ files_mesa_util = files(
'u_memset.h',
'u_mm.c',
'u_mm.h',
+ 'u_pack_color.h',
'u_debug.c',
'u_debug.h',
'u_debug_memory.c',
@@ -159,6 +168,8 @@ files_mesa_util = files(
'u_worklist.h',
'vl_vlc.h',
'vl_rbsp.h',
+ 'vl_zscan_data.h',
+ 'vl_zscan_data.c',
'vma.c',
'vma.h',
'xxhash.h',
@@ -219,14 +230,16 @@ deps_for_libmesa_util = [
dep_dl,
dep_unwind,
dep_futex,
+ idep_blake3,
idep_mesautilc11
]
if with_platform_android
deps_for_libmesa_util += dep_android
files_debug_stack = files('u_debug_stack_android.cpp')
- else
+else
files_debug_stack = files(
+ 'dbghelp.h',
'u_debug_stack.c',
'u_debug_symbol.c',
'u_debug_symbol.h',
@@ -245,22 +258,34 @@ if with_perfetto
deps_for_libmesa_util += dep_perfetto
endif
+if with_gpuvis
+ files_mesa_util += files(
+ 'perf/u_gpuvis.c',
+ 'perf/u_gpuvis.h',
+ 'perf/gpuvis_trace_utils.h',
+ )
+endif
+
u_trace_py = files('perf/u_trace.py')
libmesa_util_sse41 = static_library(
'mesa_util_sse41',
files('streaming-load-memcpy.c'),
c_args : [c_msvc_compat_args, sse41_args],
- include_directories : [inc_include, inc_src, inc_mesa],
+ include_directories : [inc_util],
gnu_symbol_visibility : 'hidden',
)
+# subdir format provide files_mesa_format
+subdir('format')
+files_mesa_util += files_mesa_format
+
_libmesa_util = static_library(
'mesa_util',
[files_mesa_util, files_debug_stack, format_srgb],
- include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
+ include_directories : [inc_util, include_directories('format')],
dependencies : deps_for_libmesa_util,
- link_with: [libmesa_format, libmesa_util_sse41],
+ link_with: [libmesa_util_sse41],
c_args : [c_msvc_compat_args],
gnu_symbol_visibility : 'hidden',
build_by_default : false
@@ -268,13 +293,13 @@ _libmesa_util = static_library(
idep_mesautil = declare_dependency(
link_with : _libmesa_util,
- include_directories : [inc_util, inc_gallium],
+ include_directories : [inc_util],
dependencies : deps_for_libmesa_util,
)
# Only install the drirc file if we build with support for parsing drirc files
if use_xmlconfig
- install_data(files_drirc, install_dir : join_paths(get_option('datadir'), 'drirc.d'))
+ install_data(files_drirc, install_dir : join_paths(get_option('datadir'), 'drirc.d'), install_tag : 'runtime')
endif
xmlconfig_deps = []
@@ -288,7 +313,6 @@ c_xmlconfig_arg = '-DWITH_XMLCONFIG=@0@'.format(use_xmlconfig.to_int())
_libxmlconfig = static_library(
'xmlconfig',
files_xmlconfig,
- include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
dependencies : [idep_mesautil, dep_m, xmlconfig_deps],
c_args : [
c_msvc_compat_args,
@@ -312,6 +336,8 @@ idep_xmlconfig = declare_dependency(
files_xxd = files('xxd.py')
glsl2spirv = files('glsl2spirv.py')
+devenv.set('DRIRC_CONFIGDIR', meson.current_source_dir())
+
if with_tests
# DRI_CONF macros use designated initializers (required for union
# initializaiton), so we need c++2a since gtest forces us to use c++
@@ -319,7 +345,6 @@ if with_tests
test('xmlconfig',
executable('xmlconfig_test',
files('tests/xmlconfig.cpp'),
- include_directories : [inc_include, inc_src],
dependencies : [idep_mesautil, idep_xmlconfig, idep_gtest],
override_options : ['cpp_std=c++2a'],
cpp_args: ['-Wno-write-strings', c_xmlconfig_arg]
@@ -339,8 +364,10 @@ if with_tests
'tests/dag_test.cpp',
'tests/fast_idiv_by_const_test.cpp',
'tests/fast_urem_by_const_test.cpp',
+ 'tests/gc_alloc_tests.cpp',
'tests/half_float_test.cpp',
'tests/int_min_max.cpp',
+ 'tests/linear_test.cpp',
'tests/mesa-sha1_test.cpp',
'tests/os_mman_test.cpp',
'tests/perf/u_trace_test.cpp',
@@ -377,7 +404,6 @@ if with_tests
executable(
'util_tests',
files_util_tests,
- include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
dependencies : [idep_mesautil, idep_gtest],
),
suite : ['util'],
@@ -388,7 +414,6 @@ if with_tests
process_test_exe = executable(
'process_test',
files('tests/process_test.c'),
- include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
dependencies : idep_mesautil,
c_args : [c_msvc_compat_args],
)
diff --git a/lib/mesa/src/util/os_misc.c b/lib/mesa/src/util/os_misc.c
index 6ae97b983..c378a9e91 100644
--- a/lib/mesa/src/util/os_misc.c
+++ b/lib/mesa/src/util/os_misc.c
@@ -292,7 +292,7 @@ os_get_total_physical_memory(uint64_t *size)
status.dwLength = sizeof(status);
ret = GlobalMemoryStatusEx(&status);
*size = status.ullTotalPhys;
- return (ret == TRUE);
+ return (ret == true);
#else
#error unexpected platform in os_misc.c
return false;
@@ -349,7 +349,7 @@ os_get_available_system_memory(uint64_t *size)
status.dwLength = sizeof(status);
ret = GlobalMemoryStatusEx(&status);
*size = status.ullAvailPhys;
- return (ret == TRUE);
+ return (ret == true);
#else
return false;
#endif
diff --git a/lib/mesa/src/util/ralloc.c b/lib/mesa/src/util/ralloc.c
index c3a4befc1..c85c61e3d 100644
--- a/lib/mesa/src/util/ralloc.c
+++ b/lib/mesa/src/util/ralloc.c
@@ -38,9 +38,9 @@
#define CANARY 0x5A1106
#if defined(__LP64__) || defined(_WIN64)
-#define HEADER_ALIGN alignas(16)
+#define HEADER_ALIGN 16
#else
-#define HEADER_ALIGN alignas(8)
+#define HEADER_ALIGN 8
#endif
/* Align the header's size so that ralloc() allocations will return with the
@@ -50,11 +50,12 @@
*/
struct ralloc_header
{
- HEADER_ALIGN
+ alignas(HEADER_ALIGN)
#ifndef NDEBUG
/* A canary value used to determine whether a pointer is ralloc'd. */
unsigned canary;
+ unsigned size;
#endif
struct ralloc_header *parent;
@@ -139,6 +140,7 @@ ralloc_size(const void *ctx, size_t size)
#ifndef NDEBUG
info->canary = CANARY;
+ info->size = size;
#endif
return PTR_FROM_HEADER(info);
@@ -548,6 +550,7 @@ ralloc_vasprintf_rewrite_tail(char **str, size_t *start, const char *fmt,
/* The size of a slab. */
#define SLAB_SIZE (32 * 1024)
+#define GC_CONTEXT_CANARY 0xAF6B6C83
#define GC_CANARY 0xAF6B5B72
enum gc_flags {
@@ -578,7 +581,7 @@ typedef struct
* allocated using a freelist backed by a simple linear allocator.
*/
typedef struct gc_slab {
- HEADER_ALIGN
+ alignas(HEADER_ALIGN)
gc_ctx *ctx;
@@ -603,6 +606,10 @@ typedef struct gc_slab {
} gc_slab;
struct gc_ctx {
+#ifndef NDEBUG
+ unsigned canary;
+#endif
+
/* Array of slabs for fixed-size allocations. Each slab tracks allocations
* of specific sized blocks. User allocations are rounded up to the nearest
* fixed size. slabs[N] contains allocations of size
@@ -669,31 +676,38 @@ gc_context(const void *parent)
list_inithead(&ctx->slabs[i].slabs);
list_inithead(&ctx->slabs[i].free_slabs);
}
+#ifndef NDEBUG
+ ctx->canary = GC_CONTEXT_CANARY;
+#endif
return ctx;
}
-static size_t
-gc_bucket_obj_size(unsigned bucket)
+static_assert(UINT32_MAX >= MAX_FREELIST_SIZE, "Freelist sizes use uint32_t");
+
+static uint32_t
+gc_bucket_obj_size(uint32_t bucket)
{
return (bucket + 1) * FREELIST_ALIGNMENT;
}
-static unsigned
-gc_bucket_for_size(size_t size)
+static uint32_t
+gc_bucket_for_size(uint32_t size)
{
return (size - 1) / FREELIST_ALIGNMENT;
}
-static unsigned
-gc_bucket_num_objs(unsigned bucket)
+static_assert(UINT32_MAX >= SLAB_SIZE, "SLAB_SIZE use uint32_t");
+
+static uint32_t
+gc_bucket_num_objs(uint32_t bucket)
{
return (SLAB_SIZE - sizeof(gc_slab)) / gc_bucket_obj_size(bucket);
}
static gc_block_header *
-alloc_from_slab(gc_slab *slab, unsigned bucket)
+alloc_from_slab(gc_slab *slab, uint32_t bucket)
{
- size_t size = gc_bucket_obj_size(bucket);
+ uint32_t size = gc_bucket_obj_size(bucket);
gc_block_header *header;
if (slab->freelist) {
/* Prioritize already-allocated chunks, since they probably have a page
@@ -758,15 +772,15 @@ free_from_slab(gc_block_header *header, bool keep_empty_slabs)
slab->num_free++;
}
-static unsigned
-get_slab_size(unsigned bucket)
+static uint32_t
+get_slab_size(uint32_t bucket)
{
/* SLAB_SIZE rounded down to a multiple of the object size so that it's not larger than what can
* be used.
*/
- unsigned obj_size = gc_bucket_obj_size(bucket);
- unsigned num_objs = gc_bucket_num_objs(bucket);
- return align64(sizeof(gc_slab) + num_objs * obj_size, alignof(gc_slab));
+ uint32_t obj_size = gc_bucket_obj_size(bucket);
+ uint32_t num_objs = gc_bucket_num_objs(bucket);
+ return align((uint32_t)sizeof(gc_slab) + num_objs * obj_size, alignof(gc_slab));
}
static gc_slab *
@@ -801,13 +815,16 @@ gc_alloc_size(gc_ctx *ctx, size_t size, size_t align)
*/
assert((align - alignof(gc_block_header)) <= 127);
+ /* We can only align as high as the slab is. */
+ assert(align <= HEADER_ALIGN);
+
size_t header_size = align64(sizeof(gc_block_header), align);
size = align64(size, align);
size += header_size;
gc_block_header *header = NULL;
if (size <= MAX_FREELIST_SIZE) {
- unsigned bucket = gc_bucket_for_size(size);
+ uint32_t bucket = gc_bucket_for_size((uint32_t)size);
if (list_is_empty(&ctx->slabs[bucket].free_slabs) && !create_slab(ctx, bucket))
return NULL;
gc_slab *slab = list_first_entry(&ctx->slabs[bucket].free_slabs, gc_slab, free_link);
@@ -941,8 +958,7 @@ gc_sweep_end(gc_ctx *ctx)
*
* The allocator uses a fixed-sized buffer with a monotonically increasing
* offset after each allocation. If the buffer is all used, another buffer
- * is allocated, sharing the same ralloc parent, so all buffers are at
- * the same level in the ralloc hierarchy.
+ * is allocated, using the linear parent node as ralloc parent.
*
* The linear parent node is always the first buffer and keeps track of all
* other buffers.
@@ -950,141 +966,142 @@ gc_sweep_end(gc_ctx *ctx)
#define MIN_LINEAR_BUFSIZE 2048
#define SUBALLOC_ALIGNMENT 8
-#define LMAGIC 0x87b9c7d3
+#define LMAGIC_CONTEXT 0x87b9c7d3
+#define LMAGIC_NODE 0x87b910d3
-struct linear_header {
+struct linear_ctx {
- HEADER_ALIGN
+ alignas(HEADER_ALIGN)
#ifndef NDEBUG
unsigned magic; /* for debugging */
#endif
- unsigned offset; /* points to the first unused byte in the buffer */
- unsigned size; /* size of the buffer */
- void *ralloc_parent; /* new buffers will use this */
- struct linear_header *next; /* next buffer if we have more */
- struct linear_header *latest; /* the only buffer that has free space */
-
- /* After this structure, the buffer begins.
- * Each suballocation consists of linear_size_chunk as its header followed
- * by the suballocation, so it goes:
- *
- * - linear_size_chunk
- * - allocated space
- * - linear_size_chunk
- * - allocated space
- * etc.
- *
- * linear_size_chunk is only needed by linear_realloc.
- */
+ unsigned offset; /* points to the first unused byte in the latest buffer */
+ unsigned size; /* size of the latest buffer */
+ void *latest; /* the only buffer that has free space */
};
-struct linear_size_chunk {
- unsigned size; /* for realloc */
- unsigned _padding;
-};
+typedef struct linear_ctx linear_ctx;
-typedef struct linear_header linear_header;
-typedef struct linear_size_chunk linear_size_chunk;
+#ifndef NDEBUG
+struct linear_node_canary {
+ alignas(HEADER_ALIGN)
+ unsigned magic;
+ unsigned offset; /* points to the first unused byte in *this* buffer */
+};
-#define LINEAR_PARENT_TO_HEADER(parent) \
- (linear_header*) \
- ((char*)(parent) - sizeof(linear_size_chunk) - sizeof(linear_header))
+typedef struct linear_node_canary linear_node_canary;
-/* Allocate the linear buffer with its header. */
-static linear_header *
-create_linear_node(void *ralloc_ctx, unsigned min_size)
+static linear_node_canary *
+get_node_canary(void *ptr)
{
- linear_header *node;
-
- min_size += sizeof(linear_size_chunk);
-
- if (likely(min_size < MIN_LINEAR_BUFSIZE))
- min_size = MIN_LINEAR_BUFSIZE;
-
- node = ralloc_size(ralloc_ctx, sizeof(linear_header) + min_size);
- if (unlikely(!node))
- return NULL;
+ return (void *)((char *)ptr - sizeof(linear_node_canary));
+}
+#endif
+static unsigned
+get_node_canary_size()
+{
#ifndef NDEBUG
- node->magic = LMAGIC;
+ return sizeof(linear_node_canary);
+#else
+ return 0;
#endif
- node->offset = 0;
- node->size = min_size;
- node->ralloc_parent = ralloc_ctx;
- node->next = NULL;
- node->latest = node;
- return node;
}
void *
-linear_alloc_child(void *parent, unsigned size)
+linear_alloc_child(linear_ctx *ctx, unsigned size)
{
- linear_header *first = LINEAR_PARENT_TO_HEADER(parent);
- linear_header *latest = first->latest;
- linear_header *new_node;
- linear_size_chunk *ptr;
- unsigned full_size;
-
- assert(first->magic == LMAGIC);
- assert(!latest->next);
+ assert(ctx->magic == LMAGIC_CONTEXT);
+ assert(get_node_canary(ctx->latest)->magic == LMAGIC_NODE);
+ assert(get_node_canary(ctx->latest)->offset == ctx->offset);
size = ALIGN_POT(size, SUBALLOC_ALIGNMENT);
- full_size = sizeof(linear_size_chunk) + size;
- if (unlikely(latest->offset + full_size > latest->size)) {
+ if (unlikely(ctx->offset + size > ctx->size)) {
/* allocate a new node */
- new_node = create_linear_node(latest->ralloc_parent, size);
- if (unlikely(!new_node))
+ unsigned node_size = size;
+ if (likely(node_size < MIN_LINEAR_BUFSIZE))
+ node_size = MIN_LINEAR_BUFSIZE;
+
+ const unsigned canary_size = get_node_canary_size();
+ const unsigned full_size = canary_size + node_size;
+
+ /* linear context is also a ralloc context */
+ char *ptr = ralloc_size(ctx, full_size);
+ if (unlikely(!ptr))
return NULL;
- first->latest = new_node;
- latest->latest = new_node;
- latest->next = new_node;
- latest = new_node;
+#ifndef NDEBUG
+ linear_node_canary *canary = (void *) ptr;
+ canary->magic = LMAGIC_NODE;
+ canary->offset = 0;
+#endif
+
+ /* If the new buffer is going to be full, don't update `latest`
+ * pointer. Either the current one is also full, so doesn't
+ * matter, or the current one is not full, so there's still chance
+ * to use that space.
+ */
+ if (unlikely(size == node_size)) {
+#ifndef NDEBUG
+ canary->offset = size;
+#endif
+ assert((uintptr_t)(ptr + canary_size) % SUBALLOC_ALIGNMENT == 0);
+ return ptr + canary_size;
+ }
+
+ ctx->offset = 0;
+ ctx->size = node_size;
+ ctx->latest = ptr + canary_size;
}
- ptr = (linear_size_chunk *)((char*)&latest[1] + latest->offset);
- ptr->size = size;
- latest->offset += full_size;
+ void *ptr = (char *)ctx->latest + ctx->offset;
+ ctx->offset += size;
+
+#ifndef NDEBUG
+ linear_node_canary *canary = get_node_canary(ctx->latest);
+ canary->offset += size;
+#endif
- assert((uintptr_t)&ptr[1] % SUBALLOC_ALIGNMENT == 0);
- return &ptr[1];
+ assert((uintptr_t)ptr % SUBALLOC_ALIGNMENT == 0);
+ return ptr;
}
-void *
-linear_alloc_parent(void *ralloc_ctx, unsigned size)
+linear_ctx *
+linear_context(void *ralloc_ctx)
{
- linear_header *node;
+ linear_ctx *ctx;
if (unlikely(!ralloc_ctx))
return NULL;
- size = ALIGN_POT(size, SUBALLOC_ALIGNMENT);
+ const unsigned size = MIN_LINEAR_BUFSIZE;
+ const unsigned canary_size = get_node_canary_size();
+ const unsigned full_size =
+ sizeof(linear_ctx) + canary_size + size;
- node = create_linear_node(ralloc_ctx, size);
- if (unlikely(!node))
+ ctx = ralloc_size(ralloc_ctx, full_size);
+ if (unlikely(!ctx))
return NULL;
- return linear_alloc_child((char*)node +
- sizeof(linear_header) +
- sizeof(linear_size_chunk), size);
-}
-
-void *
-linear_zalloc_child(void *parent, unsigned size)
-{
- void *ptr = linear_alloc_child(parent, size);
+ ctx->offset = 0;
+ ctx->size = size;
+ ctx->latest = (char *)&ctx[1] + canary_size;
+#ifndef NDEBUG
+ ctx->magic = LMAGIC_CONTEXT;
+ linear_node_canary *canary = get_node_canary(ctx->latest);
+ canary->magic = LMAGIC_NODE;
+ canary->offset = 0;
+#endif
- if (likely(ptr))
- memset(ptr, 0, size);
- return ptr;
+ return ctx;
}
void *
-linear_zalloc_parent(void *parent, unsigned size)
+linear_zalloc_child(linear_ctx *ctx, unsigned size)
{
- void *ptr = linear_alloc_parent(parent, size);
+ void *ptr = linear_alloc_child(ctx, size);
if (likely(ptr))
memset(ptr, 0, size);
@@ -1092,67 +1109,34 @@ linear_zalloc_parent(void *parent, unsigned size)
}
void
-linear_free_parent(void *ptr)
+linear_free_context(linear_ctx *ctx)
{
- linear_header *node;
-
- if (unlikely(!ptr))
+ if (unlikely(!ctx))
return;
- node = LINEAR_PARENT_TO_HEADER(ptr);
- assert(node->magic == LMAGIC);
-
- while (node) {
- void *ptr = node;
+ assert(ctx->magic == LMAGIC_CONTEXT);
- node = node->next;
- ralloc_free(ptr);
- }
+ /* Linear context is also the ralloc parent of extra nodes. */
+ ralloc_free(ctx);
}
void
-ralloc_steal_linear_parent(void *new_ralloc_ctx, void *ptr)
+ralloc_steal_linear_context(void *new_ralloc_ctx, linear_ctx *ctx)
{
- linear_header *node;
-
- if (unlikely(!ptr))
+ if (unlikely(!ctx))
return;
+
+ assert(ctx->magic == LMAGIC_CONTEXT);
- node = LINEAR_PARENT_TO_HEADER(ptr);
- assert(node->magic == LMAGIC);
-
- while (node) {
- ralloc_steal(new_ralloc_ctx, node);
- node->ralloc_parent = new_ralloc_ctx;
- node = node->next;
- }
+ /* Linear context is also the ralloc parent of extra nodes. */
+ ralloc_steal(new_ralloc_ctx, ctx);
}
void *
-ralloc_parent_of_linear_parent(void *ptr)
+ralloc_parent_of_linear_context(linear_ctx *ctx)
{
- linear_header *node = LINEAR_PARENT_TO_HEADER(ptr);
- assert(node->magic == LMAGIC);
- return node->ralloc_parent;
-}
-
-void *
-linear_realloc(void *parent, void *old, unsigned new_size)
-{
- unsigned old_size = 0;
- ralloc_header *new_ptr;
-
- new_ptr = linear_alloc_child(parent, new_size);
-
- if (unlikely(!old))
- return new_ptr;
-
- old_size = ((linear_size_chunk*)old)[-1].size;
-
- if (likely(new_ptr && old_size))
- memcpy(new_ptr, old, MIN2(old_size, new_size));
-
- return new_ptr;
+ assert(ctx->magic == LMAGIC_CONTEXT);
+ return PTR_FROM_HEADER(get_header(ctx)->parent);
}
/* All code below is pretty much copied from ralloc and only the alloc
@@ -1160,7 +1144,7 @@ linear_realloc(void *parent, void *old, unsigned new_size)
*/
char *
-linear_strdup(void *parent, const char *str)
+linear_strdup(linear_ctx *ctx, const char *str)
{
unsigned n;
char *ptr;
@@ -1169,7 +1153,7 @@ linear_strdup(void *parent, const char *str)
return NULL;
n = strlen(str);
- ptr = linear_alloc_child(parent, n + 1);
+ ptr = linear_alloc_child(ctx, n + 1);
if (unlikely(!ptr))
return NULL;
@@ -1179,22 +1163,22 @@ linear_strdup(void *parent, const char *str)
}
char *
-linear_asprintf(void *parent, const char *fmt, ...)
+linear_asprintf(linear_ctx *ctx, const char *fmt, ...)
{
char *ptr;
va_list args;
va_start(args, fmt);
- ptr = linear_vasprintf(parent, fmt, args);
+ ptr = linear_vasprintf(ctx, fmt, args);
va_end(args);
return ptr;
}
char *
-linear_vasprintf(void *parent, const char *fmt, va_list args)
+linear_vasprintf(linear_ctx *ctx, const char *fmt, va_list args)
{
unsigned size = u_printf_length(fmt, args) + 1;
- char *ptr = linear_alloc_child(parent, size);
+ char *ptr = linear_alloc_child(ctx, size);
if (ptr != NULL)
vsnprintf(ptr, size, fmt, args);
@@ -1202,39 +1186,39 @@ linear_vasprintf(void *parent, const char *fmt, va_list args)
}
bool
-linear_asprintf_append(void *parent, char **str, const char *fmt, ...)
+linear_asprintf_append(linear_ctx *ctx, char **str, const char *fmt, ...)
{
bool success;
va_list args;
va_start(args, fmt);
- success = linear_vasprintf_append(parent, str, fmt, args);
+ success = linear_vasprintf_append(ctx, str, fmt, args);
va_end(args);
return success;
}
bool
-linear_vasprintf_append(void *parent, char **str, const char *fmt, va_list args)
+linear_vasprintf_append(linear_ctx *ctx, char **str, const char *fmt, va_list args)
{
size_t existing_length;
assert(str != NULL);
existing_length = *str ? strlen(*str) : 0;
- return linear_vasprintf_rewrite_tail(parent, str, &existing_length, fmt, args);
+ return linear_vasprintf_rewrite_tail(ctx, str, &existing_length, fmt, args);
}
bool
-linear_asprintf_rewrite_tail(void *parent, char **str, size_t *start,
+linear_asprintf_rewrite_tail(linear_ctx *ctx, char **str, size_t *start,
const char *fmt, ...)
{
bool success;
va_list args;
va_start(args, fmt);
- success = linear_vasprintf_rewrite_tail(parent, str, start, fmt, args);
+ success = linear_vasprintf_rewrite_tail(ctx, str, start, fmt, args);
va_end(args);
return success;
}
bool
-linear_vasprintf_rewrite_tail(void *parent, char **str, size_t *start,
+linear_vasprintf_rewrite_tail(linear_ctx *ctx, char **str, size_t *start,
const char *fmt, va_list args)
{
size_t new_length;
@@ -1243,17 +1227,19 @@ linear_vasprintf_rewrite_tail(void *parent, char **str, size_t *start,
assert(str != NULL);
if (unlikely(*str == NULL)) {
- *str = linear_vasprintf(parent, fmt, args);
+ *str = linear_vasprintf(ctx, fmt, args);
*start = strlen(*str);
return true;
}
new_length = u_printf_length(fmt, args);
- ptr = linear_realloc(parent, *str, *start + new_length + 1);
+ ptr = linear_alloc_child(ctx, *start + new_length + 1);
if (unlikely(ptr == NULL))
return false;
+ memcpy(ptr, *str, *start);
+
vsnprintf(ptr + *start, new_length + 1, fmt, args);
*str = ptr;
*start += new_length;
@@ -1262,17 +1248,18 @@ linear_vasprintf_rewrite_tail(void *parent, char **str, size_t *start,
/* helper routine for strcat/strncat - n is the exact amount to copy */
static bool
-linear_cat(void *parent, char **dest, const char *str, unsigned n)
+linear_cat(linear_ctx *ctx, char **dest, const char *str, unsigned n)
{
char *both;
unsigned existing_length;
assert(dest != NULL && *dest != NULL);
existing_length = strlen(*dest);
- both = linear_realloc(parent, *dest, existing_length + n + 1);
+ both = linear_alloc_child(ctx, existing_length + n + 1);
if (unlikely(both == NULL))
return false;
+ memcpy(both, *dest, existing_length);
memcpy(both + existing_length, str, n);
both[existing_length + n] = '\0';
@@ -1281,7 +1268,143 @@ linear_cat(void *parent, char **dest, const char *str, unsigned n)
}
bool
-linear_strcat(void *parent, char **dest, const char *str)
+linear_strcat(linear_ctx *ctx, char **dest, const char *str)
+{
+ return linear_cat(ctx, dest, str, strlen(str));
+}
+
+void *
+linear_alloc_child_array(linear_ctx *ctx, size_t size, unsigned count)
+{
+ if (count > SIZE_MAX/size)
+ return NULL;
+
+ return linear_alloc_child(ctx, size * count);
+}
+
+void *
+linear_zalloc_child_array(linear_ctx *ctx, size_t size, unsigned count)
{
- return linear_cat(parent, dest, str, strlen(str));
+ if (count > SIZE_MAX/size)
+ return NULL;
+
+ return linear_zalloc_child(ctx, size * count);
}
+
+typedef struct {
+ FILE *f;
+ unsigned indent;
+
+ unsigned ralloc_count;
+ unsigned linear_count;
+ unsigned gc_count;
+
+ /* These don't include padding or metadata from suballocators. */
+ unsigned content_bytes;
+ unsigned ralloc_metadata_bytes;
+ unsigned linear_metadata_bytes;
+ unsigned gc_metadata_bytes;
+
+ bool inside_linear;
+ bool inside_gc;
+} ralloc_print_info_state;
+
+static void
+ralloc_print_info_helper(ralloc_print_info_state *state, const ralloc_header *info)
+{
+ FILE *f = state->f;
+
+ if (f) {
+ for (unsigned i = 0; i < state->indent; i++) fputc(' ', f);
+ fprintf(f, "%p", info);
+ }
+
+ /* TODO: Account for padding used in various places. */
+
+#ifndef NDEBUG
+ assert(info->canary == CANARY);
+ if (f) fprintf(f, " (%d bytes)", info->size);
+ state->content_bytes += info->size;
+ state->ralloc_metadata_bytes += sizeof(ralloc_header);
+
+ const void *ptr = PTR_FROM_HEADER(info);
+ const linear_ctx *lin_ctx = ptr;
+ const gc_ctx *gc_ctx = ptr;
+
+ if (lin_ctx->magic == LMAGIC_CONTEXT) {
+ if (f) fprintf(f, " (linear context)");
+ assert(!state->inside_gc && !state->inside_linear);
+ state->inside_linear = true;
+ state->linear_metadata_bytes += sizeof(linear_ctx);
+ state->content_bytes -= sizeof(linear_ctx);
+ state->linear_count++;
+ } else if (gc_ctx->canary == GC_CONTEXT_CANARY) {
+ if (f) fprintf(f, " (gc context)");
+ assert(!state->inside_gc && !state->inside_linear);
+ state->inside_gc = true;
+ state->gc_metadata_bytes += sizeof(gc_block_header);
+ } else if (state->inside_linear) {
+ const linear_node_canary *lin_node = ptr;
+ if (lin_node->magic == LMAGIC_NODE) {
+ if (f) fprintf(f, " (linear node buffer)");
+ state->content_bytes -= sizeof(linear_node_canary);
+ state->linear_metadata_bytes += sizeof(linear_node_canary);
+ state->linear_count++;
+ }
+ } else if (state->inside_gc) {
+ if (f) fprintf(f, " (gc slab or large block)");
+ state->gc_count++;
+ }
+#endif
+
+ state->ralloc_count++;
+ if (f) fprintf(f, "\n");
+
+ const ralloc_header *c = info->child;
+ state->indent += 2;
+ while (c != NULL) {
+ ralloc_print_info_helper(state, c);
+ c = c->next;
+ }
+ state->indent -= 2;
+
+#ifndef NDEBUG
+ if (lin_ctx->magic == LMAGIC_CONTEXT) state->inside_linear = false;
+ else if (gc_ctx->canary == GC_CONTEXT_CANARY) state->inside_gc = false;
+#endif
+}
+
+void
+ralloc_print_info(FILE *f, const void *p, unsigned flags)
+{
+ ralloc_print_info_state state = {
+ .f = ((flags & RALLOC_PRINT_INFO_SUMMARY_ONLY) == 1) ? NULL : f,
+ };
+
+ const ralloc_header *info = get_header(p);
+ ralloc_print_info_helper(&state, info);
+
+ fprintf(f, "==== RALLOC INFO ptr=%p info=%p\n"
+ "ralloc allocations = %d\n"
+ " - linear = %d\n"
+ " - gc = %d\n"
+ " - other = %d\n",
+ p, info,
+ state.ralloc_count,
+ state.linear_count,
+ state.gc_count,
+ state.ralloc_count - state.linear_count - state.gc_count);
+
+ if (state.content_bytes) {
+ fprintf(f,
+ "content bytes = %d\n"
+ "ralloc metadata bytes = %d\n"
+ "linear metadata bytes = %d\n",
+ state.content_bytes,
+ state.ralloc_metadata_bytes,
+ state.linear_metadata_bytes);
+ }
+
+ fprintf(f, "====\n");
+}
+
diff --git a/lib/mesa/src/util/ralloc.h b/lib/mesa/src/util/ralloc.h
index 0fdcb3c30..58d851f18 100644
--- a/lib/mesa/src/util/ralloc.h
+++ b/lib/mesa/src/util/ralloc.h
@@ -517,7 +517,7 @@ void gc_sweep_end(gc_ctx *ctx);
*
* which is more idiomatic in C++ than calling ralloc.
*/
-#define DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(TYPE, ALLOC_FUNC) \
+#define DECLARE_RALLOC_CXX_OPERATORS_TEMPLATE(TYPE, ALLOC_FUNC) \
private: \
static void _ralloc_destructor(void *p) \
{ \
@@ -545,86 +545,166 @@ public: \
}
#define DECLARE_RALLOC_CXX_OPERATORS(type) \
- DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, ralloc_size)
+ DECLARE_RALLOC_CXX_OPERATORS_TEMPLATE(type, ralloc_size)
#define DECLARE_RZALLOC_CXX_OPERATORS(type) \
- DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, rzalloc_size)
+ DECLARE_RALLOC_CXX_OPERATORS_TEMPLATE(type, rzalloc_size)
+
+
+#define DECLARE_LINEAR_ALLOC_CXX_OPERATORS_TEMPLATE(TYPE, ALLOC_FUNC) \
+public: \
+ static void* operator new(size_t size, linear_ctx *ctx) \
+ { \
+ void *p = ALLOC_FUNC(ctx, size); \
+ assert(p != NULL); \
+ static_assert(HAS_TRIVIAL_DESTRUCTOR(TYPE)); \
+ return p; \
+ }
#define DECLARE_LINEAR_ALLOC_CXX_OPERATORS(type) \
- DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, linear_alloc_child)
+ DECLARE_LINEAR_ALLOC_CXX_OPERATORS_TEMPLATE(type, linear_alloc_child)
#define DECLARE_LINEAR_ZALLOC_CXX_OPERATORS(type) \
- DECLARE_ALLOC_CXX_OPERATORS_TEMPLATE(type, linear_zalloc_child)
+ DECLARE_LINEAR_ALLOC_CXX_OPERATORS_TEMPLATE(type, linear_zalloc_child)
+typedef struct linear_ctx linear_ctx;
/**
- * Do a fast allocation from the linear buffer, also known as the child node
+ * Do a fast allocation from the linear context, also known as the child node
* from the allocator's point of view. It can't be freed directly. You have
- * to free the parent or the ralloc parent.
+ * to free the linear context or the ralloc parent.
*
- * \param parent parent node of the linear allocator
+ * \param ctx linear context of the allocator
* \param size size to allocate (max 32 bits)
*/
-void *linear_alloc_child(void *parent, unsigned size);
+void *linear_alloc_child(linear_ctx *ctx, unsigned size);
/**
- * Allocate a parent node that will hold linear buffers. The returned
- * allocation is actually the first child node, but it's also the handle
- * of the parent node. Use it for all child node allocations.
+ * Allocate a linear context that will internally hold linear buffers.
+ * Use it for all child node allocations.
*
* \param ralloc_ctx ralloc context, must not be NULL
- * \param size size to allocate (max 32 bits)
*/
-void *linear_alloc_parent(void *ralloc_ctx, unsigned size);
+linear_ctx *linear_context(void *ralloc_ctx);
/**
* Same as linear_alloc_child, but also clears memory.
*/
-void *linear_zalloc_child(void *parent, unsigned size);
+void *linear_zalloc_child(linear_ctx *ctx, unsigned size) MALLOCLIKE;
/**
- * Same as linear_alloc_parent, but also clears memory.
+ * Free a linear context. This will free all child nodes too.
+ * Alternatively, freeing the ralloc parent will also free
+ * the linear context.
*/
-void *linear_zalloc_parent(void *ralloc_ctx, unsigned size);
+void linear_free_context(linear_ctx *ctx);
/**
- * Free the linear parent node. This will free all child nodes too.
- * Freeing the ralloc parent will also free this.
+ * Same as ralloc_steal, but steals the entire linear context.
*/
-void linear_free_parent(void *ptr);
+void ralloc_steal_linear_context(void *new_ralloc_ctx, linear_ctx *ctx);
/**
- * Same as ralloc_steal, but steals the linear parent node.
+ * Return the ralloc parent of the linear context.
*/
-void ralloc_steal_linear_parent(void *new_ralloc_ctx, void *ptr);
+void *ralloc_parent_of_linear_context(linear_ctx *ctx);
/**
- * Return the ralloc parent of the linear parent node.
+ * Do a fast allocation of an array from the linear context and initialize it to zero.
+ *
+ * Similar to \c calloc, but does not initialize the memory to zero.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \p size and \p count. This is necessary for security.
*/
-void *ralloc_parent_of_linear_parent(void *ptr);
+void *linear_alloc_child_array(linear_ctx *ctx, size_t size, unsigned count) MALLOCLIKE;
/**
- * Same as realloc except that the linear allocator doesn't free child nodes,
- * so it's reduced to memory duplication. It's used in places where
- * reallocation is required. Don't use it often. It's much slower than
- * realloc.
+ * Do a fast allocation of an array from the linear context.
+ *
+ * Similar to \c calloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \p size and \p count. This is necessary for security.
*/
-void *linear_realloc(void *parent, void *old, unsigned new_size);
+void *linear_zalloc_child_array(linear_ctx *ctx, size_t size, unsigned count) MALLOCLIKE;
/* The functions below have the same semantics as their ralloc counterparts,
* except that they always allocate a linear child node.
*/
-char *linear_strdup(void *parent, const char *str);
-char *linear_asprintf(void *parent, const char *fmt, ...);
-char *linear_vasprintf(void *parent, const char *fmt, va_list args);
-bool linear_asprintf_append(void *parent, char **str, const char *fmt, ...);
-bool linear_vasprintf_append(void *parent, char **str, const char *fmt,
+char *linear_strdup(linear_ctx *ctx, const char *str) MALLOCLIKE;
+char *linear_asprintf(linear_ctx *ctx, const char *fmt, ...) PRINTFLIKE(2, 3) MALLOCLIKE;
+char *linear_vasprintf(linear_ctx *ctx, const char *fmt, va_list args) MALLOCLIKE;
+bool linear_asprintf_append(linear_ctx *ctx, char **str, const char *fmt, ...) PRINTFLIKE(3, 4);
+bool linear_vasprintf_append(linear_ctx *ctx, char **str, const char *fmt,
va_list args);
-bool linear_asprintf_rewrite_tail(void *parent, char **str, size_t *start,
- const char *fmt, ...);
-bool linear_vasprintf_rewrite_tail(void *parent, char **str, size_t *start,
+bool linear_asprintf_rewrite_tail(linear_ctx *ctx, char **str, size_t *start,
+ const char *fmt, ...) PRINTFLIKE(4, 5);
+bool linear_vasprintf_rewrite_tail(linear_ctx *ctx, char **str, size_t *start,
const char *fmt, va_list args);
-bool linear_strcat(void *parent, char **dest, const char *str);
+bool linear_strcat(linear_ctx *ctx, char **dest, const char *str);
+
+/**
+ * \def linear_alloc(ctx, type)
+ * Do a fast allocation from the linear context.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) linear_alloc_child(ctx, sizeof(type))
+ * \endcode
+ */
+#define linear_alloc(ctx, type) ((type *) linear_alloc_child(ctx, sizeof(type)))
+
+/**
+ * \def linear_zalloc(ctx, type)
+ * Do a fast allocation from the linear context and initialize it to zero.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) linear_zalloc_child(ctx, sizeof(type))
+ * \endcode
+ */
+#define linear_zalloc(ctx, type) ((type *) linear_zalloc_child(ctx, sizeof(type)))
+
+/**
+ * \def linear_alloc_array(ctx, type, count)
+ * Do a fast allocation of an array from the linear context.
+ *
+ * Similar to \c calloc, but does not initialize the memory to zero.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count. This is necessary for security.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) linear_alloc_child_array(ctx, sizeof(type), count)
+ * \endcode
+ */
+#define linear_alloc_array(ctx, type, count) \
+ ((type *) linear_alloc_child_array(ctx, sizeof(type), count))
+
+/**
+ * \def linear_zalloc_array(ctx, type, count)
+ * Do a fast allocation of an array from the linear context and initialize it to zero
+ *
+ * Similar to \c calloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count. This is necessary for security.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) linear_zalloc_child_array(ctx, sizeof(type), count)
+ * \endcode
+ */
+#define linear_zalloc_array(ctx, type, count) \
+ ((type *) linear_zalloc_child_array(ctx, sizeof(type), count))
+
+enum {
+ RALLOC_PRINT_INFO_SUMMARY_ONLY = 1 << 0,
+};
+
+void ralloc_print_info(FILE *f, const void *p, unsigned flags);
#ifdef __cplusplus
} /* end of extern "C" */
diff --git a/lib/mesa/src/util/sha1/sha1.c b/lib/mesa/src/util/sha1/sha1.c
index 4fe2aa723..de7514c70 100644
--- a/lib/mesa/src/util/sha1/sha1.c
+++ b/lib/mesa/src/util/sha1/sha1.c
@@ -51,7 +51,7 @@ typedef union {
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
-void
+static void
SHA1Transform(uint32_t state[5], const uint8_t buffer[SHA1_BLOCK_LENGTH])
{
uint32_t a, b, c, d, e;
@@ -144,7 +144,7 @@ SHA1Update(SHA1_CTX *context, const uint8_t *data, size_t len)
/*
* Add padding and return the message digest.
*/
-void
+static void
SHA1Pad(SHA1_CTX *context)
{
uint8_t finalcount[8];
diff --git a/lib/mesa/src/util/sha1/sha1.h b/lib/mesa/src/util/sha1/sha1.h
index 029a0ae87..df534b508 100644
--- a/lib/mesa/src/util/sha1/sha1.h
+++ b/lib/mesa/src/util/sha1/sha1.h
@@ -27,8 +27,6 @@ typedef struct _SHA1_CTX {
} SHA1_CTX;
void SHA1Init(SHA1_CTX *);
-void SHA1Pad(SHA1_CTX *);
-void SHA1Transform(uint32_t [5], const uint8_t [SHA1_BLOCK_LENGTH]);
void SHA1Update(SHA1_CTX *, const uint8_t *, size_t);
void SHA1Final(uint8_t [SHA1_DIGEST_LENGTH], SHA1_CTX *);
diff --git a/lib/mesa/src/util/u_cpu_detect.c b/lib/mesa/src/util/u_cpu_detect.c
index 8baf2a7fa..3308968eb 100644
--- a/lib/mesa/src/util/u_cpu_detect.c
+++ b/lib/mesa/src/util/u_cpu_detect.c
@@ -33,11 +33,12 @@
*/
#include "util/detect.h"
-#include "pipe/p_compiler.h"
+#include "util/compiler.h"
#include "util/u_debug.h"
#include "u_cpu_detect.h"
#include "u_math.h"
+#include "os_file.h"
#include "c11/threads.h"
#include <stdio.h>
@@ -481,6 +482,40 @@ get_cpu_topology(void)
memset(util_cpu_caps.cpu_to_L3, 0xff, sizeof(util_cpu_caps.cpu_to_L3));
+#if DETECT_OS_LINUX
+ uint64_t big_cap = 0;
+ unsigned num_big_cpus = 0;
+ uint64_t *caps = malloc(sizeof(uint64_t) * util_cpu_caps.max_cpus);
+ bool fail = false;
+ for (unsigned i = 0; caps && i < util_cpu_caps.max_cpus; i++) {
+ char name[PATH_MAX];
+ snprintf(name, sizeof(name), "/sys/devices/system/cpu/cpu%u/cpu_capacity", i);
+ size_t size = 0;
+ char *cap = os_read_file(name, &size);
+ if (!cap) {
+ num_big_cpus = 0;
+ fail = true;
+ break;
+ }
+ errno = 0;
+ caps[i] = strtoull(cap, NULL, 10);
+ free(cap);
+ if (errno) {
+ fail = true;
+ break;
+ }
+ big_cap = MAX2(caps[i], big_cap);
+ }
+ if (!fail) {
+ for (unsigned i = 0; caps && i < util_cpu_caps.max_cpus; i++) {
+ if (caps[i] >= big_cap / 2)
+ num_big_cpus++;
+ }
+ }
+ free(caps);
+ util_cpu_caps.nr_big_cpus = num_big_cpus;
+#endif
+
#if DETECT_ARCH_X86 || DETECT_ARCH_X86_64
/* AMD Zen */
if (util_cpu_caps.family >= CPU_AMD_ZEN1_ZEN2 &&
@@ -821,7 +856,6 @@ _util_cpu_detect_once(void)
}
/* general feature flags */
- util_cpu_caps.has_tsc = (regs2[3] >> 4) & 1; /* 0x0000010 */
util_cpu_caps.has_mmx = (regs2[3] >> 23) & 1; /* 0x0800000 */
util_cpu_caps.has_sse = (regs2[3] >> 25) & 1; /* 0x2000000 */
util_cpu_caps.has_sse2 = (regs2[3] >> 26) & 1; /* 0x4000000 */
@@ -847,27 +881,26 @@ _util_cpu_detect_once(void)
if (cacheline > 0)
util_cpu_caps.cacheline = cacheline;
}
- if (util_cpu_caps.has_avx && regs[0] >= 0x00000007) {
+ if (regs[0] >= 0x00000007) {
uint32_t regs7[4];
cpuid_count(0x00000007, 0x00000000, regs7);
- util_cpu_caps.has_avx2 = (regs7[1] >> 5) & 1;
- }
-
- // check for avx512
- if (((regs2[2] >> 27) & 1) && // OSXSAVE
- (xgetbv() & (0x7 << 5)) && // OPMASK: upper-256 enabled by OS
- ((xgetbv() & 6) == 6)) { // XMM/YMM enabled by OS
- uint32_t regs3[4];
- cpuid_count(0x00000007, 0x00000000, regs3);
- util_cpu_caps.has_avx512f = (regs3[1] >> 16) & 1;
- util_cpu_caps.has_avx512dq = (regs3[1] >> 17) & 1;
- util_cpu_caps.has_avx512ifma = (regs3[1] >> 21) & 1;
- util_cpu_caps.has_avx512pf = (regs3[1] >> 26) & 1;
- util_cpu_caps.has_avx512er = (regs3[1] >> 27) & 1;
- util_cpu_caps.has_avx512cd = (regs3[1] >> 28) & 1;
- util_cpu_caps.has_avx512bw = (regs3[1] >> 30) & 1;
- util_cpu_caps.has_avx512vl = (regs3[1] >> 31) & 1;
- util_cpu_caps.has_avx512vbmi = (regs3[2] >> 1) & 1;
+ util_cpu_caps.has_clflushopt = (regs7[1] >> 23) & 1;
+ if (util_cpu_caps.has_avx) {
+ util_cpu_caps.has_avx2 = (regs7[1] >> 5) & 1;
+
+ // check for avx512
+ if (xgetbv() & (0x7 << 5)) { // OPMASK: upper-256 enabled by OS
+ util_cpu_caps.has_avx512f = (regs7[1] >> 16) & 1;
+ util_cpu_caps.has_avx512dq = (regs7[1] >> 17) & 1;
+ util_cpu_caps.has_avx512ifma = (regs7[1] >> 21) & 1;
+ util_cpu_caps.has_avx512pf = (regs7[1] >> 26) & 1;
+ util_cpu_caps.has_avx512er = (regs7[1] >> 27) & 1;
+ util_cpu_caps.has_avx512cd = (regs7[1] >> 28) & 1;
+ util_cpu_caps.has_avx512bw = (regs7[1] >> 30) & 1;
+ util_cpu_caps.has_avx512vl = (regs7[1] >> 31) & 1;
+ util_cpu_caps.has_avx512vbmi = (regs7[2] >> 1) & 1;
+ }
+ }
}
if (regs[1] == 0x756e6547 && regs[2] == 0x6c65746e && regs[3] == 0x49656e69) {
@@ -930,7 +963,6 @@ _util_cpu_detect_once(void)
printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type);
printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline);
- printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc);
printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx);
printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2);
printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse);
@@ -960,6 +992,7 @@ _util_cpu_detect_once(void)
printf("util_cpu_caps.has_avx512bw = %u\n", util_cpu_caps.has_avx512bw);
printf("util_cpu_caps.has_avx512vl = %u\n", util_cpu_caps.has_avx512vl);
printf("util_cpu_caps.has_avx512vbmi = %u\n", util_cpu_caps.has_avx512vbmi);
+ printf("util_cpu_caps.has_clflushopt = %u\n", util_cpu_caps.has_clflushopt);
printf("util_cpu_caps.num_L3_caches = %u\n", util_cpu_caps.num_L3_caches);
printf("util_cpu_caps.num_cpu_mask_bits = %u\n", util_cpu_caps.num_cpu_mask_bits);
}
diff --git a/lib/mesa/src/util/u_debug.h b/lib/mesa/src/util/u_debug.h
index b3505caeb..d7e63381b 100644
--- a/lib/mesa/src/util/u_debug.h
+++ b/lib/mesa/src/util/u_debug.h
@@ -1,8 +1,8 @@
/**************************************************************************
- *
+ *
* Copyright 2008 VMware, Inc.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -10,11 +10,11 @@
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
@@ -22,46 +22,90 @@
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
+ *
**************************************************************************/
/**
* @file
* Cross-platform debugging helpers.
- *
- * For now it just has assert and printf replacements, but it might be extended
- * with stack trace reports and more advanced logging in the near future.
- *
+ *
+ * For now it just has assert and printf replacements, but it might be extended
+ * with stack trace reports and more advanced logging in the near future.
+ *
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#ifndef U_DEBUG_H_
#define U_DEBUG_H_
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined(_WIN32)
+#include <sys/types.h>
+#include <unistd.h>
+#endif
#include "util/os_misc.h"
+#include "util/u_atomic.h"
+#include "util/detect_os.h"
+#include "util/macros.h"
-#if defined(PIPE_OS_HAIKU)
+#if DETECT_OS_HAIKU
/* Haiku provides debug_printf in libroot with OS.h */
#include <OS.h>
#endif
-#include "pipe/p_defines.h"
-
-
-#ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
#endif
+enum util_debug_type
+{
+ UTIL_DEBUG_TYPE_OUT_OF_MEMORY = 1,
+ UTIL_DEBUG_TYPE_ERROR,
+ UTIL_DEBUG_TYPE_SHADER_INFO,
+ UTIL_DEBUG_TYPE_PERF_INFO,
+ UTIL_DEBUG_TYPE_INFO,
+ UTIL_DEBUG_TYPE_FALLBACK,
+ UTIL_DEBUG_TYPE_CONFORMANCE,
+};
-#if defined(__GNUC__)
-#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
-#else
-#define _util_printf_format(fmt, list)
-#endif
+/**
+ * Structure that contains a callback for debug messages from the driver back
+ * to the gallium frontend.
+ */
+struct util_debug_callback
+{
+ /**
+ * When set to \c true, the callback may be called asynchronously from a
+ * driver-created thread.
+ */
+ bool async;
+
+ /**
+ * Callback for the driver to report debug/performance/etc information back
+ * to the gallium frontend.
+ *
+ * \param data user-supplied data pointer
+ * \param id message type identifier, if pointed value is 0, then a
+ * new id is assigned
+ * \param type UTIL_DEBUG_TYPE_*
+ * \param format printf-style format string
+ * \param args args for format string
+ */
+ void (*debug_message)(void *data,
+ unsigned *id,
+ enum util_debug_type type,
+ const char *fmt,
+ va_list args);
+ void *data;
+};
+
+#define _util_printf_format(fmt, list) PRINTFLIKE(fmt, list)
void _debug_vprintf(const char *format, va_list ap);
-
+
static inline void
_debug_printf(const char *format, ...)
@@ -82,7 +126,7 @@ _debug_printf(const char *format, ...)
* - avoid outputing large strings (512 bytes is the current maximum length
* that is guaranteed to be printed in all platforms)
*/
-#if !defined(PIPE_OS_HAIKU)
+#if !DETECT_OS_HAIKU
static inline void
debug_printf(const char *format, ...) _util_printf_format(1,2);
@@ -109,9 +153,9 @@ debug_printf(const char *format, ...)
*/
#define debug_printf_once(args) \
do { \
- static boolean once = TRUE; \
+ static bool once = true; \
if (once) { \
- once = FALSE; \
+ once = false; \
debug_printf args; \
} \
} while (0)
@@ -123,25 +167,15 @@ debug_printf(const char *format, ...)
#define debug_vprintf(_format, _ap) ((void)0)
#endif
-
-#ifdef DEBUG
-/**
- * Dump a blob in hex to the same place that debug_printf sends its
- * messages.
- */
-void debug_print_blob( const char *name, const void *blob, unsigned size );
-#else
-#define debug_print_blob(_name, _blob, _size) ((void)0)
-#endif
-
-
+#ifdef _WIN32
/**
- * Disable interactive error message boxes.
+ * Disable Win32 interactive error message boxes.
*
* Should be called as soon as possible for effectiveness.
*/
void
-debug_disable_error_message_boxes(void);
+debug_disable_win32_error_dialogs(void);
+#endif
/**
@@ -154,43 +188,8 @@ debug_disable_error_message_boxes(void);
#endif /* !DEBUG */
-long
-debug_get_num_option(const char *name, long dfault);
-
-#ifdef _MSC_VER
-__declspec(noreturn)
-#endif
-void _debug_assert_fail(const char *expr,
- const char *file,
- unsigned line,
- const char *function)
-#if defined(__GNUC__) && !defined(DEBUG)
- __attribute__((noreturn))
-#endif
-;
-
-
-/**
- * Assert macro
- *
- * Do not expect that the assert call terminates -- errors must be handled
- * regardless of assert behavior.
- *
- * For non debug builds the assert macro will expand to a no-op, so do not
- * call functions with side effects in the assert expression.
- */
-#ifndef NDEBUG
-#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
-#else
-#define debug_assert(expr) (void)(0 && (expr))
-#endif
-
-
-/** Override standard assert macro */
-#ifdef assert
-#undef assert
-#endif
-#define assert(expr) debug_assert(expr)
+void
+debug_get_version_option(const char *name, unsigned *major, unsigned *minor);
/**
@@ -198,10 +197,10 @@ void _debug_assert_fail(const char *expr,
*/
#ifdef DEBUG
#define debug_checkpoint() \
- _debug_printf("%s\n", __FUNCTION__)
+ _debug_printf("%s\n", __func__)
#else
#define debug_checkpoint() \
- ((void)0)
+ ((void)0)
#endif
@@ -210,10 +209,10 @@ void _debug_assert_fail(const char *expr,
*/
#ifdef DEBUG
#define debug_checkpoint_full() \
- _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
+ _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __func__)
#else
#define debug_checkpoint_full() \
- ((void)0)
+ ((void)0)
#endif
@@ -222,10 +221,10 @@ void _debug_assert_fail(const char *expr,
*/
#ifdef DEBUG
#define debug_warning(__msg) \
- _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
+ _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __func__, __msg)
#else
#define debug_warning(__msg) \
- ((void)0)
+ ((void)0)
#endif
@@ -235,16 +234,16 @@ void _debug_assert_fail(const char *expr,
#ifdef DEBUG
#define debug_warn_once(__msg) \
do { \
- static bool warned = FALSE; \
+ static bool warned = false; \
if (!warned) { \
_debug_printf("%s:%u:%s: one time warning: %s\n", \
- __FILE__, __LINE__, __FUNCTION__, __msg); \
- warned = TRUE; \
+ __FILE__, __LINE__, __func__, __msg); \
+ warned = true; \
} \
} while (0)
#else
#define debug_warn_once(__msg) \
- ((void)0)
+ ((void)0)
#endif
@@ -253,7 +252,7 @@ void _debug_assert_fail(const char *expr,
*/
#ifdef DEBUG
#define debug_error(__msg) \
- _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
+ _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __func__, __msg)
#else
#define debug_error(__msg) \
_debug_printf("error: %s\n", __msg)
@@ -262,22 +261,18 @@ void _debug_assert_fail(const char *expr,
/**
* Output a debug log message to the debug info callback.
*/
-#define pipe_debug_message(cb, type, fmt, ...) do { \
+#define util_debug_message(cb, type, fmt, ...) do { \
static unsigned id = 0; \
- if ((cb) && (cb)->debug_message) { \
- _pipe_debug_message(cb, &id, \
- PIPE_DEBUG_TYPE_ ## type, \
- fmt, ##__VA_ARGS__); \
- } \
+ _util_debug_message(cb, &id, \
+ UTIL_DEBUG_TYPE_ ## type, \
+ fmt, ##__VA_ARGS__); \
} while (0)
-struct pipe_debug_callback;
-
void
-_pipe_debug_message(
- struct pipe_debug_callback *cb,
+_util_debug_message(
+ struct util_debug_callback *cb,
unsigned *id,
- enum pipe_debug_type type,
+ enum util_debug_type type,
const char *fmt, ...) _util_printf_format(4, 5);
@@ -294,7 +289,7 @@ struct debug_named_value
/**
* Some C pre-processor magic to simplify creating named values.
- *
+ *
* Example:
* @code
* static const debug_named_value my_names[] = {
@@ -303,16 +298,16 @@ struct debug_named_value
* DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
* DEBUG_NAMED_VALUE_END
* };
- *
+ *
* ...
- * debug_printf("%s = %s\n",
+ * debug_printf("%s = %s\n",
* name,
* debug_dump_enum(my_names, my_value));
* ...
* @endcode
*/
-#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL}
-#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
+#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (uint64_t)__symbol, NULL}
+#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (uint64_t)__symbol, __desc}
#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
@@ -320,83 +315,68 @@ struct debug_named_value
* Convert a enum value to a string.
*/
const char *
-debug_dump_enum(const struct debug_named_value *names,
- unsigned long value);
-
-const char *
-debug_dump_enum_noprefix(const struct debug_named_value *names,
- const char *prefix,
- unsigned long value);
-
+debug_dump_enum(const struct debug_named_value *names,
+ uint64_t value);
/**
* Convert binary flags value to a string.
*/
const char *
-debug_dump_flags(const struct debug_named_value *names,
- unsigned long value);
+debug_dump_flags(const struct debug_named_value *names,
+ uint64_t value);
-/**
- * Function enter exit loggers
- */
-#ifdef DEBUG
-int debug_funclog_enter(const char* f, const int line, const char* file);
-void debug_funclog_exit(const char* f, const int line, const char* file);
-void debug_funclog_enter_exit(const char* f, const int line, const char* file);
-
-#define DEBUG_FUNCLOG_ENTER() \
- int __debug_decleration_work_around = \
- debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
-#define DEBUG_FUNCLOG_EXIT() \
- do { \
- (void)__debug_decleration_work_around; \
- debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
- return; \
- } while(0)
-#define DEBUG_FUNCLOG_EXIT_RET(ret) \
- do { \
- (void)__debug_decleration_work_around; \
- debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
- return ret; \
- } while(0)
-#define DEBUG_FUNCLOG_ENTER_EXIT() \
- debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
+struct debug_control {
+ const char * string;
+ uint64_t flag;
+};
-#else
-#define DEBUG_FUNCLOG_ENTER() \
- int __debug_decleration_work_around
-#define DEBUG_FUNCLOG_EXIT() \
- do { (void)__debug_decleration_work_around; return; } while(0)
-#define DEBUG_FUNCLOG_EXIT_RET(ret) \
- do { (void)__debug_decleration_work_around; return ret; } while(0)
-#define DEBUG_FUNCLOG_ENTER_EXIT()
-#endif
+uint64_t
+parse_debug_string(const char *debug,
+ const struct debug_control *control);
+uint64_t
+parse_enable_string(const char *debug,
+ uint64_t default_value,
+ const struct debug_control *control);
+
+
+bool
+comma_separated_list_contains(const char *list, const char *s);
+
/**
* Get option.
- *
- * It is an alias for getenv on Linux.
- *
- * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
- * endings with one option per line as
- *
- * NAME=value
- *
- * This file must be terminated with an extra empty line.
+ *
+ * It is an alias for getenv on Unix and Windows.
+ *
*/
const char *
debug_get_option(const char *name, const char *dfault);
-boolean
-debug_get_bool_option(const char *name, boolean dfault);
+const char *
+debug_get_option_cached(const char *name, const char *dfault);
+
+bool
+debug_parse_bool_option(const char *str, bool dfault);
+
+bool
+debug_get_bool_option(const char *name, bool dfault);
+
+int64_t
+debug_parse_num_option(const char *str, int64_t dfault);
-long
-debug_get_num_option(const char *name, long dfault);
+int64_t
+debug_get_num_option(const char *name, int64_t dfault);
+
+uint64_t
+debug_parse_flags_option(const char *name,
+ const char *str,
+ const struct debug_named_value *flags,
+ uint64_t dfault);
uint64_t
-debug_get_flags_option(const char *name,
+debug_get_flags_option(const char *name,
const struct debug_named_value *flags,
uint64_t dfault);
@@ -404,56 +384,82 @@ debug_get_flags_option(const char *name,
static const char * \
debug_get_option_ ## suffix (void) \
{ \
- static boolean first = TRUE; \
+ static bool initialized = false; \
static const char * value; \
- if (first) { \
- first = FALSE; \
- value = debug_get_option(name, dfault); \
+ if (unlikely(!p_atomic_read_relaxed(&initialized))) { \
+ const char *str = debug_get_option_cached(name, dfault); \
+ p_atomic_set(&value, str); \
+ p_atomic_set(&initialized, true); \
} \
return value; \
}
+static inline bool
+__normal_user(void)
+{
+#if defined(_WIN32)
+ return true;
+#else
+ return issetugid() == 0 && geteuid() == getuid() && getegid() == getgid();
+#endif
+}
+
+#ifndef HAVE_SECURE_GETENV
+static inline char *secure_getenv(const char *name)
+{
+ if (issetugid())
+ return NULL;
+ return getenv(name);
+}
+#endif
+
#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
-static boolean \
+static bool \
debug_get_option_ ## sufix (void) \
{ \
- static boolean first = TRUE; \
- static boolean value; \
- if (first) { \
- first = FALSE; \
- value = debug_get_bool_option(name, dfault); \
+ static bool initialized = false; \
+ static bool value; \
+ if (unlikely(!p_atomic_read_relaxed(&initialized))) { \
+ const char *str = debug_get_option_cached(name, NULL); \
+ bool parsed_value = debug_parse_bool_option(str, dfault); \
+ p_atomic_set(&value, parsed_value); \
+ p_atomic_set(&initialized, true); \
} \
return value; \
}
#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
-static long \
+static int64_t \
debug_get_option_ ## sufix (void) \
{ \
- static boolean first = TRUE; \
- static long value; \
- if (first) { \
- first = FALSE; \
- value = debug_get_num_option(name, dfault); \
+ static bool initialized = false; \
+ static int64_t value; \
+ if (unlikely(!p_atomic_read_relaxed(&initialized))) { \
+ const char *str = debug_get_option_cached(name, NULL); \
+ int64_t parsed_value = debug_parse_num_option(str, dfault); \
+ p_atomic_set(&value, parsed_value); \
+ p_atomic_set(&initialized, true); \
} \
return value; \
}
#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
-static unsigned long \
+static uint64_t \
debug_get_option_ ## sufix (void) \
{ \
- static boolean first = TRUE; \
- static unsigned long value; \
- if (first) { \
- first = FALSE; \
- value = debug_get_flags_option(name, flags, dfault); \
+ static bool initialized = false; \
+ static uint64_t value; \
+ if (unlikely(!p_atomic_read_relaxed(&initialized))) { \
+ const char *str = debug_get_option_cached(name, NULL); \
+ uint64_t parsed_value = debug_parse_flags_option(name, str, flags, dfault); \
+ p_atomic_set(&value, parsed_value); \
+ p_atomic_set(&initialized, true); \
} \
return value; \
}
-#ifdef __cplusplus
+#ifdef __cplusplus
}
#endif
diff --git a/lib/mesa/src/util/u_debug_describe.c b/lib/mesa/src/util/u_debug_describe.c
deleted file mode 100644
index 8bfd970a5..000000000
--- a/lib/mesa/src/util/u_debug_describe.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Luca Barbieri
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "pipe/p_state.h"
-#include "util/format/u_format.h"
-#include "util/u_debug_describe.h"
-#include "util/u_string.h"
-
-void
-debug_describe_reference(char* buf, UNUSED const struct pipe_reference*ptr)
-{
- strcpy(buf, "pipe_object");
-}
-
-void
-debug_describe_resource(char* buf, const struct pipe_resource *ptr)
-{
- switch(ptr->target)
- {
- case PIPE_BUFFER:
- sprintf(buf, "pipe_buffer<%u>", (unsigned)util_format_get_stride(ptr->format, ptr->width0));
- break;
- case PIPE_TEXTURE_1D:
- sprintf(buf, "pipe_texture1d<%u,%s,%u>", ptr->width0, util_format_short_name(ptr->format), ptr->last_level);
- break;
- case PIPE_TEXTURE_2D:
- sprintf(buf, "pipe_texture2d<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
- break;
- case PIPE_TEXTURE_RECT:
- sprintf(buf, "pipe_texture_rect<%u,%u,%s>", ptr->width0, ptr->height0, util_format_short_name(ptr->format));
- break;
- case PIPE_TEXTURE_CUBE:
- sprintf(buf, "pipe_texture_cube<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
- break;
- case PIPE_TEXTURE_3D:
- sprintf(buf, "pipe_texture3d<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->depth0, util_format_short_name(ptr->format), ptr->last_level);
- break;
- case PIPE_TEXTURE_1D_ARRAY:
- sprintf(buf, "pipe_texture_1darray<%u,%u,%s,%u>", ptr->width0, ptr->array_size, util_format_short_name(ptr->format), ptr->last_level);
- break;
- case PIPE_TEXTURE_2D_ARRAY:
- sprintf(buf, "pipe_texture_2darray<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->array_size, util_format_short_name(ptr->format), ptr->last_level);
- break;
- case PIPE_TEXTURE_CUBE_ARRAY:
- sprintf(buf, "pipe_texture_cubearray<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->array_size, util_format_short_name(ptr->format), ptr->last_level);
- break;
- default:
- sprintf(buf, "pipe_martian_resource<%u>", ptr->target);
- break;
- }
-}
-
-void
-debug_describe_surface(char* buf, const struct pipe_surface *ptr)
-{
- char res[128];
- debug_describe_resource(res, ptr->texture);
- sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->u.tex.level, ptr->u.tex.first_layer, ptr->u.tex.last_layer);
-}
-
-void
-debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr)
-{
- char res[128];
- debug_describe_resource(res, ptr->texture);
- sprintf(buf, "pipe_sampler_view<%s,%s>", res, util_format_short_name(ptr->format));
-}
-
-void
-debug_describe_image_view(char* buf, const struct pipe_image_view *ptr)
-{
- char res[128];
- debug_describe_resource(res, ptr->resource);
- sprintf(buf, "pipe_image_view<%s,%s>", res,
- util_format_short_name(ptr->format));
-}
-
-void
-debug_describe_so_target(char* buf,
- const struct pipe_stream_output_target *ptr)
-{
- char res[128];
- debug_describe_resource(res, ptr->buffer);
- sprintf(buf, "pipe_stream_output_target<%s,%u,%u>", res,
- ptr->buffer_offset, ptr->buffer_size);
-}
diff --git a/lib/mesa/src/util/u_debug_describe.h b/lib/mesa/src/util/u_debug_describe.h
deleted file mode 100644
index 2172ecb43..000000000
--- a/lib/mesa/src/util/u_debug_describe.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Luca Barbieri
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef U_DEBUG_DESCRIBE_H_
-#define U_DEBUG_DESCRIBE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct pipe_reference;
-struct pipe_resource;
-struct pipe_surface;
-struct pipe_sampler_view;
-struct pipe_image_view;
-
-/* a 256-byte buffer is necessary and sufficient */
-void debug_describe_reference(char* buf, const struct pipe_reference*ptr);
-void debug_describe_resource(char* buf, const struct pipe_resource *ptr);
-void debug_describe_surface(char* buf, const struct pipe_surface *ptr);
-void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr);
-void debug_describe_image_view(char* buf, const struct pipe_image_view *ptr);
-void debug_describe_so_target(char* buf,
- const struct pipe_stream_output_target *ptr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* U_DEBUG_DESCRIBE_H_ */
diff --git a/lib/mesa/src/util/u_debug_refcnt.c b/lib/mesa/src/util/u_debug_refcnt.c
deleted file mode 100644
index 06498eb67..000000000
--- a/lib/mesa/src/util/u_debug_refcnt.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Luca Barbieri
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#if defined(DEBUG)
-
-/**
- * If the GALLIUM_REFCNT_LOG env var is defined as a filename, gallium
- * reference counting will be logged to the file.
- *
- * See http://www-archive.mozilla.org/performance/refcnt-balancer.html
- * for what to do with the output on Linux, use tools/addr2line.sh to
- * postprocess it before anything else.
- */
-
-#include <stdio.h>
-
-#include "util/u_debug.h"
-#include "util/u_debug_refcnt.h"
-#include "util/u_debug_stack.h"
-#include "util/u_debug_symbol.h"
-#include "util/u_string.h"
-#include "util/u_hash_table.h"
-#include "util/u_thread.h"
-
-int debug_refcnt_state;
-
-static FILE *stream;
-
-/* TODO: maybe move this serial machinery to a stand-alone module and
- * expose it?
- */
-#ifdef PIPE_OS_WINDOWS
-static mtx_t serials_mutex;
-#else
-static mtx_t serials_mutex = _MTX_INITIALIZER_NP;
-#endif
-
-static struct hash_table *serials_hash;
-static unsigned serials_last;
-
-
-/**
- * Return a small integer serial number for the given pointer.
- */
-static boolean
-debug_serial(void *p, unsigned *pserial)
-{
- unsigned serial;
- boolean found = TRUE;
-#ifdef PIPE_OS_WINDOWS
- static boolean first = TRUE;
-
- if (first) {
- (void) mtx_init(&serials_mutex, mtx_plain);
- first = FALSE;
- }
-#endif
-
- mtx_lock(&serials_mutex);
- if (!serials_hash)
- serials_hash = util_hash_table_create_ptr_keys();
-
- serial = (unsigned) (uintptr_t) util_hash_table_get(serials_hash, p);
- if (!serial) {
- /* time to stop logging... (you'll have a 100 GB logfile at least at
- * this point) TODO: avoid this
- */
- serial = ++serials_last;
- if (!serial) {
- debug_error("More than 2^32 objects detected, aborting.\n");
- os_abort();
- }
-
- _mesa_hash_table_insert(serials_hash, p, (void *) (uintptr_t) serial);
- found = FALSE;
- }
- mtx_unlock(&serials_mutex);
-
- *pserial = serial;
-
- return found;
-}
-
-
-/**
- * Free the serial number for the given pointer.
- */
-static void
-debug_serial_delete(void *p)
-{
- mtx_lock(&serials_mutex);
- _mesa_hash_table_remove_key(serials_hash, p);
- mtx_unlock(&serials_mutex);
-}
-
-
-#if defined(PIPE_OS_WINDOWS)
-#define STACK_LEN 60
-#else
-#define STACK_LEN 64
-#endif
-
-/**
- * Log a reference count change to the log file (if enabled).
- * This is called via the pipe_reference() and debug_reference() functions,
- * basically whenever a reference count is initialized or changed.
- *
- * \param p the refcount being changed (the value is not changed here)
- * \param get_desc a function which will be called to print an object's
- * name/pointer into a string buffer during logging
- * \param change the reference count change which must be +/-1 or 0 when
- * creating the object and initializing the refcount.
- */
-void
-debug_reference_slowpath(const struct pipe_reference *p,
- debug_reference_descriptor get_desc, int change)
-{
- assert(change >= -1);
- assert(change <= 1);
-
- if (debug_refcnt_state < 0)
- return;
-
- if (!debug_refcnt_state) {
- const char *filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL);
- if (filename && filename[0])
- stream = fopen(filename, "wt");
-
- if (stream)
- debug_refcnt_state = 1;
- else
- debug_refcnt_state = -1;
- }
-
- if (debug_refcnt_state > 0) {
- struct debug_stack_frame frames[STACK_LEN];
- char buf[1024];
- unsigned i;
- unsigned refcnt = p->count;
- unsigned serial;
- boolean existing = debug_serial((void *) p, &serial);
-
- debug_backtrace_capture(frames, 1, STACK_LEN);
-
- get_desc(buf, p);
-
- if (!existing) {
- fprintf(stream, "<%s> %p %u Create\n", buf, (void *) p, serial);
- debug_backtrace_print(stream, frames, STACK_LEN);
-
- /* this is here to provide a gradual change even if we don't see
- * the initialization
- */
- for (i = 1; i <= refcnt - change; ++i) {
- fprintf(stream, "<%s> %p %u AddRef %u\n", buf, (void *) p,
- serial, i);
- debug_backtrace_print(stream, frames, STACK_LEN);
- }
- }
-
- if (change) {
- fprintf(stream, "<%s> %p %u %s %u\n", buf, (void *) p, serial,
- change > 0 ? "AddRef" : "Release", refcnt);
- debug_backtrace_print(stream, frames, STACK_LEN);
- }
-
- if (!refcnt) {
- debug_serial_delete((void *) p);
- fprintf(stream, "<%s> %p %u Destroy\n", buf, (void *) p, serial);
- debug_backtrace_print(stream, frames, STACK_LEN);
- }
-
- fflush(stream);
- }
-}
-
-#endif /* DEBUG */
diff --git a/lib/mesa/src/util/u_debug_refcnt.h b/lib/mesa/src/util/u_debug_refcnt.h
deleted file mode 100644
index 78f690b02..000000000
--- a/lib/mesa/src/util/u_debug_refcnt.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Luca Barbieri
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef U_DEBUG_REFCNT_H_
-#define U_DEBUG_REFCNT_H_
-
-#include "pipe/p_config.h"
-#include "pipe/p_state.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*debug_reference_descriptor)(char*, const struct pipe_reference*);
-
-#if defined(DEBUG)
-
-extern int debug_refcnt_state;
-
-void
-debug_reference_slowpath(const struct pipe_reference* p,
- debug_reference_descriptor get_desc, int change);
-
-static inline void
-debug_reference(const struct pipe_reference* p,
- debug_reference_descriptor get_desc, int change)
-{
- if (debug_refcnt_state >= 0)
- debug_reference_slowpath(p, get_desc, change);
-}
-
-#else
-
-static inline void
-debug_reference(UNUSED const struct pipe_reference* p,
- UNUSED debug_reference_descriptor get_desc, UNUSED int change)
-{
-}
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* U_DEBUG_REFCNT_H_ */
diff --git a/lib/mesa/src/util/u_dynarray.h b/lib/mesa/src/util/u_dynarray.h
index 769669e1e..b8fff5b8a 100644
--- a/lib/mesa/src/util/u_dynarray.h
+++ b/lib/mesa/src/util/u_dynarray.h
@@ -36,7 +36,7 @@
extern "C" {
#endif
-static unsigned util_dynarray_is_data_stack_allocated;
+extern unsigned util_dynarray_is_data_stack_allocated;
/* A zero-initialized version of this is guaranteed to represent an
* empty array.
diff --git a/lib/mesa/src/util/u_queue.c b/lib/mesa/src/util/u_queue.c
index ed1e96b10..750dd2015 100644
--- a/lib/mesa/src/util/u_queue.c
+++ b/lib/mesa/src/util/u_queue.c
@@ -442,9 +442,10 @@ util_queue_init(struct util_queue *queue,
snprintf(queue->name, sizeof(queue->name), "%s", name);
}
+ queue->create_threads_on_demand = true;
queue->flags = flags;
queue->max_threads = num_threads;
- queue->num_threads = (flags & UTIL_QUEUE_INIT_SCALE_THREADS) ? 1 : num_threads;
+ queue->num_threads = 1;
queue->max_jobs = max_jobs;
queue->global_data = global_data;
@@ -582,7 +583,7 @@ util_queue_add_job_locked(struct util_queue *queue,
/* Scale the number of threads up if there's already one job waiting. */
if (queue->num_queued > 0 &&
- queue->flags & UTIL_QUEUE_INIT_SCALE_THREADS &&
+ queue->create_threads_on_demand &&
execute != util_queue_finish_execute &&
queue->num_threads < queue->max_threads) {
util_queue_adjust_num_threads(queue, queue->num_threads + 1, true);
@@ -719,8 +720,7 @@ util_queue_finish(struct util_queue *queue)
* Also note that util_queue_add_job can unlock the mutex if there is not
* enough space in the queue and wait for space.
*/
- unsigned saved_flags = queue->flags;
- queue->flags &= ~UTIL_QUEUE_INIT_SCALE_THREADS;
+ queue->create_threads_on_demand = false;
fences = malloc(queue->num_threads * sizeof(*fences));
util_barrier_init(&barrier, queue->num_threads);
@@ -730,7 +730,7 @@ util_queue_finish(struct util_queue *queue)
util_queue_add_job_locked(queue, &barrier, &fences[i],
util_queue_finish_execute, NULL, 0, true);
}
- queue->flags = saved_flags;
+ queue->create_threads_on_demand = true;
mtx_unlock(&queue->lock);
for (unsigned i = 0; i < queue->num_threads; ++i) {
diff --git a/lib/mesa/src/util/u_queue.h b/lib/mesa/src/util/u_queue.h
index 25f2c1589..ae7516c03 100644
--- a/lib/mesa/src/util/u_queue.h
+++ b/lib/mesa/src/util/u_queue.h
@@ -50,7 +50,6 @@ extern "C" {
#define UTIL_QUEUE_INIT_USE_MINIMUM_PRIORITY (1 << 0)
#define UTIL_QUEUE_INIT_RESIZE_IF_FULL (1 << 1)
#define UTIL_QUEUE_INIT_SET_FULL_THREAD_AFFINITY (1 << 2)
-#define UTIL_QUEUE_INIT_SCALE_THREADS (1 << 3)
#if UTIL_FUTEX_SUPPORTED
#define UTIL_QUEUE_FENCE_FUTEX
@@ -206,6 +205,7 @@ struct util_queue_job {
struct util_queue {
char name[14]; /* 13 characters = the thread name without the index */
mtx_t lock;
+ bool create_threads_on_demand;
cnd_t has_queued_cond;
cnd_t has_space_cond;
thrd_t *threads;
diff --git a/lib/mesa/src/util/u_string.h b/lib/mesa/src/util/u_string.h
index 8fead06b6..b9142d761 100644
--- a/lib/mesa/src/util/u_string.h
+++ b/lib/mesa/src/util/u_string.h
@@ -35,12 +35,10 @@
#ifndef U_STRING_H_
#define U_STRING_H_
-#if !defined(XF86_LIBC_H)
-#include <stdio.h>
-#endif
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
+#include <stdio.h>
#include <string.h>
#include <limits.h>
@@ -102,6 +100,7 @@ util_vasprintf(char **ret, const char *format, va_list ap)
#define asprintf util_asprintf
static inline int
+ PRINTFLIKE(2, 3)
util_asprintf(char **str, const char *fmt, ...)
{
int ret;
@@ -118,11 +117,11 @@ util_asprintf(char **str, const char *fmt, ...)
#define strdup _strdup
-#if defined(_WIN32) && !defined(HAVE_STRTOK_R)
+#if !defined(HAVE_STRTOK_R)
#define strtok_r strtok_s
#endif
-#endif
+#endif /* _WIN32 */
#ifdef __cplusplus
diff --git a/lib/mesa/src/util/u_vector.c b/lib/mesa/src/util/u_vector.c
index 3c5593da7..cd23b963e 100644
--- a/lib/mesa/src/util/u_vector.c
+++ b/lib/mesa/src/util/u_vector.c
@@ -78,7 +78,7 @@ u_vector_add(struct u_vector *vector)
* piece goes to the right locations. Thanks to the change in
* size, it may or may not still wrap around.
*/
- split = u_align_u32(vector->tail, vector->size);
+ split = align(vector->tail, vector->size);
assert(vector->tail <= split && split < vector->head);
memcpy((char *)data + dst_tail, (char *)vector->data + src_tail,
split - vector->tail);
diff --git a/lib/mesa/src/util/u_vector.h b/lib/mesa/src/util/u_vector.h
index 5a1a08934..50e706e32 100644
--- a/lib/mesa/src/util/u_vector.h
+++ b/lib/mesa/src/util/u_vector.h
@@ -38,14 +38,6 @@
extern "C" {
#endif
-/* TODO - move to u_math.h - name it better etc */
-static inline uint32_t
-u_align_u32(uint32_t v, uint32_t a)
-{
- assert(a != 0 && a == (a & -((int32_t) a)));
- return (v + a - 1) & ~(a - 1);
-}
-
struct u_vector {
uint32_t head;
uint32_t tail;
diff --git a/lib/mesa/src/util/xmlconfig.c b/lib/mesa/src/util/xmlconfig.c
index 62b163be2..7a753e37e 100644
--- a/lib/mesa/src/util/xmlconfig.c
+++ b/lib/mesa/src/util/xmlconfig.c
@@ -1173,16 +1173,9 @@ initOptionCache(driOptionCache *cache, const driOptionCache *info)
#define DATADIR "/usr/share"
#endif
-static const char *datadir = DATADIR "/drirc.d";
static const char *execname;
void
-driInjectDataDir(const char *dir)
-{
- datadir = dir;
-}
-
-void
driInjectExecName(const char *exec)
{
execname = exec;
@@ -1216,10 +1209,15 @@ driParseConfigFiles(driOptionCache *cache, const driOptionCache *info,
userData.execName = execname;
#if WITH_XMLCONFIG
- char *home;
-
- parseConfigDir(&userData, datadir);
- parseOneConfigFile(&userData, SYSCONFDIR "/drirc");
+ char *home, *configdir;
+
+ /* parse from either $DRIRC_CONFIGDIR or $datadir/drirc.d */
+ if ((configdir = getenv("DRIRC_CONFIGDIR")))
+ parseConfigDir(&userData, configdir);
+ else {
+ parseConfigDir(&userData, DATADIR "/drirc.d");
+ parseOneConfigFile(&userData, SYSCONFDIR "/drirc");
+ }
if ((home = getenv("HOME"))) {
char filename[PATH_MAX];
diff --git a/lib/mesa/src/util/xmlconfig.h b/lib/mesa/src/util/xmlconfig.h
index 7405f0cb9..8d063974c 100644
--- a/lib/mesa/src/util/xmlconfig.h
+++ b/lib/mesa/src/util/xmlconfig.h
@@ -159,7 +159,6 @@ float driQueryOptionf(const driOptionCache *cache, const char *name);
char *driQueryOptionstr(const driOptionCache *cache, const char *name);
/* Overrides for the unit tests to control drirc parsing. */
-void driInjectDataDir(const char *dir);
void driInjectExecName(const char *exec);
/**