1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**************************************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All Rights Reserved.
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sub license, and/or sell copies of the Software, and to
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial portions
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the Software.
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **************************************************************************/
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \file
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Buffer cache.
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com>
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_compiler.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_debug.h"
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "os/os_thread.h"
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_memory.h"
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_double_list.h"
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_time.h"
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pb_buffer.h"
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pb_bufmgr.h"
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Convenience macro (type safe).
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define SUPER(__derived) (&(__derived)->base)
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pb_cache_manager;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Wrapper around a pipe buffer which adds delayed destruction.
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pb_cache_buffer
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_buffer base;
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_buffer *buffer;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_manager *mgr;
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /** Caching time interval */
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int64_t start, end;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct list_head head;
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pb_cache_manager
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_manager base;
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_manager *provider;
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned usecs;
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex mutex;
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct list_head delayed;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pb_size numDelayed;
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE struct pb_cache_buffer *
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer(struct pb_buffer *buf)
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(buf);
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (struct pb_cache_buffer *)buf;
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE struct pb_cache_manager *
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_manager(struct pb_manager *mgr)
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(mgr);
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (struct pb_cache_manager *)mgr;
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Actually destroy the buffer.
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_pb_cache_buffer_destroy(struct pb_cache_buffer *buf)
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_manager *mgr = buf->mgr;
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   LIST_DEL(&buf->head);
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(mgr->numDelayed);
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   --mgr->numDelayed;
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(!pipe_is_referenced(&buf->base.reference));
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pb_reference(&buf->buffer, NULL);
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(buf);
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Free as many cache buffers from the list head as possible.
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr)
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct list_head *curr, *next;
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf;
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int64_t now;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   now = os_time_get();
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   curr = mgr->delayed.next;
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   next = curr->next;
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while(curr != &mgr->delayed) {
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(!os_time_timeout(buf->start, buf->end, now))
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _pb_cache_buffer_destroy(buf);
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      curr = next;
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      next = curr->next;
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer_destroy(struct pb_buffer *_buf)
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_manager *mgr = buf->mgr;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex_lock(mgr->mutex);
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(!pipe_is_referenced(&buf->base.reference));
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _pb_cache_buffer_list_check_free(mgr);
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->start = os_time_get();
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->end = buf->start + mgr->usecs;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   LIST_ADDTAIL(&buf->head, &mgr->delayed);
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ++mgr->numDelayed;
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex_unlock(mgr->mutex);
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void *
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer_map(struct pb_buffer *_buf,
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    unsigned flags, void *flush_ctx)
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return pb_map(buf->buffer, flags, flush_ctx);
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer_unmap(struct pb_buffer *_buf)
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pb_unmap(buf->buffer);
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic enum pipe_error
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer_validate(struct pb_buffer *_buf,
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         struct pb_validate *vl,
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         unsigned flags)
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return pb_validate(buf->buffer, vl, flags);
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer_fence(struct pb_buffer *_buf,
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      struct pipe_fence_handle *fence)
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pb_fence(buf->buffer, fence);
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer_get_base_buffer(struct pb_buffer *_buf,
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              struct pb_buffer **base_buf,
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              pb_size *offset)
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pb_get_base_buffer(buf->buffer, base_buf, offset);
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst struct pb_vtbl
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_buffer_vtbl = {
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pb_cache_buffer_destroy,
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pb_cache_buffer_map,
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pb_cache_buffer_unmap,
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pb_cache_buffer_validate,
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pb_cache_buffer_fence,
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pb_cache_buffer_get_base_buffer
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE int
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          pb_size size,
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          const struct pb_desc *desc)
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(buf->base.size < size)
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* be lenient with size */
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(buf->base.size >= 2*size)
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!pb_check_alignment(desc->alignment, buf->base.alignment))
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!pb_check_usage(desc->usage, buf->base.usage))
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (buf->mgr->provider->is_buffer_busy) {
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (buf->mgr->provider->is_buffer_busy(buf->mgr->provider, buf->buffer))
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return -1;
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      void *ptr = pb_map(buf->buffer, PB_USAGE_DONTBLOCK, NULL);
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!ptr)
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return -1;
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pb_unmap(buf->buffer);
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return 1;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct pb_buffer *
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_manager_create_buffer(struct pb_manager *_mgr,
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               pb_size size,
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               const struct pb_desc *desc)
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf;
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *curr_buf;
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct list_head *curr, *next;
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int64_t now;
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int ret = 0;
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex_lock(mgr->mutex);
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf = NULL;
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   curr = mgr->delayed.next;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   next = curr->next;
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* search in the expired buffers, freeing them in the process */
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   now = os_time_get();
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while(curr != &mgr->delayed) {
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if(!buf && (ret = pb_cache_is_buffer_compat(curr_buf, size, desc) > 0))
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         buf = curr_buf;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if(os_time_timeout(curr_buf->start, curr_buf->end, now))
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _pb_cache_buffer_destroy(curr_buf);
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* This buffer (and all hereafter) are still hot in cache */
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ret == -1)
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      curr = next;
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      next = curr->next;
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* keep searching in the hot buffers */
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!buf && ret != -1) {
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      while(curr != &mgr->delayed) {
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ret = pb_cache_is_buffer_compat(curr_buf, size, desc);
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (ret > 0) {
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            buf = curr_buf;
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (ret == -1)
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            break;
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* no need to check the timeout here */
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         curr = next;
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         next = curr->next;
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(buf) {
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      LIST_DEL(&buf->head);
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      --mgr->numDelayed;
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pipe_mutex_unlock(mgr->mutex);
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Increase refcount */
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pipe_reference_init(&buf->base.reference, 1);
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return &buf->base;
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex_unlock(mgr->mutex);
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf = CALLOC_STRUCT(pb_cache_buffer);
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!buf)
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Empty the cache and try again. */
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!buf->buffer) {
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mgr->base.flush(&mgr->base);
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!buf->buffer) {
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(buf);
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(pipe_is_referenced(&buf->buffer->reference));
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(pb_check_alignment(desc->alignment, buf->buffer->alignment));
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(pb_check_usage(desc->usage, buf->buffer->usage));
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(buf->buffer->size >= size);
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_reference_init(&buf->base.reference, 1);
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->base.alignment = buf->buffer->alignment;
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->base.usage = buf->buffer->usage;
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->base.size = buf->buffer->size;
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->base.vtbl = &pb_cache_buffer_vtbl;
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   buf->mgr = mgr;
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return &buf->base;
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_manager_flush(struct pb_manager *_mgr)
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct list_head *curr, *next;
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_buffer *buf;
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex_lock(mgr->mutex);
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   curr = mgr->delayed.next;
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   next = curr->next;
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while(curr != &mgr->delayed) {
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _pb_cache_buffer_destroy(buf);
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      curr = next;
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      next = curr->next;
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex_unlock(mgr->mutex);
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(mgr->provider->flush);
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(mgr->provider->flush)
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mgr->provider->flush(mgr->provider);
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_manager_destroy(struct pb_manager *mgr)
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pb_cache_manager_flush(mgr);
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(mgr);
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pb_manager *
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpb_cache_manager_create(struct pb_manager *provider,
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     	unsigned usecs)
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_cache_manager *mgr;
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!provider)
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mgr = CALLOC_STRUCT(pb_cache_manager);
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!mgr)
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mgr->base.destroy = pb_cache_manager_destroy;
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mgr->base.create_buffer = pb_cache_manager_create_buffer;
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mgr->base.flush = pb_cache_manager_flush;
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mgr->provider = provider;
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mgr->usecs = usecs;
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   LIST_INITHEAD(&mgr->delayed);
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   mgr->numDelayed = 0;
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pipe_mutex_init(mgr->mutex);
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return &mgr->base;
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
412