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