1af69d88dSmrg/* 2af69d88dSmrg * Copyright 2007 Nouveau Project 3af69d88dSmrg * 4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 6af69d88dSmrg * to deal in the Software without restriction, including without limitation 7af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 10af69d88dSmrg * 11af69d88dSmrg * The above copyright notice and this permission notice shall be included in 12af69d88dSmrg * all copies or substantial portions of the Software. 13af69d88dSmrg * 14af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 21af69d88dSmrg */ 22af69d88dSmrg 23af69d88dSmrg#include <stdlib.h> 24af69d88dSmrg#include <errno.h> 25af69d88dSmrg 26af69d88dSmrg#include "nouveau_heap.h" 27af69d88dSmrg 28af69d88dSmrgint 29af69d88dSmrgnouveau_heap_init(struct nouveau_heap **heap, 30af69d88dSmrg unsigned start, unsigned size) 31af69d88dSmrg{ 3201e04c3fSmrg struct nouveau_heap *r; 33af69d88dSmrg 3401e04c3fSmrg r = calloc(1, sizeof(struct nouveau_heap)); 3501e04c3fSmrg if (!r) 3601e04c3fSmrg return 1; 37af69d88dSmrg 3801e04c3fSmrg r->start = start; 3901e04c3fSmrg r->size = size; 4001e04c3fSmrg *heap = r; 4101e04c3fSmrg return 0; 42af69d88dSmrg} 43af69d88dSmrg 44af69d88dSmrgvoid 45af69d88dSmrgnouveau_heap_destroy(struct nouveau_heap **heap) 46af69d88dSmrg{ 4701e04c3fSmrg if (!*heap) 4801e04c3fSmrg return; 4901e04c3fSmrg free(*heap); 5001e04c3fSmrg *heap = NULL; 51af69d88dSmrg} 52af69d88dSmrg 53af69d88dSmrgint 54af69d88dSmrgnouveau_heap_alloc(struct nouveau_heap *heap, unsigned size, void *priv, 55af69d88dSmrg struct nouveau_heap **res) 56af69d88dSmrg{ 5701e04c3fSmrg struct nouveau_heap *r; 58af69d88dSmrg 5901e04c3fSmrg if (!heap || !size || !res || *res) 6001e04c3fSmrg return 1; 61af69d88dSmrg 6201e04c3fSmrg while (heap) { 6301e04c3fSmrg if (!heap->in_use && heap->size >= size) { 6401e04c3fSmrg r = calloc(1, sizeof(struct nouveau_heap)); 6501e04c3fSmrg if (!r) 6601e04c3fSmrg return 1; 67af69d88dSmrg 6801e04c3fSmrg r->start = (heap->start + heap->size) - size; 6901e04c3fSmrg r->size = size; 7001e04c3fSmrg r->in_use = 1; 7101e04c3fSmrg r->priv = priv; 72af69d88dSmrg 7301e04c3fSmrg heap->size -= size; 74af69d88dSmrg 7501e04c3fSmrg r->next = heap->next; 7601e04c3fSmrg if (heap->next) 7701e04c3fSmrg heap->next->prev = r; 7801e04c3fSmrg r->prev = heap; 7901e04c3fSmrg heap->next = r; 80af69d88dSmrg 8101e04c3fSmrg *res = r; 8201e04c3fSmrg return 0; 8301e04c3fSmrg } 84af69d88dSmrg 8501e04c3fSmrg heap = heap->next; 8601e04c3fSmrg } 87af69d88dSmrg 8801e04c3fSmrg return 1; 89af69d88dSmrg} 90af69d88dSmrg 91af69d88dSmrgvoid 92af69d88dSmrgnouveau_heap_free(struct nouveau_heap **res) 93af69d88dSmrg{ 9401e04c3fSmrg struct nouveau_heap *r; 9501e04c3fSmrg 9601e04c3fSmrg if (!res || !*res) 9701e04c3fSmrg return; 9801e04c3fSmrg r = *res; 9901e04c3fSmrg *res = NULL; 10001e04c3fSmrg 10101e04c3fSmrg r->in_use = 0; 10201e04c3fSmrg 10301e04c3fSmrg if (r->next && !r->next->in_use) { 10401e04c3fSmrg struct nouveau_heap *new = r->next; 10501e04c3fSmrg 10601e04c3fSmrg new->prev = r->prev; 10701e04c3fSmrg if (r->prev) 10801e04c3fSmrg r->prev->next = new; 10901e04c3fSmrg new->size += r->size; 11001e04c3fSmrg new->start = r->start; 11101e04c3fSmrg 11201e04c3fSmrg free(r); 11301e04c3fSmrg r = new; 11401e04c3fSmrg } 11501e04c3fSmrg 11601e04c3fSmrg if (r->prev && !r->prev->in_use) { 11701e04c3fSmrg r->prev->next = r->next; 11801e04c3fSmrg if (r->next) 11901e04c3fSmrg r->next->prev = r->prev; 12001e04c3fSmrg r->prev->size += r->size; 12101e04c3fSmrg free(r); 12201e04c3fSmrg } 123af69d88dSmrg} 124