Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / gallium / auxiliary / pipebuffer / pb_cache.c
index ebd06b0e030048bc4b8bb67fb2510fa0eb6af829..ec878202f0825b266e1d862819404a1e31439c80 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "pb_cache.h"
 #include "util/u_memory.h"
-#include "util/u_time.h"
+#include "util/os_time.h"
 
 
 /**
@@ -38,35 +38,34 @@ static void
 destroy_buffer_locked(struct pb_cache_entry *entry)
 {
    struct pb_cache *mgr = entry->mgr;
+   struct pb_buffer *buf = entry->buffer;
 
-   assert(!pipe_is_referenced(&entry->buffer->reference));
+   assert(!pipe_is_referenced(&buf->reference));
    if (entry->head.next) {
-      LIST_DEL(&entry->head);
+      list_del(&entry->head);
       assert(mgr->num_buffers);
       --mgr->num_buffers;
-      mgr->cache_size -= entry->buffer->size;
+      mgr->cache_size -= buf->size;
    }
-   entry->mgr->destroy_buffer(entry->buffer);
+   mgr->destroy_buffer(buf);
 }
 
 /**
  * Free as many cache buffers from the list head as possible.
  */
 static void
-release_expired_buffers_locked(struct pb_cache *mgr)
+release_expired_buffers_locked(struct list_head *cache,
+                               int64_t current_time)
 {
    struct list_head *curr, *next;
    struct pb_cache_entry *entry;
-   int64_t now;
 
-   now = os_time_get();
-
-   curr = mgr->cache.next;
+   curr = cache->next;
    next = curr->next;
-   while (curr != &mgr->cache) {
+   while (curr != cache) {
       entry = LIST_ENTRY(struct pb_cache_entry, curr, head);
 
-      if (!os_time_timeout(entry->start, entry->end, now))
+      if (!os_time_timeout(entry->start, entry->end, current_time))
          break;
 
       destroy_buffer_locked(entry);
@@ -84,25 +83,31 @@ void
 pb_cache_add_buffer(struct pb_cache_entry *entry)
 {
    struct pb_cache *mgr = entry->mgr;
+   struct list_head *cache = &mgr->buckets[entry->bucket_index];
+   struct pb_buffer *buf = entry->buffer;
+   unsigned i;
 
-   pipe_mutex_lock(mgr->mutex);
-   assert(!pipe_is_referenced(&entry->buffer->reference));
+   mtx_lock(&mgr->mutex);
+   assert(!pipe_is_referenced(&buf->reference));
 
-   release_expired_buffers_locked(mgr);
+   int64_t current_time = os_time_get();
+
+   for (i = 0; i < mgr->num_heaps; i++)
+      release_expired_buffers_locked(&mgr->buckets[i], current_time);
 
    /* Directly release any buffer that exceeds the limit. */
-   if (mgr->cache_size + entry->buffer->size > mgr->max_cache_size) {
-      entry->mgr->destroy_buffer(entry->buffer);
-      pipe_mutex_unlock(mgr->mutex);
+   if (mgr->cache_size + buf->size > mgr->max_cache_size) {
+      mgr->destroy_buffer(buf);
+      mtx_unlock(&mgr->mutex);
       return;
    }
 
    entry->start = os_time_get();
    entry->end = entry->start + mgr->usecs;
-   LIST_ADDTAIL(&entry->head, &mgr->cache);
+   list_addtail(&entry->head, cache);
    ++mgr->num_buffers;
-   mgr->cache_size += entry->buffer->size;
-   pipe_mutex_unlock(mgr->mutex);
+   mgr->cache_size += buf->size;
+   mtx_unlock(&mgr->mutex);
 }
 
 /**
@@ -114,25 +119,24 @@ static int
 pb_cache_is_buffer_compat(struct pb_cache_entry *entry,
                           pb_size size, unsigned alignment, unsigned usage)
 {
+   struct pb_cache *mgr = entry->mgr;
    struct pb_buffer *buf = entry->buffer;
 
-   if (usage & entry->mgr->bypass_usage)
-      return 0;
-
-   if (buf->size < size)
+   if (!pb_check_usage(usage, buf->usage))
       return 0;
 
    /* be lenient with size */
-   if (buf->size > (unsigned) (entry->mgr->size_factor * size))
+   if (buf->size < size ||
+       buf->size > (unsigned) (mgr->size_factor * size))
       return 0;
 
-   if (!pb_check_alignment(alignment, buf->alignment))
+   if (usage & mgr->bypass_usage)
       return 0;
 
-   if (!pb_check_usage(usage, buf->usage))
+   if (!pb_check_alignment(alignment, buf->alignment))
       return 0;
 
-   return entry->mgr->can_reclaim(buf) ? 1 : -1;
+   return mgr->can_reclaim(buf) ? 1 : -1;
 }
 
 /**
@@ -141,7 +145,8 @@ pb_cache_is_buffer_compat(struct pb_cache_entry *entry,
  */
 struct pb_buffer *
 pb_cache_reclaim_buffer(struct pb_cache *mgr, pb_size size,
-                        unsigned alignment, unsigned usage)
+                        unsigned alignment, unsigned usage,
+                        unsigned bucket_index)
 {
    struct pb_cache_entry *entry;
    struct pb_cache_entry *cur_entry;
@@ -149,19 +154,22 @@ pb_cache_reclaim_buffer(struct pb_cache *mgr, pb_size size,
    int64_t now;
    int ret = 0;
 
-   pipe_mutex_lock(mgr->mutex);
+   assert(bucket_index < mgr->num_heaps);
+   struct list_head *cache = &mgr->buckets[bucket_index];
+
+   mtx_lock(&mgr->mutex);
 
    entry = NULL;
-   cur = mgr->cache.next;
+   cur = cache->next;
    next = cur->next;
 
    /* search in the expired buffers, freeing them in the process */
    now = os_time_get();
-   while (cur != &mgr->cache) {
+   while (cur != cache) {
       cur_entry = LIST_ENTRY(struct pb_cache_entry, cur, head);
 
       if (!entry && (ret = pb_cache_is_buffer_compat(cur_entry, size,
-                                                     alignment, usage) > 0))
+                                                     alignment, usage)) > 0)
          entry = cur_entry;
       else if (os_time_timeout(cur_entry->start, cur_entry->end, now))
          destroy_buffer_locked(cur_entry);
@@ -179,7 +187,7 @@ pb_cache_reclaim_buffer(struct pb_cache *mgr, pb_size size,
 
    /* keep searching in the hot buffers */
    if (!entry && ret != -1) {
-      while (cur != &mgr->cache) {
+      while (cur != cache) {
          cur_entry = LIST_ENTRY(struct pb_cache_entry, cur, head);
          ret = pb_cache_is_buffer_compat(cur_entry, size, alignment, usage);
 
@@ -200,15 +208,15 @@ pb_cache_reclaim_buffer(struct pb_cache *mgr, pb_size size,
       struct pb_buffer *buf = entry->buffer;
 
       mgr->cache_size -= buf->size;
-      LIST_DEL(&entry->head);
+      list_del(&entry->head);
       --mgr->num_buffers;
-      pipe_mutex_unlock(mgr->mutex);
+      mtx_unlock(&mgr->mutex);
       /* Increase refcount */
       pipe_reference_init(&buf->reference, 1);
       return buf;
    }
 
-   pipe_mutex_unlock(mgr->mutex);
+   mtx_unlock(&mgr->mutex);
    return NULL;
 }
 
@@ -220,32 +228,43 @@ pb_cache_release_all_buffers(struct pb_cache *mgr)
 {
    struct list_head *curr, *next;
    struct pb_cache_entry *buf;
+   unsigned i;
 
-   pipe_mutex_lock(mgr->mutex);
-   curr = mgr->cache.next;
-   next = curr->next;
-   while (curr != &mgr->cache) {
-      buf = LIST_ENTRY(struct pb_cache_entry, curr, head);
-      destroy_buffer_locked(buf);
-      curr = next;
+   mtx_lock(&mgr->mutex);
+   for (i = 0; i < mgr->num_heaps; i++) {
+      struct list_head *cache = &mgr->buckets[i];
+
+      curr = cache->next;
       next = curr->next;
+      while (curr != cache) {
+         buf = LIST_ENTRY(struct pb_cache_entry, curr, head);
+         destroy_buffer_locked(buf);
+         curr = next;
+         next = curr->next;
+      }
    }
-   pipe_mutex_unlock(mgr->mutex);
+   mtx_unlock(&mgr->mutex);
 }
 
 void
 pb_cache_init_entry(struct pb_cache *mgr, struct pb_cache_entry *entry,
-                    struct pb_buffer *buf)
+                    struct pb_buffer *buf, unsigned bucket_index)
 {
+   assert(bucket_index < mgr->num_heaps);
+
    memset(entry, 0, sizeof(*entry));
    entry->buffer = buf;
    entry->mgr = mgr;
+   entry->bucket_index = bucket_index;
 }
 
 /**
  * Initialize a caching buffer manager.
  *
  * @param mgr     The cache buffer manager
+ * @param num_heaps  Number of separate caches/buckets indexed by bucket_index
+ *                   for faster buffer matching (alternative to slower
+ *                   "usage"-based matching).
  * @param usecs   Unused buffers may be released from the cache after this
  *                time
  * @param size_factor  Declare buffers that are size_factor times bigger than
@@ -258,15 +277,25 @@ pb_cache_init_entry(struct pb_cache *mgr, struct pb_cache_entry *entry,
  * @param can_reclaim     Whether a buffer can be reclaimed (e.g. is not busy)
  */
 void
-pb_cache_init(struct pb_cache *mgr, uint usecs, float size_factor,
+pb_cache_init(struct pb_cache *mgr, uint num_heaps,
+              uint usecs, float size_factor,
               unsigned bypass_usage, uint64_t maximum_cache_size,
               void (*destroy_buffer)(struct pb_buffer *buf),
               bool (*can_reclaim)(struct pb_buffer *buf))
 {
-   LIST_INITHEAD(&mgr->cache);
-   pipe_mutex_init(mgr->mutex);
+   unsigned i;
+
+   mgr->buckets = CALLOC(num_heaps, sizeof(struct list_head));
+   if (!mgr->buckets)
+      return;
+
+   for (i = 0; i < num_heaps; i++)
+      list_inithead(&mgr->buckets[i]);
+
+   (void) mtx_init(&mgr->mutex, mtx_plain);
    mgr->cache_size = 0;
    mgr->max_cache_size = maximum_cache_size;
+   mgr->num_heaps = num_heaps;
    mgr->usecs = usecs;
    mgr->num_buffers = 0;
    mgr->bypass_usage = bypass_usage;
@@ -282,5 +311,7 @@ void
 pb_cache_deinit(struct pb_cache *mgr)
 {
    pb_cache_release_all_buffers(mgr);
-   pipe_mutex_destroy(mgr->mutex);
+   mtx_destroy(&mgr->mutex);
+   FREE(mgr->buckets);
+   mgr->buckets = NULL;
 }