VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/bufpool.c@ 79241

Last change on this file since 79241 was 78909, checked in by vboxsync, 6 years ago

GuestHost/OpenGL/util/bufpool.c: Fix memory leak

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.4 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_mem.h"
8#include "cr_error.h"
9#include "cr_bufpool.h"
10#include <limits.h>
11
12/*
13 * New (version 1.4) buffer pool implementation.
14 *
15 * Now, each buffer in the pool can be a different size.
16 * We only return a buffer from crBufferPoolPop() if we have exactly
17 * the right size buffer.
18 *
19 * Note: the old implementation had a 'max buffers' parameter but it
20 * really wasn't good for anything since we always grew the buffer pool
21 * if we pushed a new buffer that would cause use to exceed the limit.
22 * That's gone now.
23 *
24 * We're just using a simple linked list here. Since we seldom have
25 * more than about 10-15 buffers in the pool, that's OK. A binary tree
26 * would be nicer though.
27 *
28 * MCH: BufferPoolPop will now return the smallest buffer in the pool that
29 * is >= to the size required. This fixes BufferPool overruns with lots
30 * of MTUs.
31 */
32
33
34#ifndef NULL
35#define NULL ((void *) 0)
36#endif
37
38
39typedef struct buffer
40{
41 void *address;
42 unsigned int size;
43 struct buffer *next;
44} Buffer;
45
46
47struct CRBufferPool_t
48{
49 unsigned int maxBuffers;
50 int numBuffers;
51 struct buffer *head;
52};
53
54
55int
56crBufferPoolGetNumBuffers( CRBufferPool *pool )
57{
58 if ( pool )
59 return pool->numBuffers;
60 return 0;
61}
62
63int
64crBufferPoolGetMaxBuffers( CRBufferPool *pool )
65{
66 if ( pool )
67 return pool->maxBuffers;
68 return 0;
69}
70
71CRBufferPool *
72crBufferPoolInit( unsigned int maxBuffers )
73{
74 CRBufferPool *pool = crCalloc(sizeof(CRBufferPool));
75 if (pool) {
76 pool->head = NULL;
77 pool->maxBuffers = maxBuffers;
78 pool->numBuffers = 0;
79 }
80 return pool;
81}
82
83void
84crBufferPoolFree( CRBufferPool *pool )
85{
86 Buffer *b, *next;
87
88 for (b = pool->head; b; b = next) {
89 next = b->next;
90 crFree(b->address);
91 crFree(b);
92 }
93 crFree(pool);
94}
95
96void
97crBufferPoolCallbackFree(CRBufferPool *pool, CRBufferPoolDeleteCallback pfnDelete)
98{
99 Buffer *b, *next;
100
101 CRASSERT(pfnDelete);
102
103 for (b = pool->head; b; b = next) {
104 next = b->next;
105 (*pfnDelete)(b->address);
106 crFree(b);
107 }
108 crFree(pool);
109}
110
111void
112crBufferPoolPush( CRBufferPool *pool, void *buf, unsigned int bytes )
113{
114 Buffer *b = crCalloc(sizeof(Buffer));
115 if (b) {
116#ifdef DEBUG
117 /* check that the buffer to push isn't already in the pool! */
118 {
119 const Buffer *bd;
120 for (bd = pool->head; bd; bd = bd->next) {
121 CRASSERT(bd->address != buf);
122 }
123 }
124#endif
125
126 b->address = buf;
127 b->size = bytes;
128 b->next = pool->head;
129 pool->head = b;
130 pool->numBuffers++;
131 }
132}
133
134void *
135crBufferPoolPop( CRBufferPool *pool, unsigned int bytes )
136{
137 Buffer *b, *prev, *prev_smallest;
138 unsigned int smallest = UINT_MAX; /* size of smallest buffer >= bytes */
139 int i;
140
141 prev = NULL;
142 prev_smallest = NULL;
143 for (b = pool->head, i=0; i<pool->numBuffers; b = b->next, i++) {
144 if (b->size == bytes) {
145 /* we found an exact size match! */
146 void *p = b->address;
147 if (prev) {
148 prev->next = b->next;
149 }
150 else {
151 pool->head = b->next;
152 }
153 crFree(b);
154 pool->numBuffers--;
155 CRASSERT(pool->numBuffers >= 0);
156 return p;
157 }
158 else if (b->size >= bytes){
159 /* We found a buffer that's large enough, but keep looking
160 * for a smaller one that's large enough.
161 */
162 if (b->size < smallest) {
163 prev_smallest = prev; /* save ptr to previous! */
164 smallest = b->size;
165 }
166 }
167 prev = b;
168 }
169
170 if (smallest < UINT_MAX) {
171 /* we found the smallest buffer whose size is > bytes */
172 void *p;
173 if (prev_smallest) {
174 b = prev_smallest->next;
175 }
176 else {
177 b = pool->head;
178 }
179 CRASSERT(b->size == smallest);
180 CRASSERT(b->size >= bytes);
181 p = b->address;
182 if (prev_smallest) {
183 prev_smallest->next = b->next;
184 }
185 else {
186 pool->head = b->next;
187 }
188 crFree(b);
189 pool->numBuffers--;
190 CRASSERT(pool->numBuffers >= 0);
191 return p;
192 }
193
194 /* found no buffer large enough */
195 return NULL;
196}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette