当前位置: 首页 > article >正文

存储块的获取与释放

目录

获取存储块

释放存储块

设计实现


获取存储块

空闲存储块直接取出空闲块

空闲存储块任务进入等待队列

释放存储块

任务等待插入空闲链表

任务等待释放等待队列头部的任务

设计实现

  • 获取存储块(先检查是否有空闲存储块,有则取出一个;没有则将任务插入事件队列中,再执行一次事件调度以便于切换到其他任务,切换回来时从tTask中取出获得的消息,返回取出等待结果)
  • 无等待获取存储块(没有空闲存储块直接返回资源不可用,不会阻塞任务运行)
  • 释放存储块(有任务等待则唤醒位于队列首部也就是最先等待的任务,如果这个任务的优先级更高,则执行调度切换过去;没有任务等待着将存储块插入队列中)

tMemBlock.c

#include "tinyOS.h"

/* 存储块初始化函数 */
//参数:存储块,存储块分配空间的起始地址,存储块的大小,存储块的数量
void tMemBlockInit(tMemBlock *memBlock, uint8_t *memStart, uint32_t blockSize, uint32_t blockCnt)
{
	uint8_t *memBlockStart = (uint8_t *)memStart;									//存储空间的起始地址
	uint8_t *memBlockEnd = memBlockStart + blockSize * blockCnt;	//存储空间的结束地址
	
	//对存储空间进行划分时,划分的每一个存储块的大小会作为链表的结点插入链表中,这个链表结点会占用存储块开始的一部分空间,所以要求blockSize不能小于结点大小
	if(blockSize < sizeof(tNode))
	{
		return;
	}
	
	tEventInit(&memBlock->event, tEventTypeMemBlock);
	memBlock->memStart = memStart;
	memBlock->blockSize = blockSize;
	memBlock->maxCount = blockCnt;
	
	tListInit(&memBlock->blockList);//初始化存放存储块的链表
	//从存储区的起始地址,依次划分各个存储块
	while(memBlockStart < memBlockEnd)//从开始去找到尾部
	{
		tNodeInit((tNode *)memBlockStart);//对每一个存储块是要它最开始的存储区作为一个结点,进行初始化
		tListAddLast(&memBlock->blockList, (tNode *)memBlockStart);//将存储块加到存储块链表中
		
		memBlockStart += blockSize;//指针前移
	}
}

/* 存储块获取函数 */
//参数:存储块,用于获取存储块时将存储块存入其中的指针,最大的等待计数
uint32_t tMemBlockWait(tMemBlock *memBlock, uint8_t **mem, uint32_t waitTicks)
{
	uint32_t status = tTaskEnterCritical();
	
	if(tListCount(&memBlock->blockList) > 0)//是否有空闲存储块
	{
		*mem = (uint8_t *)tListRemoveFirst(&memBlock->blockList);//从列表头部移出一个存储块
		tTaskExitCritical(status);
		return tErrorNoError;//返回没有错误
	}
	else
	{
		tEventWait(&memBlock->event, currentTask, (void *)0, tEventTypeMemBlock, waitTicks);//任务在事件控制块上等待
		tTaskExitCritical(status);
		
		tTaskSched();//切换到其他任务运行
		
		*mem = currentTask->eventMsg;//取出分配到的存储块
		return currentTask->waitEventResult;//返回等待结果
	}
}

/* 存储块无等待获取函数 */
uint32_t tMemBlockWaitGet(tMemBlock *memBlock, void **mem)
{
	uint32_t status = tTaskEnterCritical();
	
	if(tListCount(&memBlock->blockList) > 0)
	{
		*mem = (uint8_t *)tListRemoveFirst(&memBlock->blockList);
		tTaskExitCritical(status);
		return tErrorNoError;
	}
	else
	{
		tTaskExitCritical(status);
		return tErrorResourceUnavailable;//返回资源不可用
	}
}

/* 存储块释放函数 */
void tMemBlockNotify(tMemBlock *memBlock, uint8_t *mem)
{
	uint32_t status = tTaskEnterCritical();
	
	if(tEventWaitCount(&memBlock->event) > 0)//是否有任务在事件控制块上等待
	{
		tTask *task = tEventWakeUp(&memBlock->event, (void *)mem, tErrorNoError);//移出一个任务
		if(task->prio < currentTask->prio)//判断优先级
		{
			tTaskSched();
		}
	}
	else
	{
		tListAddLast(&memBlock->blockList, (tNode *)mem);//将存储块插入空闲存储块列表
	}
	tTaskExitCritical(status);
}

tMemBlock.h

#ifndef __TMEMBOLCK_H
#define __TMEMBOLCK_H

#include "tEvent.h"

/* 存储块结构 */
typedef struct _tMemBlock
{
	tEvent event;				//事件控制块
	void *memStart;			//存储区的起始地址
	uint32_t blockSize;	//每个存储块的大小
	uint32_t maxCount;	//最大存储块数量
	tList blockList;		//存储块列表
}tMemBlock;

void tMemBlockInit(tMemBlock *memBlock, uint8_t *memStart, uint32_t blockSize, uint32_t blockCnt);
uint32_t tMemBlockWait(tMemBlock *memBlock, uint8_t **mem, uint32_t waitTicks);
uint32_t tMemBlockWaitGet(tMemBlock *memBlock, void **mem);
void tMemBlockNotify(tMemBlock *memBlock, uint8_t *mem);
	
#endif

app.c

#include "tinyOS.h"
#include "string.h"

//定义任务,分别为它们配备独立的堆栈空间
tTask tTask1;
tTask tTask2;
tTask tTask3;
tTask tTask4;
tTaskStack task1Env[1024];
tTaskStack task2Env[1024];
tTaskStack task3Env[1024];
tTaskStack task4Env[1024];

typedef uint8_t (*tBlock)[100];
uint8_t mem1[20][100];//20个存储块,每个块是100字节
tMemBlock memBlock1;

//定义任务要执行的功能
int task1Flag;
void task1Entry(void *param)
{
	tBlock block[20];
	
	tSetSysTickPeriod(10);//初始化
	
	tMemBlockInit(&memBlock1, (uint8_t *)mem1, 100, 20);
	for(int i = 0; i <20; i++)
	{
		tMemBlockWait(&memBlock1, (uint8_t **)&block[i], 0);
	}
	
	tTaskDelay(2);
	
	for(int i = 0; i <20; i++)
	{
		memset(block[i], i, 100);
		tMemBlockNotify(&memBlock1, (uint8_t *)block[i]);
		tTaskDelay(2);
	}
	
	for(;;)//任务里是for的死循环
	{
		task1Flag = 0; 
		tTaskDelay(1);
		task1Flag = 1;
		tTaskDelay(1);
	}
}

int task2Flag;
void task2Entry(void *param)
{
	
	for(;;)
	{
		tBlock block;
		tMemBlockWait(&memBlock1, (uint8_t **)&block, 0);
		task2Flag = *(uint8_t *)block;

	}
}
int task3Flag;
void task3Entry(void *param)
{
	for(;;)
	{
		task3Flag = 0;
		tTaskDelay(1);
		task3Flag = 1;
		tTaskDelay(1);
	}
}
int task4Flag;
void task4Entry(void *param)
{
	for(;;)
	{
		task4Flag = 0;
		tTaskDelay(1);
		task4Flag = 1;
		tTaskDelay(1);
	}
}

/* 应用任务初始化函数 */
void tInitApp(void)
{
	//最后一个参数:传堆栈末端地址,因为堆栈是向下生长的,初始堆栈地址是堆栈空间最后一个单元地址的末端
	tTaskInit(&tTask1, task1Entry, (void *)0x11111111, 0, &task1Env[1024]);
	tTaskInit(&tTask2, task2Entry, (void *)0x22222222, 1, &task2Env[1024]);
	tTaskInit(&tTask3, task3Entry, (void *)0x22222222, 1, &task3Env[1024]);
	tTaskInit(&tTask4, task4Entry, (void *)0x22222222, 1, &task4Env[1024]);
}

调试现象:


http://www.kler.cn/a/453146.html

相关文章:

  • k8s,service如何找到容器
  • TP5 动态渲染多个Layui表格并批量打印所有表格
  • 接口测试Day03-postman断言关联
  • Jensen-Shannon Divergence:定义、性质与应用
  • 每天40分玩转Django:Django静态文件
  • MySQL变量
  • Windows下ESP32-IDF开发环境搭建
  • 智源研究院与安谋科技达成战略合作,共建开源AI“芯”生态
  • 冰狐智能辅助使用插件化开发集成三方ocr
  • Linux中的lseek 函数与fcntl函数
  • CMS(Concurrent Mark Sweep)垃圾回收器的具体流程
  • 使用Python读写文本文件
  • 【2024最新】基于Python+Mysql+django的水果销售系统Lw+PPT
  • 网络层协议--ip协议
  • uni-app 中使用微信小程序第三方 SDK 及资源汇总
  • 常用的Django模板语言
  • 437 路径总和III
  • 接口调用限频(代理模式+滑动窗口)
  • Electron【详解】菜单 Menu
  • tokenizer、tokenizer.encode、tokenizer.encode_plus比较
  • 打造两轮差速机器人fishbot:从零开始构建移动机器人
  • 前端开发 -- 自动回复机器人【附完整源码】
  • 如何检查交叉编译器gcc工具链里是否有某个库(以zlib库和libpng库为例)
  • 修炼之道 ---其四
  • 3.系统学习-熵与决策树
  • 福特汽车物流仓储系统WMS:开源了,可直接下载