14563b2591c1359c58687ee6321359c59b6f8eb5
[mesa.git] / src / mesa / main / mm.c
1 /*
2 * GLX Hardware Device Driver common code
3 * Copyright (C) 1999 Wittawat Yamwong
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24 /* $XFree86: xc/lib/GL/mesa/src/drv/common/mm.c,v 1.4 2002/10/30 12:51:27 alanh Exp $ */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28
29 #include "mm.h"
30
31
32 void mmDumpMemInfo( memHeap_t *heap )
33 {
34 TMemBlock *p;
35
36 fprintf(stderr, "Memory heap %p:\n", (void *)heap);
37 if (heap == 0) {
38 fprintf(stderr, " heap == 0\n");
39 } else {
40 p = (TMemBlock *)heap;
41 while (p) {
42 fprintf(stderr, " Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
43 p->free ? '.':'U',
44 p->reserved ? 'R':'.');
45 p = p->next;
46 }
47 }
48 fprintf(stderr, "End of memory blocks\n");
49 }
50
51 memHeap_t *mmInit(int ofs,
52 int size)
53 {
54 PMemBlock blocks;
55
56 if (size <= 0) {
57 return NULL;
58 }
59 blocks = (TMemBlock *) calloc(1,sizeof(TMemBlock));
60 if (blocks) {
61 blocks->ofs = ofs;
62 blocks->size = size;
63 blocks->free = 1;
64 return (memHeap_t *)blocks;
65 } else
66 return NULL;
67 }
68
69
70 static TMemBlock* SliceBlock(TMemBlock *p,
71 int startofs, int size,
72 int reserved, int alignment)
73 {
74 TMemBlock *newblock;
75
76 /* break left */
77 if (startofs > p->ofs) {
78 newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
79 if (!newblock)
80 return NULL;
81 newblock->ofs = startofs;
82 newblock->size = p->size - (startofs - p->ofs);
83 newblock->free = 1;
84 newblock->next = p->next;
85 p->size -= newblock->size;
86 p->next = newblock;
87 p = newblock;
88 }
89
90 /* break right */
91 if (size < p->size) {
92 newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
93 if (!newblock)
94 return NULL;
95 newblock->ofs = startofs + size;
96 newblock->size = p->size - size;
97 newblock->free = 1;
98 newblock->next = p->next;
99 p->size = size;
100 p->next = newblock;
101 }
102
103 /* p = middle block */
104 p->align = alignment;
105 p->free = 0;
106 p->reserved = reserved;
107 return p;
108 }
109
110 PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
111 {
112 int mask,startofs,endofs;
113 TMemBlock *p;
114
115 if (!heap || align2 < 0 || size <= 0)
116 return NULL;
117 mask = (1 << align2)-1;
118 startofs = 0;
119 p = (TMemBlock *)heap;
120 while (p) {
121 if ((p)->free) {
122 startofs = (p->ofs + mask) & ~mask;
123 if ( startofs < startSearch ) {
124 startofs = startSearch;
125 }
126 endofs = startofs+size;
127 if (endofs <= (p->ofs+p->size))
128 break;
129 }
130 p = p->next;
131 }
132 if (!p)
133 return NULL;
134 p = SliceBlock(p,startofs,size,0,mask+1);
135 p->heap = heap;
136 return p;
137 }
138
139 PMemBlock mmFindBlock( memHeap_t *heap, int start)
140 {
141 TMemBlock *p = (TMemBlock *)heap;
142
143 while (p) {
144 if (p->ofs == start && p->free)
145 return p;
146
147 p = p->next;
148 }
149
150 return NULL;
151 }
152
153
154 static __inline__ int Join2Blocks(TMemBlock *p)
155 {
156 if (p->free && p->next && p->next->free) {
157 TMemBlock *q = p->next;
158 p->size += q->size;
159 p->next = q->next;
160 free(q);
161 return 1;
162 }
163 return 0;
164 }
165
166 int mmFreeMem(PMemBlock b)
167 {
168 TMemBlock *p,*prev;
169
170 if (!b)
171 return 0;
172 if (!b->heap) {
173 fprintf(stderr, "no heap\n");
174 return -1;
175 }
176 p = b->heap;
177 prev = NULL;
178 while (p && p != b) {
179 prev = p;
180 p = p->next;
181 }
182 if (!p || p->free || p->reserved) {
183 if (!p)
184 fprintf(stderr, "block not found in heap\n");
185 else if (p->free)
186 fprintf(stderr, "block already free\n");
187 else
188 fprintf(stderr, "block is reserved\n");
189 return -1;
190 }
191 p->free = 1;
192 Join2Blocks(p);
193 if (prev)
194 Join2Blocks(prev);
195 return 0;
196 }
197
198
199 void mmDestroy(memHeap_t *heap)
200 {
201 TMemBlock *p,*q;
202
203 if (!heap)
204 return;
205 p = (TMemBlock *)heap;
206 while (p) {
207 q = p->next;
208 free(p);
209 p = q;
210 }
211 }