pb_bufmgr_cache.c revision e9d156e9e4f92ae1ce70bd563c251b34d238c4bc
1988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul/**************************************************************************
2988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul *
3a99114a69f2b7963ca1f855a320aea8aa56755acBrian * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * All Rights Reserved.
50bf5dbe002a64e198f55724cc1542602c012490fBrian *
6988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
7988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * copy of this software and associated documentation files (the
8988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * "Software"), to deal in the Software without restriction, including
9988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * without limitation the rights to use, copy, modify, merge, publish,
10988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * distribute, sub license, and/or sell copies of the Software, and to
11988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * permit persons to whom the Software is furnished to do so, subject to
12988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * the following conditions:
13988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul *
14988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * The above copyright notice and this permission notice (including the
15988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * next paragraph) shall be included in all copies or substantial portions
16988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * of the Software.
17988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul *
18988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul *
26bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul **************************************************************************/
27bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul
28122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul/**
29bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul * \file
30bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul * Buffer cache.
31bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul *
32bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com>
33bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
34bd5ba36bf73fb63e62f779138d5e1ef6fcec6f26Brian Paul */
35bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul
36a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul
37bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "pipe/p_compiler.h"
38bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "util/u_debug.h"
39a4bec69e7271eda0137874973aa8c7d44175fedfBrian Paul#include "pipe/p_thread.h"
40bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "util/u_memory.h"
41bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "util/u_double_list.h"
42bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "util/u_time.h"
43bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul
44bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "pb_buffer.h"
451f32c665c8af0622e2bbf451edb999ffbcd7d0feEric Anholt#include "pb_bufmgr.h"
46f37070bab6af350caec905ea7658e9241042b6ccIan Romanick
47867f9b07d42c2b49ddb9e5bb17f0ac5c4a80d8acMarek Olšák
48fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
49988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * Convenience macro (type safe).
50ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul */
51b5ee368baf6472a79d250f0be418200760f4b43dBrian Paul#define SUPER(__derived) (&(__derived)->base)
52988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
53d0dc75c000d5af92648c7de901756400672b8447Brian Paul
54988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulstruct pb_cache_manager;
55bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul
566f9dbe773953b024075910b3bec11ebc96c2e8e0Brian Paul
57bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul/**
58988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * Wrapper around a pipe buffer which adds delayed destruction.
59988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul */
60988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulstruct pb_cache_buffer
61988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul{
62988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct pb_buffer base;
63988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
64988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct pb_buffer *buffer;
65988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct pb_cache_manager *mgr;
66988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
67988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   /** Caching time interval */
68988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct util_time start, end;
69988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
70988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct list_head head;
71988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul};
726bf1ea897fa470af58fe8916dff45e2da79634a3Brian Paul
73988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
74988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulstruct pb_cache_manager
75988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul{
76988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct pb_manager base;
77e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
78988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct pb_manager *provider;
79988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   unsigned usecs;
80988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
81988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   pipe_mutex mutex;
82988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
83988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct list_head delayed;
84988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   size_t numDelayed;
85122c6768e3d4c1d1b57203eca70569f9301baab5Brian Paul};
866b146214dc16b441376d8dcaba21bcc4256a2402Keith Whitwell
87988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
88bd5ba36bf73fb63e62f779138d5e1ef6fcec6f26Brian Paulstatic INLINE struct pb_cache_buffer *
89988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulpb_cache_buffer(struct pb_buffer *buf)
90988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul{
91988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   assert(buf);
92988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   return (struct pb_cache_buffer *)buf;
93988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul}
948f5fffe75d2f8ae7c7ee706b53379a25bc673ae4Brian Paul
95e42d00b3f4503a0840575c8e5f4517a66c8af613Brian Paul
96e3dc78e57a7effbd30dc9539b3ea05ad85ac34e5Brian Paulstatic INLINE struct pb_cache_manager *
97cd9ab2584f5e2a5eb0e96a948e6aedc9a33c886dBrian Paulpb_cache_manager(struct pb_manager *mgr)
98e885cb48a0b9292b3df9204f1c2783bf1fe29a28Eric Anholt{
99988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   assert(mgr);
100e8fdd0e0d5286f4a9c763ffde44decec51124ebcBrian Paul   return (struct pb_cache_manager *)mgr;
101ec19bdd16c3d4070af69fd865042babe0a627595Brian Paul}
10268d293b03535ca50daf70650b32db780f1718a3bBrian Paul
103988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
104988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul/**
105988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul * Actually destroy the buffer.
10620177a620ef123ae7cdbc7252fd41a48f5b76accBrian Paul */
10720177a620ef123ae7cdbc7252fd41a48f5b76accBrian Paulstatic INLINE void
108e6cf338d015e994012535fce5e06c7dc59482b02Brian Paul_pb_cache_buffer_destroy(struct pb_cache_buffer *buf)
109e6cf338d015e994012535fce5e06c7dc59482b02Brian Paul{
110e10337da21d45ab7cccfa98b4112d1b33f3a5604Brian Paul   struct pb_cache_manager *mgr = buf->mgr;
111e10337da21d45ab7cccfa98b4112d1b33f3a5604Brian Paul
112b4dc35d9bc879c104faac043b640ae2673763b93Chia-I Wu   LIST_DEL(&buf->head);
113988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   assert(mgr->numDelayed);
1144d859f73fce9918381c65da55f046a7c605c9e65Brian Paul   --mgr->numDelayed;
1154d859f73fce9918381c65da55f046a7c605c9e65Brian Paul   assert(!pipe_is_referenced(&buf->base.base.reference));
1164d859f73fce9918381c65da55f046a7c605c9e65Brian Paul   pb_reference(&buf->buffer, NULL);
1174d859f73fce9918381c65da55f046a7c605c9e65Brian Paul   FREE(buf);
1184d859f73fce9918381c65da55f046a7c605c9e65Brian Paul}
119988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
120988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
121988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul/**
122c93105eb9e2499efb237fd89dba0cebd48f18375Ian Romanick * Free as many cache buffers from the list head as possible.
123988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul */
124988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulstatic void
125988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul_pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr)
126988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul{
127988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct list_head *curr, *next;
128acafeeb6dce74382fb3a48b83ab72bf67b7581eaBrian Paul   struct pb_cache_buffer *buf;
129acafeeb6dce74382fb3a48b83ab72bf67b7581eaBrian Paul   struct util_time now;
130988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
131988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   util_time_get(&now);
132988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
133988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   curr = mgr->delayed.next;
134988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   next = curr->next;
135988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   while(curr != &mgr->delayed) {
136988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul      buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
137988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
138988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul      if(!util_time_timeout(&buf->start, &buf->end, &now))
139988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul	 break;
140988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
141988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul      _pb_cache_buffer_destroy(buf);
142988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
143988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul      curr = next;
144988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul      next = curr->next;
145988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   }
146988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul}
147988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
148988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
149988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulstatic void
150988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulpb_cache_buffer_destroy(struct pb_buffer *_buf)
151878c371e6cf6eb28afacc482d8aeaa0119f00d5bBrian Paul{
1525179f671e7f9366e278dbff519c283956ba0c2feBrian Paul   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
153878c371e6cf6eb28afacc482d8aeaa0119f00d5bBrian Paul   struct pb_cache_manager *mgr = buf->mgr;
154988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
155988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   pipe_mutex_lock(mgr->mutex);
156988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   assert(!pipe_is_referenced(&buf->base.base.reference));
157988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
158988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   _pb_cache_buffer_list_check_free(mgr);
159a8da1feb231115205f3a19b0bb0a9317157ba167Brian Paul
160331eb58f68db26b54f706a908a3e1424a461b709Brian Paul   util_time_get(&buf->start);
161e75b283b45add351dbe5a09289fe85546df8a79aBrian Paul   util_time_add(&buf->start, mgr->usecs, &buf->end);
162a8da1feb231115205f3a19b0bb0a9317157ba167Brian Paul   LIST_ADDTAIL(&buf->head, &mgr->delayed);
163a8da1feb231115205f3a19b0bb0a9317157ba167Brian Paul   ++mgr->numDelayed;
164a8da1feb231115205f3a19b0bb0a9317157ba167Brian Paul   pipe_mutex_unlock(mgr->mutex);
165f37070bab6af350caec905ea7658e9241042b6ccIan Romanick}
166f37070bab6af350caec905ea7658e9241042b6ccIan Romanick
1672c6f911e10761c0946261d494bf149b19072821dBrian Paul
168d0dc75c000d5af92648c7de901756400672b8447Brian Paulstatic void *
169d0dc75c000d5af92648c7de901756400672b8447Brian Paulpb_cache_buffer_map(struct pb_buffer *_buf,
170d0dc75c000d5af92648c7de901756400672b8447Brian Paul                  unsigned flags)
171755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul{
172755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
173e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   return pb_map(buf->buffer, flags);
17462c66b34303303e6786652efa611a100ae64439aBrian Paul}
1752c6f911e10761c0946261d494bf149b19072821dBrian Paul
176afa1df58714c37b056fe9aee77500e900ee9dbf0Brian Paul
177afa1df58714c37b056fe9aee77500e900ee9dbf0Brian Paulstatic void
178867f9b07d42c2b49ddb9e5bb17f0ac5c4a80d8acMarek Olšákpb_cache_buffer_unmap(struct pb_buffer *_buf)
179867f9b07d42c2b49ddb9e5bb17f0ac5c4a80d8acMarek Olšák{
180ee34e6ef716bb630440299ac1efbc2055ef09ffdIan Romanick   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
181ee34e6ef716bb630440299ac1efbc2055ef09ffdIan Romanick   pb_unmap(buf->buffer);
182ee34e6ef716bb630440299ac1efbc2055ef09ffdIan Romanick}
183ee34e6ef716bb630440299ac1efbc2055ef09ffdIan Romanick
184ee34e6ef716bb630440299ac1efbc2055ef09ffdIan Romanick
185a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paulstatic enum pipe_error
186a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paulpb_cache_buffer_validate(struct pb_buffer *_buf,
187fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         struct pb_validate *vl,
188fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         unsigned flags)
1891f32c665c8af0622e2bbf451edb999ffbcd7d0feEric Anholt{
1901f32c665c8af0622e2bbf451edb999ffbcd7d0feEric Anholt   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
191988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   return pb_validate(buf->buffer, vl, flags);
192988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul}
193988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
194988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
195988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulstatic void
196988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulpb_cache_buffer_fence(struct pb_buffer *_buf,
197b5ee368baf6472a79d250f0be418200760f4b43dBrian Paul                      struct pipe_fence_handle *fence)
198988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul{
199988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
200fd7c46f53f3a7ae5c67f3c44ba283eeb4f72b366Chad Versace   pb_fence(buf->buffer, fence);
201988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul}
202988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
203988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul
204988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulstatic void
205988a8862c8379c0312d40353ee4b35537dff59a1Brian Paulpb_cache_buffer_get_base_buffer(struct pb_buffer *_buf,
206988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul                              struct pb_buffer **base_buf,
207988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul                              unsigned *offset)
208988a8862c8379c0312d40353ee4b35537dff59a1Brian Paul{
20912d69fca096facf0ddb4642faaed4d5f02d76848Brian Paul   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
21012d69fca096facf0ddb4642faaed4d5f02d76848Brian Paul   pb_get_base_buffer(buf->buffer, base_buf, offset);
21112d69fca096facf0ddb4642faaed4d5f02d76848Brian Paul}
2120bf5dbe002a64e198f55724cc1542602c012490fBrian
2130bf5dbe002a64e198f55724cc1542602c012490fBrian
2140bf5dbe002a64e198f55724cc1542602c012490fBrianconst struct pb_vtbl
2150bf5dbe002a64e198f55724cc1542602c012490fBrianpb_cache_buffer_vtbl = {
216a99114a69f2b7963ca1f855a320aea8aa56755acBrian      pb_cache_buffer_destroy,
217a99114a69f2b7963ca1f855a320aea8aa56755acBrian      pb_cache_buffer_map,
218a99114a69f2b7963ca1f855a320aea8aa56755acBrian      pb_cache_buffer_unmap,
219a99114a69f2b7963ca1f855a320aea8aa56755acBrian      pb_cache_buffer_validate,
220a99114a69f2b7963ca1f855a320aea8aa56755acBrian      pb_cache_buffer_fence,
221f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg      pb_cache_buffer_get_base_buffer
222a99114a69f2b7963ca1f855a320aea8aa56755acBrian};
223a99114a69f2b7963ca1f855a320aea8aa56755acBrian
224a99114a69f2b7963ca1f855a320aea8aa56755acBrian
225a99114a69f2b7963ca1f855a320aea8aa56755acBrianstatic INLINE boolean
226a99114a69f2b7963ca1f855a320aea8aa56755acBrianpb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
227a99114a69f2b7963ca1f855a320aea8aa56755acBrian                          size_t size,
22874713e2d293f9e796a4053a5a99ee5cb7df5c740Brian Paul                          const struct pb_desc *desc)
22974713e2d293f9e796a4053a5a99ee5cb7df5c740Brian Paul{
230a99114a69f2b7963ca1f855a320aea8aa56755acBrian   if(buf->base.base.size < size)
231a99114a69f2b7963ca1f855a320aea8aa56755acBrian      return FALSE;
23274713e2d293f9e796a4053a5a99ee5cb7df5c740Brian Paul
23374713e2d293f9e796a4053a5a99ee5cb7df5c740Brian Paul   /* be lenient with size */
23474713e2d293f9e796a4053a5a99ee5cb7df5c740Brian Paul   if(buf->base.base.size >= 2*size)
23574713e2d293f9e796a4053a5a99ee5cb7df5c740Brian Paul      return FALSE;
236a99114a69f2b7963ca1f855a320aea8aa56755acBrian
237fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul   if(!pb_check_alignment(desc->alignment, buf->base.base.alignment))
238fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul      return FALSE;
239fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul
240fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul   if(!pb_check_usage(desc->usage, buf->base.base.usage))
2419b8287f8f5398647ced3a52885233d58e548c2b7Brian Paul      return FALSE;
2429b8287f8f5398647ced3a52885233d58e548c2b7Brian Paul
2439b8287f8f5398647ced3a52885233d58e548c2b7Brian Paul   return TRUE;
2449b8287f8f5398647ced3a52885233d58e548c2b7Brian Paul}
245fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul
246fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul
247fd5511d27fc44096117c47ab503fb5b47f993061Brian Paulstatic struct pb_buffer *
248fd5511d27fc44096117c47ab503fb5b47f993061Brian Paulpb_cache_manager_create_buffer(struct pb_manager *_mgr,
249fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul                               size_t size,
250fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul                               const struct pb_desc *desc)
251fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul{
252fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
253fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul   struct pb_cache_buffer *buf;
254a99114a69f2b7963ca1f855a320aea8aa56755acBrian   struct pb_cache_buffer *curr_buf;
255a99114a69f2b7963ca1f855a320aea8aa56755acBrian   struct list_head *curr, *next;
256a99114a69f2b7963ca1f855a320aea8aa56755acBrian   struct util_time now;
257a99114a69f2b7963ca1f855a320aea8aa56755acBrian
258a99114a69f2b7963ca1f855a320aea8aa56755acBrian   pipe_mutex_lock(mgr->mutex);
259a99114a69f2b7963ca1f855a320aea8aa56755acBrian
260a99114a69f2b7963ca1f855a320aea8aa56755acBrian   buf = NULL;
261a99114a69f2b7963ca1f855a320aea8aa56755acBrian   curr = mgr->delayed.next;
262a99114a69f2b7963ca1f855a320aea8aa56755acBrian   next = curr->next;
263a99114a69f2b7963ca1f855a320aea8aa56755acBrian
264a99114a69f2b7963ca1f855a320aea8aa56755acBrian   /* search in the expired buffers, freeing them in the process */
265a99114a69f2b7963ca1f855a320aea8aa56755acBrian   util_time_get(&now);
266a99114a69f2b7963ca1f855a320aea8aa56755acBrian   while(curr != &mgr->delayed) {
267a99114a69f2b7963ca1f855a320aea8aa56755acBrian      curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
268a99114a69f2b7963ca1f855a320aea8aa56755acBrian      if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc))
269a99114a69f2b7963ca1f855a320aea8aa56755acBrian	 buf = curr_buf;
270a99114a69f2b7963ca1f855a320aea8aa56755acBrian      else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now))
27191e61f435a71436c209934a0ece165b540aba3e0Brian Paul	 _pb_cache_buffer_destroy(curr_buf);
272a99114a69f2b7963ca1f855a320aea8aa56755acBrian      else
273a99114a69f2b7963ca1f855a320aea8aa56755acBrian         /* This buffer (and all hereafter) are still hot in cache */
274a99114a69f2b7963ca1f855a320aea8aa56755acBrian         break;
275a99114a69f2b7963ca1f855a320aea8aa56755acBrian      curr = next;
276a99114a69f2b7963ca1f855a320aea8aa56755acBrian      next = curr->next;
277a99114a69f2b7963ca1f855a320aea8aa56755acBrian   }
278a99114a69f2b7963ca1f855a320aea8aa56755acBrian
279099aad2fb0dba8baff61dc7a6803c6c976c08069Brian Paul   /* keep searching in the hot buffers */
280099aad2fb0dba8baff61dc7a6803c6c976c08069Brian Paul   if(!buf) {
281099aad2fb0dba8baff61dc7a6803c6c976c08069Brian Paul      while(curr != &mgr->delayed) {
282099aad2fb0dba8baff61dc7a6803c6c976c08069Brian Paul         curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
283a99114a69f2b7963ca1f855a320aea8aa56755acBrian         if(pb_cache_is_buffer_compat(curr_buf, size, desc)) {
284a99114a69f2b7963ca1f855a320aea8aa56755acBrian            buf = curr_buf;
285a99114a69f2b7963ca1f855a320aea8aa56755acBrian            break;
286a99114a69f2b7963ca1f855a320aea8aa56755acBrian         }
287a99114a69f2b7963ca1f855a320aea8aa56755acBrian         /* no need to check the timeout here */
288a99114a69f2b7963ca1f855a320aea8aa56755acBrian         curr = next;
289a99114a69f2b7963ca1f855a320aea8aa56755acBrian         next = curr->next;
290a99114a69f2b7963ca1f855a320aea8aa56755acBrian      }
291a99114a69f2b7963ca1f855a320aea8aa56755acBrian   }
292a99114a69f2b7963ca1f855a320aea8aa56755acBrian
293a99114a69f2b7963ca1f855a320aea8aa56755acBrian   if(buf) {
294a99114a69f2b7963ca1f855a320aea8aa56755acBrian      LIST_DEL(&buf->head);
295a99114a69f2b7963ca1f855a320aea8aa56755acBrian      pipe_mutex_unlock(mgr->mutex);
296a99114a69f2b7963ca1f855a320aea8aa56755acBrian      /* Increase refcount */
297a99114a69f2b7963ca1f855a320aea8aa56755acBrian      pb_reference((struct pb_buffer**)&buf, &buf->base);
298a99114a69f2b7963ca1f855a320aea8aa56755acBrian      return &buf->base;
299a99114a69f2b7963ca1f855a320aea8aa56755acBrian   }
300a99114a69f2b7963ca1f855a320aea8aa56755acBrian
301a99114a69f2b7963ca1f855a320aea8aa56755acBrian   pipe_mutex_unlock(mgr->mutex);
302a99114a69f2b7963ca1f855a320aea8aa56755acBrian
303a99114a69f2b7963ca1f855a320aea8aa56755acBrian   buf = CALLOC_STRUCT(pb_cache_buffer);
304a99114a69f2b7963ca1f855a320aea8aa56755acBrian   if(!buf)
305a99114a69f2b7963ca1f855a320aea8aa56755acBrian      return NULL;
306a99114a69f2b7963ca1f855a320aea8aa56755acBrian
307a99114a69f2b7963ca1f855a320aea8aa56755acBrian   buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
308a99114a69f2b7963ca1f855a320aea8aa56755acBrian   if(!buf->buffer) {
309a99114a69f2b7963ca1f855a320aea8aa56755acBrian      FREE(buf);
310a99114a69f2b7963ca1f855a320aea8aa56755acBrian      return NULL;
311a99114a69f2b7963ca1f855a320aea8aa56755acBrian   }
312a99114a69f2b7963ca1f855a320aea8aa56755acBrian
313a99114a69f2b7963ca1f855a320aea8aa56755acBrian   assert(pipe_is_referenced(&buf->buffer->base.reference));
314a99114a69f2b7963ca1f855a320aea8aa56755acBrian   assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment));
315a99114a69f2b7963ca1f855a320aea8aa56755acBrian   assert(pb_check_usage(desc->usage, buf->buffer->base.usage));
316a99114a69f2b7963ca1f855a320aea8aa56755acBrian   assert(buf->buffer->base.size >= size);
317a99114a69f2b7963ca1f855a320aea8aa56755acBrian
318a99114a69f2b7963ca1f855a320aea8aa56755acBrian   pipe_reference_init(&buf->base.base.reference, 1);
319a99114a69f2b7963ca1f855a320aea8aa56755acBrian   buf->base.base.alignment = buf->buffer->base.alignment;
320a99114a69f2b7963ca1f855a320aea8aa56755acBrian   buf->base.base.usage = buf->buffer->base.usage;
321a99114a69f2b7963ca1f855a320aea8aa56755acBrian   buf->base.base.size = buf->buffer->base.size;
322a99114a69f2b7963ca1f855a320aea8aa56755acBrian
323   buf->base.vtbl = &pb_cache_buffer_vtbl;
324   buf->mgr = mgr;
325
326   return &buf->base;
327}
328
329
330static void
331pb_cache_manager_flush(struct pb_manager *_mgr)
332{
333   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
334   struct list_head *curr, *next;
335   struct pb_cache_buffer *buf;
336
337   pipe_mutex_lock(mgr->mutex);
338   curr = mgr->delayed.next;
339   next = curr->next;
340   while(curr != &mgr->delayed) {
341      buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
342      _pb_cache_buffer_destroy(buf);
343      curr = next;
344      next = curr->next;
345   }
346   pipe_mutex_unlock(mgr->mutex);
347
348   assert(mgr->provider->flush);
349   if(mgr->provider->flush)
350      mgr->provider->flush(mgr->provider);
351}
352
353
354static void
355pb_cache_manager_destroy(struct pb_manager *mgr)
356{
357   pb_cache_manager_flush(mgr);
358   FREE(mgr);
359}
360
361
362struct pb_manager *
363pb_cache_manager_create(struct pb_manager *provider,
364                     	unsigned usecs)
365{
366   struct pb_cache_manager *mgr;
367
368   if(!provider)
369      return NULL;
370
371   mgr = CALLOC_STRUCT(pb_cache_manager);
372   if (!mgr)
373      return NULL;
374
375   mgr->base.destroy = pb_cache_manager_destroy;
376   mgr->base.create_buffer = pb_cache_manager_create_buffer;
377   mgr->base.flush = pb_cache_manager_flush;
378   mgr->provider = provider;
379   mgr->usecs = usecs;
380   LIST_INITHEAD(&mgr->delayed);
381   mgr->numDelayed = 0;
382   pipe_mutex_init(mgr->mutex);
383
384   return &mgr->base;
385}
386