⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 heap.c

📁 COS 0.0.1.rar Cos操作系统源代码
💻 C
字号:
/* heap.c - allocation thru a heap   Author:	Paul Barker Part of:	COS Created:	01/09/04 Last Modified:	16/10/04 Copyright (C) 2004 Paul Barker        This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                     (See file "Copying")*/#include <cosbase.h>#include <cos/debug.h>#include <cos/page.h>#include <cos/mem.h>#include <cos/heap.h>#define SIZE_OF_NODE(n) ((n->end - (iptr_t)n) - sizeof(heap_node_t))// minimum allocation size#define QUANTUM		8#define QUANTUM_MASK	(~(QUANTUM - 1))// given ptr must already be alloc'd, of at least size init_size// I suggest that the type PG_CLUSTER_HEAP is *always* used for heaps.heap_t* heap_create(size_t init_size, ptr_t start){	TRACE(("Creating Heap\n"));	// handle no given pointer	if (start == 0)	{		TRACE(("Was not given a pointer,"));		// handle 0 initial size		if (init_size == 0)			init_size = PAGE_SIZE;				init_size = (init_size & PAGE_MASK) +			     ((init_size & ~PAGE_MASK) ? 4096 : 0);				TRACE((" will allocate %d (0x%x) bytes\n",			init_size, init_size));				start = phys_alloc(init_size / PAGE_SIZE, PG_CLUSTER_HEAP,				   PG_CLUSTER_FREE);	}		if (init_size == 0)		return 0;	// invalid if start given		TRACE(("Using pointer 0x%x\n", start));		memzero(start, init_size);		heap_t* h = (heap_t*)start;	iptr_t p = (iptr_t)start;		// need to do addition below		h->end = p + init_size;	h->first_free = (heap_node_t*)(p + sizeof(heap_t));		heap_node_t* node = h->first_free;	node->flags = HEAP_FREE;	node->end = h->end;		TRACE(("Done\n"));		return h;}// add free nodevoid heap_add_free(heap_t* heap, heap_node_t* p){	TRACE(("Adding free node at 0x%x to heap at 0x%x\n", p, heap));	p->flags |= HEAP_FREE;		// first find end of free list	heap_node_t* free = heap->first_free;		TRACE(("First free node at 0x%x\n", free));		if (free == NULL)	{		heap->first_free = p;		return;	}		while (free->next)	{		free = free->next;		TRACE(("Moving to next free node at 0x%x\n", free));	}		// now set the next free to the given node	free->next = p;		TRACE(("Done\n"));}// allocate from a heapptr_t heap_alloc(heap_t* heap, size_t sz){	heap_node_t* node = heap->first_free;	u32_t s = 0;	count_t n = 0;		sz &= QUANTUM_MASK;		TRACE(("Allocating memory of size %d (0x%x) bytes\n", sz, sz));	TRACE(("from heap at 0x%x, first free is at 0x%x\n", heap, node));		while (node)	{		s = SIZE_OF_NODE(node);		TRACE(("Loop (%d): Node of size %d (0x%x) bytes\n", n, s, s));		TRACE(("\tstart=0x%x, end=0x%x\n",			((iptr_t)node) + sizeof(heap_node_t), node->end));		if ((s >= sz) && (node->flags & HEAP_FREE))			goto finish;		node = node->next;		TRACE(("\tMoving to next node at 0x%x\n", node));		++n;	}		TRACE(("Not enough free memory!\n"));		// could not find a node big enough	return NULL;	finish:	TRACE(("Found a node large enough\n"));		iptr_t i = (iptr_t)node;		// cut out a new node if possible	if (s >= (sz + sizeof(heap_node_t) + QUANTUM))	{		heap_node_t* new_node = (heap_node_t*)					(i + sizeof(heap_node_t) + sz);		TRACE(("Splitting a free node at 0x%x\n", new_node));				new_node->end = node->end;		node->end = (iptr_t)new_node;		heap_add_free(heap, new_node);	}		node->flags &= ~HEAP_FREE;		iptr_t ret = i + sizeof(heap_node_t);	TRACE(("Returning pointer 0x%x\n", ret));	return (ptr_t)ret;}// free previously allocated memoryvoid heap_free(heap_t* heap, ptr_t p){	TRACE(("Freeing memory at 0x%x from heap at 0x%x\n", p, heap));	// mark the node as free	iptr_t i = (iptr_t)p;	heap_node_t* node = (heap_node_t*)(i - sizeof(heap_node_t));		node->flags |= HEAP_FREE;		TRACE(("\tnode at 0x%x, end at 0x%x\n", node, node->end));		count_t sz = SIZE_OF_NODE(node);	TRACE(("\tmeaning size is %d (0x%x) bytes\n", sz, sz));}/*  TODO:	Support best fit allocation.	Use phys_alloc() to fulfil requests for more memory than is free in		the requested heap.	Support requesting alignment.	Compaction of a heap (meaning remove unused pages).	Validation function.	In heap_free(), we must condense adjacent free nodes into a single		node.	Add mutexes.	heap_destroy().*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -