/*
 * 程序清单：内存池例程
 *
 * 这个程序会创建一个静态的内存池对象，2个动态线程。两个线程会试图分别从内存池中获得
 * 内存块
 */
#include <rtthread.h>
#include "tc_comm.h"

static rt_uint8_t *ptr[48];
static rt_uint8_t mempool[4096];
static struct rt_mempool mp;

/* 指向线程控制块的指针 */
static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;

/* 线程1入口 */
static void thread1_entry(void* parameter)
{
	int i;
	char *block;

	while(1)
	{
		for (i = 0; i < 48; i++)
		{
			/* 申请内存块 */
			rt_kprintf("allocate No.%d\n", i);
			if (ptr[i] == RT_NULL)
			{
				ptr[i] = rt_mp_alloc(&mp, RT_WAITING_FOREVER);
			}
		}

		/* 继续申请一个内存块，因为已经没有内存块，线程应该被挂起 */
		block = rt_mp_alloc(&mp, RT_WAITING_FOREVER);
		rt_kprintf("allocate the block mem\n");
		/* 释放这个内存块 */
		rt_mp_free(block);
		block = RT_NULL;
	}
}

/* 线程2入口，线程2的优先级比线程1低，应该线程1先获得执行。*/
static void thread2_entry(void *parameter)
{
	int i;

	while(1)
	{
		rt_kprintf("try to release block\n");

		for (i = 0 ; i < 48; i ++)
		{
			/* 释放所有分配成功的内存块 */
			if (ptr[i] != RT_NULL)
			{
				rt_kprintf("release block %d\n", i);

				rt_mp_free(ptr[i]);
				ptr[i] = RT_NULL;
			}
		}

		/* 休眠10个OS Tick */
		rt_thread_delay(10);
	}
}

int mempool_simple_init()
{
	int i;
	for (i = 0; i < 48; i ++) ptr[i] = RT_NULL;

	/* 初始化内存池对象 */
	rt_mp_init(&mp, "mp1", &mempool[0], sizeof(mempool), 80);

	/* 创建线程1 */
	tid1 = rt_thread_create("t1",
		thread1_entry, RT_NULL, /* 线程入口是thread1_entry, 入口参数是RT_NULL */
		THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
	if (tid1 != RT_NULL)
		rt_thread_startup(tid1);
	else
		tc_stat(TC_STAT_END | TC_STAT_FAILED);

	/* 创建线程2 */
	tid2 = rt_thread_create("t2",
		thread2_entry, RT_NULL, /* 线程入口是thread2_entry, 入口参数是RT_NULL */
		THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
	if (tid2 != RT_NULL)
		rt_thread_startup(tid2);
	else
		tc_stat(TC_STAT_END | TC_STAT_FAILED);

	return 0;
}

#ifdef RT_USING_TC
static void _tc_cleanup()
{
	/* 调度器上锁，上锁后，将不再切换到其他线程，仅响应中断 */
	rt_enter_critical();

	/* 删除线程 */
	if (tid1 != RT_NULL && tid1->stat != RT_THREAD_CLOSE)
		rt_thread_delete(tid1);
	if (tid2 != RT_NULL && tid2->stat != RT_THREAD_CLOSE)
		rt_thread_delete(tid2);

	/* 执行内存池脱离 */
	rt_mp_detach(&mp);

	/* 调度器解锁 */
	rt_exit_critical();

	/* 设置TestCase状态 */
	tc_done(TC_STAT_PASSED);
}

int _tc_mempool_simple()
{
	/* 设置TestCase清理回调函数 */
	tc_cleanup(_tc_cleanup);
	mempool_simple_init();

	/* 返回TestCase运行的最长时间 */
	return 100;
}
/* 输出函数命令到finsh shell中 */
FINSH_FUNCTION_EXPORT(_tc_mempool_simple, a memory pool example);
#else
/* 用户应用入口 */
int rt_application_init()
{
	mempool_simple_init();

	return 0;
}
#endif
