1*7688df22SAndroid Build Coastguard Worker /*
2*7688df22SAndroid Build Coastguard Worker * GLX Hardware Device Driver common code
3*7688df22SAndroid Build Coastguard Worker * Copyright (C) 1999 Wittawat Yamwong
4*7688df22SAndroid Build Coastguard Worker *
5*7688df22SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
6*7688df22SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
7*7688df22SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
8*7688df22SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*7688df22SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
10*7688df22SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
11*7688df22SAndroid Build Coastguard Worker *
12*7688df22SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included
13*7688df22SAndroid Build Coastguard Worker * in all copies or substantial portions of the Software.
14*7688df22SAndroid Build Coastguard Worker *
15*7688df22SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16*7688df22SAndroid Build Coastguard Worker * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*7688df22SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*7688df22SAndroid Build Coastguard Worker * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19*7688df22SAndroid Build Coastguard Worker * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20*7688df22SAndroid Build Coastguard Worker * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21*7688df22SAndroid Build Coastguard Worker * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*7688df22SAndroid Build Coastguard Worker *
23*7688df22SAndroid Build Coastguard Worker */
24*7688df22SAndroid Build Coastguard Worker
25*7688df22SAndroid Build Coastguard Worker #include <stdlib.h>
26*7688df22SAndroid Build Coastguard Worker #include <assert.h>
27*7688df22SAndroid Build Coastguard Worker
28*7688df22SAndroid Build Coastguard Worker #include "xf86drm.h"
29*7688df22SAndroid Build Coastguard Worker #include "libdrm_macros.h"
30*7688df22SAndroid Build Coastguard Worker #include "mm.h"
31*7688df22SAndroid Build Coastguard Worker
mmDumpMemInfo(const struct mem_block * heap)32*7688df22SAndroid Build Coastguard Worker drm_private void mmDumpMemInfo(const struct mem_block *heap)
33*7688df22SAndroid Build Coastguard Worker {
34*7688df22SAndroid Build Coastguard Worker drmMsg("Memory heap %p:\n", (void *)heap);
35*7688df22SAndroid Build Coastguard Worker if (heap == 0) {
36*7688df22SAndroid Build Coastguard Worker drmMsg(" heap == 0\n");
37*7688df22SAndroid Build Coastguard Worker } else {
38*7688df22SAndroid Build Coastguard Worker const struct mem_block *p;
39*7688df22SAndroid Build Coastguard Worker
40*7688df22SAndroid Build Coastguard Worker for (p = heap->next; p != heap; p = p->next) {
41*7688df22SAndroid Build Coastguard Worker drmMsg(" Offset:%08x, Size:%08x, %c%c\n", p->ofs,
42*7688df22SAndroid Build Coastguard Worker p->size, p->free ? 'F' : '.',
43*7688df22SAndroid Build Coastguard Worker p->reserved ? 'R' : '.');
44*7688df22SAndroid Build Coastguard Worker }
45*7688df22SAndroid Build Coastguard Worker
46*7688df22SAndroid Build Coastguard Worker drmMsg("\nFree list:\n");
47*7688df22SAndroid Build Coastguard Worker
48*7688df22SAndroid Build Coastguard Worker for (p = heap->next_free; p != heap; p = p->next_free) {
49*7688df22SAndroid Build Coastguard Worker drmMsg(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs,
50*7688df22SAndroid Build Coastguard Worker p->size, p->free ? 'F' : '.',
51*7688df22SAndroid Build Coastguard Worker p->reserved ? 'R' : '.');
52*7688df22SAndroid Build Coastguard Worker }
53*7688df22SAndroid Build Coastguard Worker
54*7688df22SAndroid Build Coastguard Worker }
55*7688df22SAndroid Build Coastguard Worker drmMsg("End of memory blocks\n");
56*7688df22SAndroid Build Coastguard Worker }
57*7688df22SAndroid Build Coastguard Worker
mmInit(int ofs,int size)58*7688df22SAndroid Build Coastguard Worker drm_private struct mem_block *mmInit(int ofs, int size)
59*7688df22SAndroid Build Coastguard Worker {
60*7688df22SAndroid Build Coastguard Worker struct mem_block *heap, *block;
61*7688df22SAndroid Build Coastguard Worker
62*7688df22SAndroid Build Coastguard Worker if (size <= 0)
63*7688df22SAndroid Build Coastguard Worker return NULL;
64*7688df22SAndroid Build Coastguard Worker
65*7688df22SAndroid Build Coastguard Worker heap = (struct mem_block *)calloc(1, sizeof(struct mem_block));
66*7688df22SAndroid Build Coastguard Worker if (!heap)
67*7688df22SAndroid Build Coastguard Worker return NULL;
68*7688df22SAndroid Build Coastguard Worker
69*7688df22SAndroid Build Coastguard Worker block = (struct mem_block *)calloc(1, sizeof(struct mem_block));
70*7688df22SAndroid Build Coastguard Worker if (!block) {
71*7688df22SAndroid Build Coastguard Worker free(heap);
72*7688df22SAndroid Build Coastguard Worker return NULL;
73*7688df22SAndroid Build Coastguard Worker }
74*7688df22SAndroid Build Coastguard Worker
75*7688df22SAndroid Build Coastguard Worker heap->next = block;
76*7688df22SAndroid Build Coastguard Worker heap->prev = block;
77*7688df22SAndroid Build Coastguard Worker heap->next_free = block;
78*7688df22SAndroid Build Coastguard Worker heap->prev_free = block;
79*7688df22SAndroid Build Coastguard Worker
80*7688df22SAndroid Build Coastguard Worker block->heap = heap;
81*7688df22SAndroid Build Coastguard Worker block->next = heap;
82*7688df22SAndroid Build Coastguard Worker block->prev = heap;
83*7688df22SAndroid Build Coastguard Worker block->next_free = heap;
84*7688df22SAndroid Build Coastguard Worker block->prev_free = heap;
85*7688df22SAndroid Build Coastguard Worker
86*7688df22SAndroid Build Coastguard Worker block->ofs = ofs;
87*7688df22SAndroid Build Coastguard Worker block->size = size;
88*7688df22SAndroid Build Coastguard Worker block->free = 1;
89*7688df22SAndroid Build Coastguard Worker
90*7688df22SAndroid Build Coastguard Worker return heap;
91*7688df22SAndroid Build Coastguard Worker }
92*7688df22SAndroid Build Coastguard Worker
SliceBlock(struct mem_block * p,int startofs,int size,int reserved,int alignment)93*7688df22SAndroid Build Coastguard Worker static struct mem_block *SliceBlock(struct mem_block *p,
94*7688df22SAndroid Build Coastguard Worker int startofs, int size,
95*7688df22SAndroid Build Coastguard Worker int reserved, int alignment)
96*7688df22SAndroid Build Coastguard Worker {
97*7688df22SAndroid Build Coastguard Worker struct mem_block *newblock;
98*7688df22SAndroid Build Coastguard Worker
99*7688df22SAndroid Build Coastguard Worker /* break left [p, newblock, p->next], then p = newblock */
100*7688df22SAndroid Build Coastguard Worker if (startofs > p->ofs) {
101*7688df22SAndroid Build Coastguard Worker newblock =
102*7688df22SAndroid Build Coastguard Worker (struct mem_block *)calloc(1, sizeof(struct mem_block));
103*7688df22SAndroid Build Coastguard Worker if (!newblock)
104*7688df22SAndroid Build Coastguard Worker return NULL;
105*7688df22SAndroid Build Coastguard Worker newblock->ofs = startofs;
106*7688df22SAndroid Build Coastguard Worker newblock->size = p->size - (startofs - p->ofs);
107*7688df22SAndroid Build Coastguard Worker newblock->free = 1;
108*7688df22SAndroid Build Coastguard Worker newblock->heap = p->heap;
109*7688df22SAndroid Build Coastguard Worker
110*7688df22SAndroid Build Coastguard Worker newblock->next = p->next;
111*7688df22SAndroid Build Coastguard Worker newblock->prev = p;
112*7688df22SAndroid Build Coastguard Worker p->next->prev = newblock;
113*7688df22SAndroid Build Coastguard Worker p->next = newblock;
114*7688df22SAndroid Build Coastguard Worker
115*7688df22SAndroid Build Coastguard Worker newblock->next_free = p->next_free;
116*7688df22SAndroid Build Coastguard Worker newblock->prev_free = p;
117*7688df22SAndroid Build Coastguard Worker p->next_free->prev_free = newblock;
118*7688df22SAndroid Build Coastguard Worker p->next_free = newblock;
119*7688df22SAndroid Build Coastguard Worker
120*7688df22SAndroid Build Coastguard Worker p->size -= newblock->size;
121*7688df22SAndroid Build Coastguard Worker p = newblock;
122*7688df22SAndroid Build Coastguard Worker }
123*7688df22SAndroid Build Coastguard Worker
124*7688df22SAndroid Build Coastguard Worker /* break right, also [p, newblock, p->next] */
125*7688df22SAndroid Build Coastguard Worker if (size < p->size) {
126*7688df22SAndroid Build Coastguard Worker newblock =
127*7688df22SAndroid Build Coastguard Worker (struct mem_block *)calloc(1, sizeof(struct mem_block));
128*7688df22SAndroid Build Coastguard Worker if (!newblock)
129*7688df22SAndroid Build Coastguard Worker return NULL;
130*7688df22SAndroid Build Coastguard Worker newblock->ofs = startofs + size;
131*7688df22SAndroid Build Coastguard Worker newblock->size = p->size - size;
132*7688df22SAndroid Build Coastguard Worker newblock->free = 1;
133*7688df22SAndroid Build Coastguard Worker newblock->heap = p->heap;
134*7688df22SAndroid Build Coastguard Worker
135*7688df22SAndroid Build Coastguard Worker newblock->next = p->next;
136*7688df22SAndroid Build Coastguard Worker newblock->prev = p;
137*7688df22SAndroid Build Coastguard Worker p->next->prev = newblock;
138*7688df22SAndroid Build Coastguard Worker p->next = newblock;
139*7688df22SAndroid Build Coastguard Worker
140*7688df22SAndroid Build Coastguard Worker newblock->next_free = p->next_free;
141*7688df22SAndroid Build Coastguard Worker newblock->prev_free = p;
142*7688df22SAndroid Build Coastguard Worker p->next_free->prev_free = newblock;
143*7688df22SAndroid Build Coastguard Worker p->next_free = newblock;
144*7688df22SAndroid Build Coastguard Worker
145*7688df22SAndroid Build Coastguard Worker p->size = size;
146*7688df22SAndroid Build Coastguard Worker }
147*7688df22SAndroid Build Coastguard Worker
148*7688df22SAndroid Build Coastguard Worker /* p = middle block */
149*7688df22SAndroid Build Coastguard Worker p->free = 0;
150*7688df22SAndroid Build Coastguard Worker
151*7688df22SAndroid Build Coastguard Worker /* Remove p from the free list:
152*7688df22SAndroid Build Coastguard Worker */
153*7688df22SAndroid Build Coastguard Worker p->next_free->prev_free = p->prev_free;
154*7688df22SAndroid Build Coastguard Worker p->prev_free->next_free = p->next_free;
155*7688df22SAndroid Build Coastguard Worker
156*7688df22SAndroid Build Coastguard Worker p->next_free = 0;
157*7688df22SAndroid Build Coastguard Worker p->prev_free = 0;
158*7688df22SAndroid Build Coastguard Worker
159*7688df22SAndroid Build Coastguard Worker p->reserved = reserved;
160*7688df22SAndroid Build Coastguard Worker return p;
161*7688df22SAndroid Build Coastguard Worker }
162*7688df22SAndroid Build Coastguard Worker
mmAllocMem(struct mem_block * heap,int size,int align2,int startSearch)163*7688df22SAndroid Build Coastguard Worker drm_private struct mem_block *mmAllocMem(struct mem_block *heap, int size,
164*7688df22SAndroid Build Coastguard Worker int align2, int startSearch)
165*7688df22SAndroid Build Coastguard Worker {
166*7688df22SAndroid Build Coastguard Worker struct mem_block *p;
167*7688df22SAndroid Build Coastguard Worker const int mask = (1 << align2) - 1;
168*7688df22SAndroid Build Coastguard Worker int startofs = 0;
169*7688df22SAndroid Build Coastguard Worker int endofs;
170*7688df22SAndroid Build Coastguard Worker
171*7688df22SAndroid Build Coastguard Worker if (!heap || align2 < 0 || size <= 0)
172*7688df22SAndroid Build Coastguard Worker return NULL;
173*7688df22SAndroid Build Coastguard Worker
174*7688df22SAndroid Build Coastguard Worker for (p = heap->next_free; p != heap; p = p->next_free) {
175*7688df22SAndroid Build Coastguard Worker assert(p->free);
176*7688df22SAndroid Build Coastguard Worker
177*7688df22SAndroid Build Coastguard Worker startofs = (p->ofs + mask) & ~mask;
178*7688df22SAndroid Build Coastguard Worker if (startofs < startSearch) {
179*7688df22SAndroid Build Coastguard Worker startofs = startSearch;
180*7688df22SAndroid Build Coastguard Worker }
181*7688df22SAndroid Build Coastguard Worker endofs = startofs + size;
182*7688df22SAndroid Build Coastguard Worker if (endofs <= (p->ofs + p->size))
183*7688df22SAndroid Build Coastguard Worker break;
184*7688df22SAndroid Build Coastguard Worker }
185*7688df22SAndroid Build Coastguard Worker
186*7688df22SAndroid Build Coastguard Worker if (p == heap)
187*7688df22SAndroid Build Coastguard Worker return NULL;
188*7688df22SAndroid Build Coastguard Worker
189*7688df22SAndroid Build Coastguard Worker assert(p->free);
190*7688df22SAndroid Build Coastguard Worker p = SliceBlock(p, startofs, size, 0, mask + 1);
191*7688df22SAndroid Build Coastguard Worker
192*7688df22SAndroid Build Coastguard Worker return p;
193*7688df22SAndroid Build Coastguard Worker }
194*7688df22SAndroid Build Coastguard Worker
Join2Blocks(struct mem_block * p)195*7688df22SAndroid Build Coastguard Worker static int Join2Blocks(struct mem_block *p)
196*7688df22SAndroid Build Coastguard Worker {
197*7688df22SAndroid Build Coastguard Worker /* XXX there should be some assertions here */
198*7688df22SAndroid Build Coastguard Worker
199*7688df22SAndroid Build Coastguard Worker /* NOTE: heap->free == 0 */
200*7688df22SAndroid Build Coastguard Worker
201*7688df22SAndroid Build Coastguard Worker if (p->free && p->next->free) {
202*7688df22SAndroid Build Coastguard Worker struct mem_block *q = p->next;
203*7688df22SAndroid Build Coastguard Worker
204*7688df22SAndroid Build Coastguard Worker assert(p->ofs + p->size == q->ofs);
205*7688df22SAndroid Build Coastguard Worker p->size += q->size;
206*7688df22SAndroid Build Coastguard Worker
207*7688df22SAndroid Build Coastguard Worker p->next = q->next;
208*7688df22SAndroid Build Coastguard Worker q->next->prev = p;
209*7688df22SAndroid Build Coastguard Worker
210*7688df22SAndroid Build Coastguard Worker q->next_free->prev_free = q->prev_free;
211*7688df22SAndroid Build Coastguard Worker q->prev_free->next_free = q->next_free;
212*7688df22SAndroid Build Coastguard Worker
213*7688df22SAndroid Build Coastguard Worker free(q);
214*7688df22SAndroid Build Coastguard Worker return 1;
215*7688df22SAndroid Build Coastguard Worker }
216*7688df22SAndroid Build Coastguard Worker return 0;
217*7688df22SAndroid Build Coastguard Worker }
218*7688df22SAndroid Build Coastguard Worker
mmFreeMem(struct mem_block * b)219*7688df22SAndroid Build Coastguard Worker drm_private int mmFreeMem(struct mem_block *b)
220*7688df22SAndroid Build Coastguard Worker {
221*7688df22SAndroid Build Coastguard Worker if (!b)
222*7688df22SAndroid Build Coastguard Worker return 0;
223*7688df22SAndroid Build Coastguard Worker
224*7688df22SAndroid Build Coastguard Worker if (b->free) {
225*7688df22SAndroid Build Coastguard Worker drmMsg("block already free\n");
226*7688df22SAndroid Build Coastguard Worker return -1;
227*7688df22SAndroid Build Coastguard Worker }
228*7688df22SAndroid Build Coastguard Worker if (b->reserved) {
229*7688df22SAndroid Build Coastguard Worker drmMsg("block is reserved\n");
230*7688df22SAndroid Build Coastguard Worker return -1;
231*7688df22SAndroid Build Coastguard Worker }
232*7688df22SAndroid Build Coastguard Worker
233*7688df22SAndroid Build Coastguard Worker b->free = 1;
234*7688df22SAndroid Build Coastguard Worker b->next_free = b->heap->next_free;
235*7688df22SAndroid Build Coastguard Worker b->prev_free = b->heap;
236*7688df22SAndroid Build Coastguard Worker b->next_free->prev_free = b;
237*7688df22SAndroid Build Coastguard Worker b->prev_free->next_free = b;
238*7688df22SAndroid Build Coastguard Worker
239*7688df22SAndroid Build Coastguard Worker Join2Blocks(b);
240*7688df22SAndroid Build Coastguard Worker if (b->prev != b->heap)
241*7688df22SAndroid Build Coastguard Worker Join2Blocks(b->prev);
242*7688df22SAndroid Build Coastguard Worker
243*7688df22SAndroid Build Coastguard Worker return 0;
244*7688df22SAndroid Build Coastguard Worker }
245*7688df22SAndroid Build Coastguard Worker
mmDestroy(struct mem_block * heap)246*7688df22SAndroid Build Coastguard Worker drm_private void mmDestroy(struct mem_block *heap)
247*7688df22SAndroid Build Coastguard Worker {
248*7688df22SAndroid Build Coastguard Worker struct mem_block *p;
249*7688df22SAndroid Build Coastguard Worker
250*7688df22SAndroid Build Coastguard Worker if (!heap)
251*7688df22SAndroid Build Coastguard Worker return;
252*7688df22SAndroid Build Coastguard Worker
253*7688df22SAndroid Build Coastguard Worker for (p = heap->next; p != heap;) {
254*7688df22SAndroid Build Coastguard Worker struct mem_block *next = p->next;
255*7688df22SAndroid Build Coastguard Worker free(p);
256*7688df22SAndroid Build Coastguard Worker p = next;
257*7688df22SAndroid Build Coastguard Worker }
258*7688df22SAndroid Build Coastguard Worker
259*7688df22SAndroid Build Coastguard Worker free(heap);
260*7688df22SAndroid Build Coastguard Worker }
261