271 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|     Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
 | |
| 
 | |
|     Redistribution and use in source and binary forms, with or without
 | |
|     modification, are permitted provided that the following conditions
 | |
|     are met:
 | |
|     1. Redistributions of source code must retain the above copyright
 | |
|        notice, this list of conditions and the following disclaimer.
 | |
|     2. Redistributions in binary form must reproduce the above copyright
 | |
|        notice, this list of conditions and the following disclaimer in the
 | |
|        documentation and/or other materials provided with the distribution.
 | |
| 
 | |
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 | |
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | |
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | |
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | |
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | |
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| /* THIS FILE IS SUPPOSED TO BE INCLUDED BY MODULE SOURCE THAT MAINTAINS MAPPING BETWEEN ID AND DATA */
 | |
| 
 | |
| typedef struct __IDMAP_NODE_T __IDMAP_NODE_T;
 | |
| struct __IDMAP_NODE_T
 | |
| {
 | |
| 	__IDMAP_NODE_T* prev;
 | |
| 	__IDMAP_NODE_T* next;
 | |
| 	int id;
 | |
| 
 | |
| 	__IDMAP_NODE_T_DATA
 | |
| };
 | |
| 
 | |
| typedef struct __IDMAP_LIST_T __IDMAP_LIST_T;
 | |
| struct __IDMAP_LIST_T
 | |
| {
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 	__IDMAP_NODE_T* head;
 | |
| 	__IDMAP_NODE_T* tail;
 | |
| 	__IDMAP_NODE_T* free;
 | |
| #else
 | |
| 	struct
 | |
| 	{
 | |
| 		__IDMAP_NODE_T* prev;
 | |
| 		__IDMAP_NODE_T* next;
 | |
| 	} used;
 | |
| 	struct
 | |
| 	{
 | |
| 		__IDMAP_NODE_T* prev;
 | |
| 		__IDMAP_NODE_T* next;
 | |
| 	} free;
 | |
| #endif
 | |
| 
 | |
| 	/* mapping table to map 'id' to 'node' */
 | |
| 	struct
 | |
| 	{
 | |
| 		__IDMAP_NODE_T** tab;
 | |
| 		int capa;
 | |
| 		int high;
 | |
| 	} map;
 | |
| 
 | |
| 	__IDMAP_LIST_T_DATA
 | |
| };
 | |
| 
 | |
| 
 | |
| static __IDMAP_NODE_T* __MAKE_IDMAP_NODE (hawk_rtx_t* rtx, __IDMAP_LIST_T* list)
 | |
| {
 | |
| 	/* create a new context node and append it to the list tail */
 | |
| 	__IDMAP_NODE_T* node;
 | |
| 
 | |
| 	node = HAWK_NULL;
 | |
| 
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 	if (list->free)
 | |
| 	{
 | |
| 		node = list->free;
 | |
| 		list->free = node->next;
 | |
| 	}
 | |
| #else
 | |
| 	if (list->free.next != (__IDMAP_NODE_T*)&list->free)
 | |
| 	{
 | |
| 		/* remove a node from a free list */
 | |
| 		node = list->free.next;
 | |
| 		node->prev->next = node->next;
 | |
| 		node->next->prev = node->prev;
 | |
| 	}
 | |
| #endif
 | |
| 	else
 | |
| 	{
 | |
| 		node = hawk_rtx_callocmem(rtx, HAWK_SIZEOF(*node));
 | |
| 		if (!node) goto oops;
 | |
| 
 | |
| 		if (list->map.high <= list->map.capa)
 | |
| 		{
 | |
| 			hawk_oow_t newcapa, inc;
 | |
| 			__IDMAP_NODE_T** tmp;
 | |
| 
 | |
| 			inc = HAWK_TYPE_MAX(int) - list->map.capa;
 | |
| 			if (inc == 0) goto oops; /* too many nodes */
 | |
| 
 | |
| 			if (inc > 64) inc = 64;
 | |
| 			newcapa = (hawk_oow_t)list->map.capa + inc;
 | |
| 
 | |
| 			tmp = (__IDMAP_NODE_T**)hawk_rtx_reallocmem(rtx, list->map.tab, HAWK_SIZEOF(*tmp) * newcapa);
 | |
| 			if (!tmp) goto oops;
 | |
| 
 | |
| 			HAWK_MEMSET (&tmp[list->map.capa], 0, HAWK_SIZEOF(*tmp) * (newcapa - list->map.capa));
 | |
| 
 | |
| 			list->map.tab = tmp;
 | |
| 			list->map.capa = newcapa;
 | |
| 		}
 | |
| 
 | |
| 		node->id = list->map.high;
 | |
| 		list->map.high++;
 | |
| 	}
 | |
| 
 | |
| 	HAWK_ASSERT (list->map.tab[node->id] == HAWK_NULL);
 | |
| 	list->map.tab[node->id] = node;
 | |
| 
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 	/* append it to the tail */
 | |
| 	node->next = HAWK_NULL;
 | |
| 	node->prev = list->tail;
 | |
| 	if (list->tail) list->tail->next = node;
 | |
| 	else list->head = node;
 | |
| 	list->tail = node;
 | |
| #else
 | |
| 	/* append it */
 | |
| 	node->next = (__IDMAP_NODE_T*)&list->used;
 | |
| 	node->prev = list->used.prev;
 | |
| 	node->prev->next = node;
 | |
| 	list->used.prev = node;
 | |
| #endif
 | |
| 
 | |
| 	return node;
 | |
| 
 | |
| oops:
 | |
| 	if (node) hawk_rtx_freemem (rtx, node);
 | |
| 	return HAWK_NULL;
 | |
| }
 | |
| 
 | |
| static void __FREE_IDMAP_NODE (hawk_rtx_t* rtx, __IDMAP_LIST_T* list, __IDMAP_NODE_T* node)
 | |
| {
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 	if (node->prev) node->prev->next = node->next;
 | |
| 	if (node->next) node->next->prev = node->prev;
 | |
| 	if (list->head == node) list->head = node->next;
 | |
| 	if (list->tail == node) list->tail = node->prev;
 | |
| #else
 | |
| 	node->prev->next = node->next;
 | |
| 	node->next->prev = node->prev;
 | |
| #endif
 | |
| 
 | |
| 	list->map.tab[node->id] = HAWK_NULL;
 | |
| 
 | |
| 	if (list->map.high == node->id + 1)
 | |
| 	{
 | |
| 		/* destroy the actual node if the node to be freed has the
 | |
| 		 * highest id */
 | |
| 		hawk_rtx_freemem (rtx, node);
 | |
| 		list->map.high--;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		/* otherwise, chain the node to the free list */
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 		node->next = list->free;
 | |
| 		list->free = node;
 | |
| #else
 | |
| 		node->next = (__IDMAP_NODE_T*)&list->free;
 | |
| 		node->prev = list->free.prev;
 | |
| 		node->prev->next = node;
 | |
| 		list->free.prev = node;
 | |
| #endif
 | |
| 	}
 | |
| 
 | |
| 	/* however, i destroy the whole free list when all the nodes are
 | |
| 	 * chanined to the free list */
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 	if (list->head == HAWK_NULL)
 | |
| 	{
 | |
| 		__IDMAP_NODE_T* curnode;
 | |
| 
 | |
| 		while (list->free)
 | |
| 		{
 | |
| 			curnode = list->free;
 | |
| 			list->free = list->free->next;
 | |
| 			hawk_rtx_freemem (rtx, curnode);
 | |
| 		}
 | |
| 
 | |
| 		hawk_rtx_freemem (rtx, list->map.tab);
 | |
| 		list->map.high = 0;
 | |
| 		list->map.capa = 0;
 | |
| 		list->map.tab = HAWK_NULL;
 | |
| 	}
 | |
| #else
 | |
| 	if (list->used.next == (__IDMAP_NODE_T*)&list->used)
 | |
| 	{
 | |
| 		__IDMAP_NODE_T* node;
 | |
| 
 | |
| 		while (list->free.next != (__IDMAP_NODE_T*)&list->free)
 | |
| 		{
 | |
| 			node = list->free.next;
 | |
| 			node->prev->next = node->next;
 | |
| 			node->next->prev = node->prev;
 | |
| 			hawk_rtx_freemem (rtx, node);
 | |
| 		}
 | |
| 
 | |
| 		hawk_rtx_freemem (rtx, list->map.tab);
 | |
| 		list->map.high = 0;
 | |
| 		list->map.capa = 0;
 | |
| 		list->map.tab = HAWK_NULL;
 | |
| 	}
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static void __INIT_IDMAP_LIST (hawk_rtx_t* rtx, __IDMAP_LIST_T* list)
 | |
| {
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 	/* nothing */
 | |
| #else
 | |
| 	list->used.next = (__IDMAP_NODE_T*)&list->used;
 | |
| 	list->used.prev = (__IDMAP_NODE_T*)&list->used;
 | |
| 	list->free.next = (__IDMAP_NODE_T*)&list->free;
 | |
| 	list->free.prev = (__IDMAP_NODE_T*)&list->free;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static void __FINI_IDMAP_LIST (hawk_rtx_t* rtx, __IDMAP_LIST_T* list)
 | |
| {
 | |
| #if defined(__IDMAP_AVOID_CIRCULAR_LIST)
 | |
| 	__IDMAP_NODE_T* node, * next;
 | |
| 	node = data->list->head;
 | |
| 	while (node)
 | |
| 	{
 | |
| 		next = node->next;
 | |
| 		__FREE_IDMAP_NODE (rtx, list, node);
 | |
| 		node = next;
 | |
| 	}
 | |
| 
 | |
| 	node = data->list->free;
 | |
| 	while (node)
 | |
| 	{
 | |
| 		next = node->next;
 | |
| 		__FREE_IDMAP_NODE (rtx, list, node);
 | |
| 		node = next;
 | |
| 	}
 | |
| #else
 | |
| 	__IDMAP_NODE_T* node;
 | |
| 
 | |
| 	while (list->used.next != (__IDMAP_NODE_T*)&list->used)
 | |
| 	{
 | |
| 		node = list->used.next;
 | |
| 		node->prev->next = node->next;
 | |
| 		node->next->prev = node->prev;
 | |
| 		__FREE_IDMAP_NODE (rtx, list, node);
 | |
| 	}
 | |
| 
 | |
| 	while (list->free.next != (__IDMAP_NODE_T*)&list->free)
 | |
| 	{
 | |
| 		node = list->free.next;
 | |
| 		node->prev->next = node->next;
 | |
| 		node->next->prev = node->prev;
 | |
| 		__FREE_IDMAP_NODE (rtx, list, node);
 | |
| 	}
 | |
| #endif
 | |
| }
 |