OSDN Git Service

freedreno/msm: use hashtable to track bo idx
authorRob Clark <robclark@freedesktop.org>
Tue, 28 Jun 2016 17:33:07 +0000 (13:33 -0400)
committerRob Clark <robclark@freedesktop.org>
Wed, 20 Jul 2016 23:42:21 +0000 (19:42 -0400)
Note: cache the last ring the bo was emitted on, to avoid excess
hashtable lookups.  We do this by tracking ring seqno to avoid
problems with dangling pointers.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
freedreno/msm/msm_priv.h
freedreno/msm/msm_ringbuffer.c

index 1f44398..6d670aa 100644 (file)
@@ -40,6 +40,7 @@
 struct msm_device {
        struct fd_device base;
        struct fd_bo_cache ring_cache;
+       unsigned ring_cnt;
 };
 
 static inline struct msm_device * to_msm_device(struct fd_device *x)
@@ -72,18 +73,11 @@ struct msm_bo {
        struct fd_bo base;
        uint64_t offset;
        uint64_t presumed;
-       /* in the common case, a bo won't be referenced by more than a single
-        * (parent) ring[*].  So to avoid looping over all the bo's in the
-        * reloc table to find the idx of a bo that might already be in the
-        * table, we cache the idx in the bo.  But in order to detect the
-        * slow-path where bo is ref'd in multiple rb's, we also must track
-        * the current_ring for which the idx is valid.  See bo2idx().
-        *
-        * [*] in case multiple ringbuffers, ie. one toplevel and other rb(s)
-        *     used for IB target(s), the toplevel rb is the parent which is
-        *     tracking bo's for the submit
+       /* to avoid excess hashtable lookups, cache the ring this bo was
+        * last emitted on (since that will probably also be the next ring
+        * it is emitted on)
         */
-       struct fd_ringbuffer *current_ring;
+       unsigned current_ring_seqno;
        uint32_t idx;
 };
 
index 86fc83e..fbfaefa 100644 (file)
@@ -92,6 +92,11 @@ struct msm_ringbuffer {
 
        int is_growable;
        unsigned cmd_count;
+
+       unsigned seqno;
+
+       /* maps fd_bo to idx: */
+       void *bo_table;
 };
 
 static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x)
@@ -217,21 +222,24 @@ static uint32_t bo2idx(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t fl
        struct msm_bo *msm_bo = to_msm_bo(bo);
        uint32_t idx;
        pthread_mutex_lock(&idx_lock);
-       if (!msm_bo->current_ring) {
-               idx = append_bo(ring, bo);
-               msm_bo->current_ring = ring;
-               msm_bo->idx = idx;
-       } else if (msm_bo->current_ring == ring) {
+       if (msm_bo->current_ring_seqno == msm_ring->seqno) {
                idx = msm_bo->idx;
        } else {
-               /* slow-path: */
-               for (idx = 0; idx < msm_ring->nr_bos; idx++)
-                       if (msm_ring->bos[idx] == bo)
-                               break;
-               if (idx == msm_ring->nr_bos) {
-                       /* not found */
+               void *val;
+
+               if (!msm_ring->bo_table)
+                       msm_ring->bo_table = drmHashCreate();
+
+               if (!drmHashLookup(msm_ring->bo_table, bo->handle, &val)) {
+                       /* found */
+                       idx = (uint32_t)val;
+               } else {
                        idx = append_bo(ring, bo);
+                       val = (void *)idx;
+                       drmHashInsert(msm_ring->bo_table, bo->handle, val);
                }
+               msm_bo->current_ring_seqno = msm_ring->seqno;
+               msm_bo->idx = idx;
        }
        pthread_mutex_unlock(&idx_lock);
        if (flags & FD_RELOC_READ)
@@ -318,7 +326,7 @@ static void flush_reset(struct fd_ringbuffer *ring)
 
        for (i = 0; i < msm_ring->nr_bos; i++) {
                struct msm_bo *msm_bo = to_msm_bo(msm_ring->bos[i]);
-               msm_bo->current_ring = NULL;
+               msm_bo->current_ring_seqno = 0;
                fd_bo_del(&msm_bo->base);
        }
 
@@ -333,6 +341,11 @@ static void flush_reset(struct fd_ringbuffer *ring)
        msm_ring->nr_cmds = 0;
        msm_ring->nr_bos = 0;
 
+       if (msm_ring->bo_table) {
+               drmHashDestroy(msm_ring->bo_table);
+               msm_ring->bo_table = NULL;
+       }
+
        if (msm_ring->is_growable) {
                delete_cmds(msm_ring);
        } else {
@@ -551,6 +564,7 @@ drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe,
        }
 
        list_inithead(&msm_ring->cmd_list);
+       msm_ring->seqno = ++to_msm_device(pipe->dev)->ring_cnt;
 
        ring = &msm_ring->base;
        ring->funcs = &funcs;