Back to index

libdrm  2.4.37
mm.c
Go to the documentation of this file.
00001 /*
00002  * GLX Hardware Device Driver common code
00003  * Copyright (C) 1999 Wittawat Yamwong
00004  *
00005  * Permission is hereby granted, free of charge, to any person obtaining a
00006  * copy of this software and associated documentation files (the "Software"),
00007  * to deal in the Software without restriction, including without limitation
00008  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00009  * and/or sell copies of the Software, and to permit persons to whom the
00010  * Software is furnished to do so, subject to the following conditions:
00011  *
00012  * The above copyright notice and this permission notice shall be included
00013  * in all copies or substantial portions of the Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018  * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
00021  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022  *
00023  */
00024 
00025 #include <stdlib.h>
00026 #include <assert.h>
00027 
00028 #include "xf86drm.h"
00029 #include "mm.h"
00030 
00031 void mmDumpMemInfo(const struct mem_block *heap)
00032 {
00033        drmMsg("Memory heap %p:\n", (void *)heap);
00034        if (heap == 0) {
00035               drmMsg("  heap == 0\n");
00036        } else {
00037               const struct mem_block *p;
00038 
00039               for (p = heap->next; p != heap; p = p->next) {
00040                      drmMsg("  Offset:%08x, Size:%08x, %c%c\n", p->ofs,
00041                             p->size, p->free ? 'F' : '.',
00042                             p->reserved ? 'R' : '.');
00043               }
00044 
00045               drmMsg("\nFree list:\n");
00046 
00047               for (p = heap->next_free; p != heap; p = p->next_free) {
00048                      drmMsg(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs,
00049                             p->size, p->free ? 'F' : '.',
00050                             p->reserved ? 'R' : '.');
00051               }
00052 
00053        }
00054        drmMsg("End of memory blocks\n");
00055 }
00056 
00057 struct mem_block *mmInit(int ofs, int size)
00058 {
00059        struct mem_block *heap, *block;
00060 
00061        if (size <= 0)
00062               return NULL;
00063 
00064        heap = (struct mem_block *)calloc(1, sizeof(struct mem_block));
00065        if (!heap)
00066               return NULL;
00067 
00068        block = (struct mem_block *)calloc(1, sizeof(struct mem_block));
00069        if (!block) {
00070               free(heap);
00071               return NULL;
00072        }
00073 
00074        heap->next = block;
00075        heap->prev = block;
00076        heap->next_free = block;
00077        heap->prev_free = block;
00078 
00079        block->heap = heap;
00080        block->next = heap;
00081        block->prev = heap;
00082        block->next_free = heap;
00083        block->prev_free = heap;
00084 
00085        block->ofs = ofs;
00086        block->size = size;
00087        block->free = 1;
00088 
00089        return heap;
00090 }
00091 
00092 static struct mem_block *SliceBlock(struct mem_block *p,
00093                                 int startofs, int size,
00094                                 int reserved, int alignment)
00095 {
00096        struct mem_block *newblock;
00097 
00098        /* break left  [p, newblock, p->next], then p = newblock */
00099        if (startofs > p->ofs) {
00100               newblock =
00101                   (struct mem_block *)calloc(1, sizeof(struct mem_block));
00102               if (!newblock)
00103                      return NULL;
00104               newblock->ofs = startofs;
00105               newblock->size = p->size - (startofs - p->ofs);
00106               newblock->free = 1;
00107               newblock->heap = p->heap;
00108 
00109               newblock->next = p->next;
00110               newblock->prev = p;
00111               p->next->prev = newblock;
00112               p->next = newblock;
00113 
00114               newblock->next_free = p->next_free;
00115               newblock->prev_free = p;
00116               p->next_free->prev_free = newblock;
00117               p->next_free = newblock;
00118 
00119               p->size -= newblock->size;
00120               p = newblock;
00121        }
00122 
00123        /* break right, also [p, newblock, p->next] */
00124        if (size < p->size) {
00125               newblock =
00126                   (struct mem_block *)calloc(1, sizeof(struct mem_block));
00127               if (!newblock)
00128                      return NULL;
00129               newblock->ofs = startofs + size;
00130               newblock->size = p->size - size;
00131               newblock->free = 1;
00132               newblock->heap = p->heap;
00133 
00134               newblock->next = p->next;
00135               newblock->prev = p;
00136               p->next->prev = newblock;
00137               p->next = newblock;
00138 
00139               newblock->next_free = p->next_free;
00140               newblock->prev_free = p;
00141               p->next_free->prev_free = newblock;
00142               p->next_free = newblock;
00143 
00144               p->size = size;
00145        }
00146 
00147        /* p = middle block */
00148        p->free = 0;
00149 
00150        /* Remove p from the free list: 
00151         */
00152        p->next_free->prev_free = p->prev_free;
00153        p->prev_free->next_free = p->next_free;
00154 
00155        p->next_free = 0;
00156        p->prev_free = 0;
00157 
00158        p->reserved = reserved;
00159        return p;
00160 }
00161 
00162 struct mem_block *mmAllocMem(struct mem_block *heap, int size, int align2,
00163                           int startSearch)
00164 {
00165        struct mem_block *p;
00166        const int mask = (1 << align2) - 1;
00167        int startofs = 0;
00168        int endofs;
00169 
00170        if (!heap || align2 < 0 || size <= 0)
00171               return NULL;
00172 
00173        for (p = heap->next_free; p != heap; p = p->next_free) {
00174               assert(p->free);
00175 
00176               startofs = (p->ofs + mask) & ~mask;
00177               if (startofs < startSearch) {
00178                      startofs = startSearch;
00179               }
00180               endofs = startofs + size;
00181               if (endofs <= (p->ofs + p->size))
00182                      break;
00183        }
00184 
00185        if (p == heap)
00186               return NULL;
00187 
00188        assert(p->free);
00189        p = SliceBlock(p, startofs, size, 0, mask + 1);
00190 
00191        return p;
00192 }
00193 
00194 struct mem_block *mmFindBlock(struct mem_block *heap, int start)
00195 {
00196        struct mem_block *p;
00197 
00198        for (p = heap->next; p != heap; p = p->next) {
00199               if (p->ofs == start)
00200                      return p;
00201        }
00202 
00203        return NULL;
00204 }
00205 
00206 static int Join2Blocks(struct mem_block *p)
00207 {
00208        /* XXX there should be some assertions here */
00209 
00210        /* NOTE: heap->free == 0 */
00211 
00212        if (p->free && p->next->free) {
00213               struct mem_block *q = p->next;
00214 
00215               assert(p->ofs + p->size == q->ofs);
00216               p->size += q->size;
00217 
00218               p->next = q->next;
00219               q->next->prev = p;
00220 
00221               q->next_free->prev_free = q->prev_free;
00222               q->prev_free->next_free = q->next_free;
00223 
00224               free(q);
00225               return 1;
00226        }
00227        return 0;
00228 }
00229 
00230 int mmFreeMem(struct mem_block *b)
00231 {
00232        if (!b)
00233               return 0;
00234 
00235        if (b->free) {
00236               drmMsg("block already free\n");
00237               return -1;
00238        }
00239        if (b->reserved) {
00240               drmMsg("block is reserved\n");
00241               return -1;
00242        }
00243 
00244        b->free = 1;
00245        b->next_free = b->heap->next_free;
00246        b->prev_free = b->heap;
00247        b->next_free->prev_free = b;
00248        b->prev_free->next_free = b;
00249 
00250        Join2Blocks(b);
00251        if (b->prev != b->heap)
00252               Join2Blocks(b->prev);
00253 
00254        return 0;
00255 }
00256 
00257 void mmDestroy(struct mem_block *heap)
00258 {
00259        struct mem_block *p;
00260 
00261        if (!heap)
00262               return;
00263 
00264        for (p = heap->next; p != heap;) {
00265               struct mem_block *next = p->next;
00266               free(p);
00267               p = next;
00268        }
00269 
00270        free(heap);
00271 }