📄 mempool.c.svn-base
字号:
/* * File : partition.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.fayfayspace.org/license/LICENSE. * * Change Logs: * Date Author Notes * 2006-05-27 Bernard implement memory pool * 2006-06-03 Bernard fix the thread timer init bug * 2006-06-30 Bernard fix the allocate/free block bug */#include <rthw.h>#include <rtthread.h>#include "kservice.h"#ifdef RT_USING_MEMPOOL/** * @addtogroup Kernel *//*@{*/rt_err_t rt_mp_init(struct rt_mempool* mp, const char* name, void *start, rt_size_t size, rt_size_t block_size){ rt_uint8 *block_ptr; register rt_base_t offset; /* parameter check */ RT_ASSERT(mp != RT_NULL); /* init object */ rt_object_init(&(mp->parent), RT_Object_Class_MemPool, name); /* init memory pool */ mp->start_address = start; mp->size = RT_ALIGN(size, RT_ALIGN_SIZE); mp->block_size = block_size; /* align to align size byte */ mp->block_total_count = mp->size / (mp->block_size + sizeof(rt_uint8*)); mp->block_free_count = mp->block_total_count; /* init suspended thread list */ rt_list_init(&(mp->suspend_thread)); mp->suspend_thread_count = 0; /* init free block list */ block_ptr = (rt_uint8*) mp->start_address; for (offset = 0; offset < mp->block_total_count; offset ++) { *(rt_uint8**)(block_ptr + offset * (block_size + sizeof(rt_uint8*))) = (rt_uint8*)(block_ptr + (offset + 1) * (block_size + sizeof(rt_uint8*))); } *(rt_uint8**)(block_ptr + offset * (block_size + sizeof(rt_uint8*))) = RT_NULL; mp->block_list = block_ptr; return RT_EOK;}rt_err_t rt_mp_detach(struct rt_mempool* mp){ struct rt_thread* thread; register rt_ubase_t temp; /* parameter check */ RT_ASSERT(mp != RT_NULL); /* wakeup all suspended threads */ while (!rt_list_isempty(&(mp->suspend_thread))) { /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* * resume thread * In rt_thread_resume function, it will remove current thread from suspend * list */ rt_thread_resume(thread); /* decrease suspended thread count */ mp->suspend_thread_count --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } /* detach object */ rt_object_detach(&(mp->parent)); return RT_EOK;}rt_mp_t rt_mp_create(void *mp_start, const char* name, rt_size_t block_count, rt_size_t block_size){ rt_uint8 *block_ptr; struct rt_mempool* mp; register rt_base_t offset; /* allocate object */ mp = (struct rt_mempool*)rt_object_allocate(RT_Object_Class_MemPool, name); /* init memory pool */ mp->block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE); mp->size = (block_size + sizeof(rt_uint8*))* block_count; /* allocate memory */ mp->start_address = rt_malloc((block_size + sizeof(rt_uint8*))* block_count); if (mp->start_address == RT_NULL) { /* no memory, delete memory pool object */ rt_object_delete(&(mp->parent)); return RT_NULL; } mp->block_total_count = block_count; mp->block_free_count = mp->block_total_count; /* init suspended thread list */ rt_list_init(&(mp->suspend_thread)); mp->suspend_thread_count = 0; /* init free block list */ block_ptr = (rt_uint8*) mp->start_address; for (offset = 0; offset < mp->block_total_count; offset ++) { *(rt_uint8**)(block_ptr + offset * (block_size + sizeof(rt_uint8*))) = block_ptr + (offset + 1) * (block_size + sizeof(rt_uint8*)); } *(rt_uint8**)(block_ptr + offset * (block_size + sizeof(rt_uint8*))) = RT_NULL; mp->block_list = block_ptr; return mp;}rt_err_t rt_mp_delete(rt_mp_t mp){ struct rt_thread* thread; register rt_ubase_t temp; /* parameter check */ RT_ASSERT(mp != RT_NULL); /* wakeup all suspended threads */ while (!rt_list_isempty(&(mp->suspend_thread))) { /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* * resume thread * In rt_thread_resume function, it will remove current thread from suspend * list */ rt_thread_resume(thread); /* decrease suspended thread count */ mp->suspend_thread_count --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } /* release allocated room */ rt_free(mp->start_address); /* detach object */ rt_object_delete(&(mp->parent)); return RT_EOK;}void *rt_mp_alloc (rt_mp_t mp, rt_int32 time){ rt_uint8* block_ptr; register rt_base_t level; struct rt_thread* thread; /* disable interrupt */ level = rt_hw_interrupt_disable(); if(mp->block_free_count) { /* memory block is available. decrease the free block counter */ mp->block_free_count--; /* get block from block list */ block_ptr = mp->block_list; mp->block_list = *(rt_uint8**)block_ptr; /* point to memory pool */ *(rt_uint8**)block_ptr = (rt_uint8*)mp; } else { /* memory block is unavailable. */ if (time == 0) return RT_NULL; else { /* get current thread */ thread = rt_thread_self(); /* need suspend thread */ rt_thread_suspend(thread); rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist)); mp->suspend_thread_count++; if (time > 0) { /* init thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ level = rt_hw_interrupt_disable(); /* do a schedule */ rt_schedule(); if (thread->error != RT_EOK) return RT_NULL; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* decrease free block */ mp->block_free_count --; /* get block from block list */ block_ptr = mp->block_list; mp->block_list = *(rt_uint8**)block_ptr; /* point to memory pool */ *(rt_uint8**)block_ptr = (rt_uint8*)mp; } } /* enable interrupt */ rt_hw_interrupt_enable(level); return (rt_uint8*)(block_ptr + sizeof(rt_uint8*));}void rt_mp_free (void *block){ rt_uint8 **block_ptr; struct rt_mempool *mp; struct rt_thread *thread; register rt_base_t level; /* get the control block of pool which the block belongs to */ block_ptr = (rt_uint8**)((rt_uint8*)block - sizeof(rt_uint8*)); mp = (struct rt_mempool*) *block_ptr; rt_kprintf("mp free: %s\n", mp->parent.name); /* disable interrupt */ level = rt_hw_interrupt_disable(); /* increase the free block count */ mp->block_free_count ++; /* link the block into the block list */ *block_ptr = mp->block_list; mp->block_list = (rt_uint8*)block_ptr; if (mp->suspend_thread_count > 0) { /* get the suspended thread */ thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist); /* set error */ thread->error = RT_EOK; /* resume thread */ rt_thread_resume(thread); /* decrease suspended thread count */ mp->suspend_thread_count --; /* enable interrupt */ rt_hw_interrupt_enable(level); /* do a schedule */ rt_schedule(); return; } /* enable interrupt */ rt_hw_interrupt_enable(level);}#endif/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -