1fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca/**************************************************************************
2fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca *
3fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * All Rights Reserved.
5fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca *
6fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * Permission is hereby granted, free of charge, to any person obtaining a
7fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * copy of this software and associated documentation files (the
8fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * "Software"), to deal in the Software without restriction, including
9fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * without limitation the rights to use, copy, modify, merge, publish,
10fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * distribute, sub license, and/or sell copies of the Software, and to
11fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * permit persons to whom the Software is furnished to do so, subject to
12fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * the following conditions:
13fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca *
14fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * The above copyright notice and this permission notice (including the
15fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * next paragraph) shall be included in all copies or substantial portions
16fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * of the Software.
17fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca *
18fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca *
26fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca **************************************************************************/
27fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
28fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca/**
29fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * \file
30fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * Buffer cache.
31fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca *
32e06474dbae6979177629fb6187331291ff230c65José Fonseca * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com>
33fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
34fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca */
35fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
36fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
37fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca#include "pipe/p_compiler.h"
38ea4bf267e4b023b08043f91ac44592fed1736e7fJosé Fonseca#include "util/u_debug.h"
392aaca1df9df6980ec88180c8866c8987b31db91aJosé Fonseca#include "os/os_thread.h"
404f25420bdd834e81a3e22733304efc5261c2998aBrian Paul#include "util/u_memory.h"
41fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca#include "util/u_double_list.h"
42fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca#include "util/u_time.h"
43fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
44fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca#include "pb_buffer.h"
45fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca#include "pb_bufmgr.h"
46fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
47fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
48fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca/**
49fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * Convenience macro (type safe).
50fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca */
51fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca#define SUPER(__derived) (&(__derived)->base)
52fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
53fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
54fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastruct pb_cache_manager;
55fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
56fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
57fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca/**
58fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * Wrapper around a pipe buffer which adds delayed destruction.
59fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca */
60fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastruct pb_cache_buffer
61fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
62fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_buffer base;
63fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
64fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_buffer *buffer;
65fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_manager *mgr;
66fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
67fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   /** Caching time interval */
68bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul   int64_t start, end;
69fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
70fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct list_head head;
71fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca};
72fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
73fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
74fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastruct pb_cache_manager
75fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
76fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_manager base;
77fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
78fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_manager *provider;
79fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   unsigned usecs;
80fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
810bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex mutex;
82fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
83fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct list_head delayed;
842af0173e9e4eefe910c6011038e7346091a9b2a4José Fonseca   pb_size numDelayed;
85fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca};
86fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
87fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
88fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic INLINE struct pb_cache_buffer *
89fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_buffer(struct pb_buffer *buf)
90fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
91fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   assert(buf);
92fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   return (struct pb_cache_buffer *)buf;
93fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
94fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
95fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
96fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic INLINE struct pb_cache_manager *
97fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_manager(struct pb_manager *mgr)
98fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
99fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   assert(mgr);
100fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   return (struct pb_cache_manager *)mgr;
101fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
102fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
103fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
104fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca/**
105fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * Actually destroy the buffer.
106fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca */
107fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic INLINE void
108fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca_pb_cache_buffer_destroy(struct pb_cache_buffer *buf)
109fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
110fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_manager *mgr = buf->mgr;
111fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
112fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   LIST_DEL(&buf->head);
113fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   assert(mgr->numDelayed);
114fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   --mgr->numDelayed;
1154682e706012fe26627a2f827db01b5068cc62814Marek Olšák   assert(!pipe_is_referenced(&buf->base.reference));
116fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   pb_reference(&buf->buffer, NULL);
117fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   FREE(buf);
118fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
119fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
120fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
121fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca/**
122fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca * Free as many cache buffers from the list head as possible.
123fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca */
124fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic void
125fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca_pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr)
126fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
127fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct list_head *curr, *next;
128fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_buffer *buf;
129bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul   int64_t now;
130fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
131bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul   now = os_time_get();
132fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
133fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   curr = mgr->delayed.next;
134fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   next = curr->next;
135fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   while(curr != &mgr->delayed) {
136fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
137fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
138bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul      if(!os_time_timeout(buf->start, buf->end, now))
139fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca	 break;
140fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
141fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      _pb_cache_buffer_destroy(buf);
142fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
143fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      curr = next;
144fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      next = curr->next;
145fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   }
146fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
147fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
148fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
149fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic void
150fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_buffer_destroy(struct pb_buffer *_buf)
151fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
152fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
153fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_manager *mgr = buf->mgr;
154fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
1550bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex_lock(mgr->mutex);
1564682e706012fe26627a2f827db01b5068cc62814Marek Olšák   assert(!pipe_is_referenced(&buf->base.reference));
157fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
158fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   _pb_cache_buffer_list_check_free(mgr);
159fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
160bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul   buf->start = os_time_get();
161bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul   buf->end = buf->start + mgr->usecs;
162fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   LIST_ADDTAIL(&buf->head, &mgr->delayed);
163fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   ++mgr->numDelayed;
1640bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex_unlock(mgr->mutex);
165fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
166fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
167fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
168fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic void *
169fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_buffer_map(struct pb_buffer *_buf,
170b5fcf0c8e07e666523b007fab1d0fc18c2c89241Dave Airlie		    unsigned flags, void *flush_ctx)
171fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
172fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
173b5fcf0c8e07e666523b007fab1d0fc18c2c89241Dave Airlie   return pb_map(buf->buffer, flags, flush_ctx);
174fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
175fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
176fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
177fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic void
178fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_buffer_unmap(struct pb_buffer *_buf)
179fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
180fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
181fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   pb_unmap(buf->buffer);
182fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
183fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
184fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
185e06474dbae6979177629fb6187331291ff230c65José Fonsecastatic enum pipe_error
186e06474dbae6979177629fb6187331291ff230c65José Fonsecapb_cache_buffer_validate(struct pb_buffer *_buf,
187e06474dbae6979177629fb6187331291ff230c65José Fonseca                         struct pb_validate *vl,
188e06474dbae6979177629fb6187331291ff230c65José Fonseca                         unsigned flags)
189e06474dbae6979177629fb6187331291ff230c65José Fonseca{
190e06474dbae6979177629fb6187331291ff230c65José Fonseca   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
191e06474dbae6979177629fb6187331291ff230c65José Fonseca   return pb_validate(buf->buffer, vl, flags);
192e06474dbae6979177629fb6187331291ff230c65José Fonseca}
193e06474dbae6979177629fb6187331291ff230c65José Fonseca
194e06474dbae6979177629fb6187331291ff230c65José Fonseca
195e06474dbae6979177629fb6187331291ff230c65José Fonsecastatic void
196e06474dbae6979177629fb6187331291ff230c65José Fonsecapb_cache_buffer_fence(struct pb_buffer *_buf,
197e06474dbae6979177629fb6187331291ff230c65José Fonseca                      struct pipe_fence_handle *fence)
198e06474dbae6979177629fb6187331291ff230c65José Fonseca{
199e06474dbae6979177629fb6187331291ff230c65José Fonseca   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
200e06474dbae6979177629fb6187331291ff230c65José Fonseca   pb_fence(buf->buffer, fence);
201e06474dbae6979177629fb6187331291ff230c65José Fonseca}
202e06474dbae6979177629fb6187331291ff230c65José Fonseca
203e06474dbae6979177629fb6187331291ff230c65José Fonseca
204fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic void
205fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_buffer_get_base_buffer(struct pb_buffer *_buf,
206fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca                              struct pb_buffer **base_buf,
2072af0173e9e4eefe910c6011038e7346091a9b2a4José Fonseca                              pb_size *offset)
208fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
209fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
210fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   pb_get_base_buffer(buf->buffer, base_buf, offset);
211fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
212fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
213fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
214fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecaconst struct pb_vtbl
215fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_buffer_vtbl = {
216fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      pb_cache_buffer_destroy,
217fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      pb_cache_buffer_map,
218fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      pb_cache_buffer_unmap,
219e06474dbae6979177629fb6187331291ff230c65José Fonseca      pb_cache_buffer_validate,
220e06474dbae6979177629fb6187331291ff230c65José Fonseca      pb_cache_buffer_fence,
221fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      pb_cache_buffer_get_base_buffer
222fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca};
223fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
224fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
22549866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airliestatic INLINE int
22695aeeb6d746e57473116ef4d72c05330902f68a5José Fonsecapb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
2272af0173e9e4eefe910c6011038e7346091a9b2a4José Fonseca                          pb_size size,
22895aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca                          const struct pb_desc *desc)
22995aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca{
2304682e706012fe26627a2f827db01b5068cc62814Marek Olšák   if(buf->base.size < size)
23149866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie      return 0;
2324b52f4df1b37918a363d05e0b3db22125e801367José Fonseca
2334b52f4df1b37918a363d05e0b3db22125e801367José Fonseca   /* be lenient with size */
2344682e706012fe26627a2f827db01b5068cc62814Marek Olšák   if(buf->base.size >= 2*size)
23549866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie      return 0;
23695aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
2374682e706012fe26627a2f827db01b5068cc62814Marek Olšák   if(!pb_check_alignment(desc->alignment, buf->base.alignment))
23849866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie      return 0;
23995aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
2404682e706012fe26627a2f827db01b5068cc62814Marek Olšák   if(!pb_check_usage(desc->usage, buf->base.usage))
24149866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie      return 0;
2420dab3189e1d100a9a2487f7aff45589b423c386cDave Airlie
24349579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák   if (buf->mgr->provider->is_buffer_busy) {
24449579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák      if (buf->mgr->provider->is_buffer_busy(buf->mgr->provider, buf->buffer))
24549579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák         return -1;
24649579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák   } else {
24749579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák      void *ptr = pb_map(buf->buffer, PB_USAGE_DONTBLOCK, NULL);
24849579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák
24949579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák      if (!ptr)
25049579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák         return -1;
25149579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák
25249579a4df8f9f85139a02c95ae59ea0a5dec663cMarek Olšák      pb_unmap(buf->buffer);
2530dab3189e1d100a9a2487f7aff45589b423c386cDave Airlie   }
2540dab3189e1d100a9a2487f7aff45589b423c386cDave Airlie
25549866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie   return 1;
25695aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca}
25795aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
25895aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
259fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastatic struct pb_buffer *
260fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_manager_create_buffer(struct pb_manager *_mgr,
2612af0173e9e4eefe910c6011038e7346091a9b2a4José Fonseca                               pb_size size,
262fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca                               const struct pb_desc *desc)
263fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
264fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
265fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_buffer *buf;
26695aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca   struct pb_cache_buffer *curr_buf;
267fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct list_head *curr, *next;
268bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul   int64_t now;
26949866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie   int ret = 0;
27049866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie
2710bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex_lock(mgr->mutex);
27295aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
27395aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca   buf = NULL;
274fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   curr = mgr->delayed.next;
275fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   next = curr->next;
27695aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
27795aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca   /* search in the expired buffers, freeing them in the process */
278bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul   now = os_time_get();
279fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   while(curr != &mgr->delayed) {
28095aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca      curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
28149866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie      if(!buf && (ret = pb_cache_is_buffer_compat(curr_buf, size, desc) > 0))
28249866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie         buf = curr_buf;
283bcace317c7ff2c774784b24b51b2de5d9cc871a0Brian Paul      else if(os_time_timeout(curr_buf->start, curr_buf->end, now))
28449866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie         _pb_cache_buffer_destroy(curr_buf);
285038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca      else
286038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca         /* This buffer (and all hereafter) are still hot in cache */
287038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca         break;
28849866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie      if (ret == -1)
28949866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie         break;
29095aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca      curr = next;
29195aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca      next = curr->next;
29295aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca   }
293fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
29495aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca   /* keep searching in the hot buffers */
29549866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie   if(!buf && ret != -1) {
296038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca      while(curr != &mgr->delayed) {
297038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca         curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
29849866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie         ret = pb_cache_is_buffer_compat(curr_buf, size, desc);
29949866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie         if (ret > 0) {
300038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca            buf = curr_buf;
301038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca            break;
302038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca         }
30349866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie         if (ret == -1)
30449866c8f34579420a30c33f76cfb2d77bafcdf0aDave Airlie            break;
305038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca         /* no need to check the timeout here */
306038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca         curr = next;
307038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca         next = curr->next;
308038d53cbdb9e504388141c25859bce12f7e8f87eJosé Fonseca      }
309fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   }
31095aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
31195aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca   if(buf) {
31295aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca      LIST_DEL(&buf->head);
313bf21b7006c63c3dc47045c22d4f372dfe6c7ce67Dave Airlie      --mgr->numDelayed;
3140bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul      pipe_mutex_unlock(mgr->mutex);
3155e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer      /* Increase refcount */
3164682e706012fe26627a2f827db01b5068cc62814Marek Olšák      pipe_reference_init(&buf->base.reference, 1);
31795aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca      return &buf->base;
31895aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca   }
31995aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
3200bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex_unlock(mgr->mutex);
321fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
322fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   buf = CALLOC_STRUCT(pb_cache_buffer);
323fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   if(!buf)
324fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      return NULL;
325fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
326fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
32739d7de69b1e3317ba813b4475f2b6132d70f8eefMarek Olšák
32839d7de69b1e3317ba813b4475f2b6132d70f8eefMarek Olšák   /* Empty the cache and try again. */
32939d7de69b1e3317ba813b4475f2b6132d70f8eefMarek Olšák   if (!buf->buffer) {
33039d7de69b1e3317ba813b4475f2b6132d70f8eefMarek Olšák      mgr->base.flush(&mgr->base);
33139d7de69b1e3317ba813b4475f2b6132d70f8eefMarek Olšák      buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
33239d7de69b1e3317ba813b4475f2b6132d70f8eefMarek Olšák   }
33339d7de69b1e3317ba813b4475f2b6132d70f8eefMarek Olšák
334fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   if(!buf->buffer) {
335fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      FREE(buf);
336fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      return NULL;
337fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   }
338fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
3394682e706012fe26627a2f827db01b5068cc62814Marek Olšák   assert(pipe_is_referenced(&buf->buffer->reference));
3404682e706012fe26627a2f827db01b5068cc62814Marek Olšák   assert(pb_check_alignment(desc->alignment, buf->buffer->alignment));
3414682e706012fe26627a2f827db01b5068cc62814Marek Olšák   assert(pb_check_usage(desc->usage, buf->buffer->usage));
3424682e706012fe26627a2f827db01b5068cc62814Marek Olšák   assert(buf->buffer->size >= size);
34395aeeb6d746e57473116ef4d72c05330902f68a5José Fonseca
3444682e706012fe26627a2f827db01b5068cc62814Marek Olšák   pipe_reference_init(&buf->base.reference, 1);
3454682e706012fe26627a2f827db01b5068cc62814Marek Olšák   buf->base.alignment = buf->buffer->alignment;
3464682e706012fe26627a2f827db01b5068cc62814Marek Olšák   buf->base.usage = buf->buffer->usage;
3474682e706012fe26627a2f827db01b5068cc62814Marek Olšák   buf->base.size = buf->buffer->size;
348fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
349fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   buf->base.vtbl = &pb_cache_buffer_vtbl;
350fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   buf->mgr = mgr;
351fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
352fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   return &buf->base;
353fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
354fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
355fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
3561672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonsecastatic void
3571672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonsecapb_cache_manager_flush(struct pb_manager *_mgr)
358fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
359fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
360fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct list_head *curr, *next;
361fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_buffer *buf;
362fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
3630bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex_lock(mgr->mutex);
364fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   curr = mgr->delayed.next;
365fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   next = curr->next;
366fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   while(curr != &mgr->delayed) {
367fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
368fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      _pb_cache_buffer_destroy(buf);
369fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      curr = next;
370fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      next = curr->next;
371fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   }
3720bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex_unlock(mgr->mutex);
3731672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonseca
3741672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonseca   assert(mgr->provider->flush);
3751672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonseca   if(mgr->provider->flush)
3761672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonseca      mgr->provider->flush(mgr->provider);
377a75a3df851339c782e045e01c2b21ffadb1e09f5José Fonseca}
378a75a3df851339c782e045e01c2b21ffadb1e09f5José Fonseca
379a75a3df851339c782e045e01c2b21ffadb1e09f5José Fonseca
380a75a3df851339c782e045e01c2b21ffadb1e09f5José Fonsecastatic void
381a75a3df851339c782e045e01c2b21ffadb1e09f5José Fonsecapb_cache_manager_destroy(struct pb_manager *mgr)
382a75a3df851339c782e045e01c2b21ffadb1e09f5José Fonseca{
3831672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonseca   pb_cache_manager_flush(mgr);
384fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   FREE(mgr);
385fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
386fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
387fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
388fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecastruct pb_manager *
389fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonsecapb_cache_manager_create(struct pb_manager *provider,
390fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca                     	unsigned usecs)
391fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca{
392fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   struct pb_cache_manager *mgr;
393fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
394ea4ca10b1bec67c8a60db0e4e5581318ce9f62f9José Fonseca   if(!provider)
395ea4ca10b1bec67c8a60db0e4e5581318ce9f62f9José Fonseca      return NULL;
396ea4ca10b1bec67c8a60db0e4e5581318ce9f62f9José Fonseca
397ea4ca10b1bec67c8a60db0e4e5581318ce9f62f9José Fonseca   mgr = CALLOC_STRUCT(pb_cache_manager);
398fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   if (!mgr)
399fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca      return NULL;
400fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
401fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   mgr->base.destroy = pb_cache_manager_destroy;
402fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   mgr->base.create_buffer = pb_cache_manager_create_buffer;
4031672e8e05996d48e51a1998bd7e9b08b78e012f5José Fonseca   mgr->base.flush = pb_cache_manager_flush;
404fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   mgr->provider = provider;
405fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   mgr->usecs = usecs;
406fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   LIST_INITHEAD(&mgr->delayed);
407fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   mgr->numDelayed = 0;
4080bb852fa49e7f9a31036089ea4f5dfbd312a4a3aBrian Paul   pipe_mutex_init(mgr->mutex);
409fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca
410fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca   return &mgr->base;
411fb2b5f7a4ac411a5bb5cde12ba15265b30c032e8José Fonseca}
412