16d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller/* 26d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * Copyright 2007 Nouveau Project 36d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * 46d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * Permission is hereby granted, free of charge, to any person obtaining a 56d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * copy of this software and associated documentation files (the "Software"), 66d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * to deal in the Software without restriction, including without limitation 76d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * and/or sell copies of the Software, and to permit persons to whom the 96d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * Software is furnished to do so, subject to the following conditions: 106d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * 116d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * The above copyright notice and this permission notice shall be included in 126d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * all copies or substantial portions of the Software. 136d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * 146d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 156d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 166d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 176d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 186d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 196d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 206d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller * SOFTWARE. 216d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller */ 226d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 236d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller#include <stdlib.h> 246d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller#include <errno.h> 256d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 266d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller#include "nouveau_heap.h" 276d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 286d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillerint 296d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillernouveau_heap_init(struct nouveau_heap **heap, 306d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller unsigned start, unsigned size) 316d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller{ 326d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller struct nouveau_heap *r; 336d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 346d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r = calloc(1, sizeof(struct nouveau_heap)); 356d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (!r) 366d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return 1; 376d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 386d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->start = start; 396d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->size = size; 406d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller *heap = r; 416d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return 0; 426d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller} 436d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 446d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillervoid 456d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillernouveau_heap_destroy(struct nouveau_heap **heap) 466d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller{ 476d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (!*heap) 486d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return; 496d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller free(*heap); 506d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller *heap = NULL; 516d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller} 526d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 536d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillerint 546d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillernouveau_heap_alloc(struct nouveau_heap *heap, unsigned size, void *priv, 556d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller struct nouveau_heap **res) 566d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller{ 576d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller struct nouveau_heap *r; 586d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 596d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (!heap || !size || !res || *res) 606d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return 1; 616d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 626d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller while (heap) { 636d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (!heap->in_use && heap->size >= size) { 646d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r = calloc(1, sizeof(struct nouveau_heap)); 656d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (!r) 666d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return 1; 676d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 686d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->start = (heap->start + heap->size) - size; 696d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->size = size; 706d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->in_use = 1; 716d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->priv = priv; 726d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 736d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller heap->size -= size; 746d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 756d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->next = heap->next; 766d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (heap->next) 776d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller heap->next->prev = r; 786d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->prev = heap; 796d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller heap->next = r; 806d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 816d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller *res = r; 826d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return 0; 836d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller } 846d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 856d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller heap = heap->next; 866d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller } 876d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 886d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return 1; 896d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller} 906d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 916d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillervoid 926d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumillernouveau_heap_free(struct nouveau_heap **res) 936d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller{ 946d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller struct nouveau_heap *r; 956d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 966d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (!res || !*res) 976d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller return; 986d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r = *res; 996d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller *res = NULL; 1006d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 1016d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->in_use = 0; 1026d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 1036d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (r->next && !r->next->in_use) { 1046d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller struct nouveau_heap *new = r->next; 1056d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 1066d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller new->prev = r->prev; 1076d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (r->prev) 1086d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->prev->next = new; 1096d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller new->size += r->size; 1106d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller new->start = r->start; 1116d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 1126d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller free(r); 1136d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r = new; 1146d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller } 1156d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 1166d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (r->prev && !r->prev->in_use) { 1176d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->prev->next = r->next; 1186d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller if (r->next) 1196d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->next->prev = r->prev; 1206d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller r->prev->size += r->size; 1216d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller free(r); 1226d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller } 1236d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller} 124