📄 lock.c
字号:
mb_free(pg_lock_pool,semp); //释放内存
return true;
}else
return false;
}
//----查询一个信号量-----------------------------------------------------------
//功能:查询信号灯已经被使用的数量,
//参数:semp,被查询的信号量
//返回:已使用的信号灯数量
//-----------------------------------------------------------------------------
uint32_t semp_query_used(struct semaphore_LCB *semp)
{
if(semp == NULL) //参数错误
return 0;
else
return semp->lamp_used; //返回已使用的信号灯数量
}
//----查询信号量容量-----------------------------------------------------------
//功能:查询一个信号量包含信号灯的总数
//参数:semp,被查询的信号量
//返回:信号灯总数
//-----------------------------------------------------------------------------
uint32_t semp_query_capacital(struct semaphore_LCB *semp)
{
if(semp == NULL) //参数错误
return 0;
return semp->lamps_limit;
}
//----查询可用信号灯数量-------------------------------------------------------
//功能:查询一个信号量可用信号灯的数量
//参数:semp,被查询的信号量
//返回:信号灯总数
//-----------------------------------------------------------------------------
uint32_t semp_query_free(struct semaphore_LCB *semp)
{
if(semp == NULL) //参数错误
return 0;
return semp->lamp_counter;
}
//-----------------------下面是互斥量------------------------------------------
//----创建一个信号量-----------------------------------------------------------
//功能:建立一个信号量,以后就可以使用这个信号量了。
//参数:init_lamp,初始信号灯状态
// name,互斥量的名字
//返回:新建立的互斥量指针
//-----------------------------------------------------------------------------
struct mutex_LCB *mutex_create(bool_t init_lamp,char *name)
{
struct mutex_LCB *mutex;
mutex = mb_malloc(pg_lock_pool,0);
if(mutex == NULL)
return NULL;
mutex->enable = init_lamp;
mutex->mutex_sync = NULL;
mutex->prio_bak = cn_prio_invalid;
//把新节点挂到信号量根节点下
rsc_add_son(&pg_mutex_rsc->node,&mutex->node,
sizeof(struct mutex_LCB),name);
return mutex;
}
//----创建一个内核互斥量-------------------------------------------------------
//功能:与mutex_createe的区别是,本函数需要调用者提供mutex实体,而不是从池中分配。
// 因为cn_locks_limit是用户定义的,如果内核也与应用程序共享的话,将使内核
// 与应用程序发生耦合。
//参数:mutex,目标信号量指针
// init_lamp,初始信号灯状态,true=资源可用,false=资源不可用
// name,互斥量的名字
//返回:新建立的信号量指针
//-----------------------------------------------------------------------------
void __mutex_createe_knl( struct mutex_LCB *mutex,bool_t init_lamp,char *name)
{
mutex->enable = init_lamp;
mutex->mutex_sync = NULL;
mutex->prio_bak = cn_prio_invalid;
//把新节点挂到信号量根节点下
rsc_add_son(&pg_mutex_rsc->node,&mutex->node,
sizeof(struct mutex_LCB),name);
}
//----释放一个互斥量-----------------------------------------------------------
//功能:释放互斥量
//参数:mutex,互斥量指针
//返回:无
//-----------------------------------------------------------------------------
void mutex_post(struct mutex_LCB *mutex)
{
struct event_script *event;
if(mutex == NULL)
return;
if(mutex->owner != pg_event_running) //互斥量只能由拥有者释放
return;
int_save_asyn_signal();
if(mutex->mutex_sync == NULL) //等待队列空,点亮一盏信号灯
{
mutex->enable = true; //互斥量可用
} else //有事件在等待,把互斥量直接转交给队列中优先级最高的事件
{
event = mutex->mutex_sync;
event->sync_head = NULL;
if(event->multi_next == event)
{//队列中只有一个事件
mutex->mutex_sync = NULL;
}else
{//队列中有多个事件,取出队列头部的事件
mutex->mutex_sync = event->next;
event->multi_next->multi_previous = event->multi_previous;
event->multi_previous->multi_next = event->multi_next;
event->multi_next = NULL;
event->multi_previous = NULL;
}
if(event->event_status.bit.wait_overtime)
__y_resume_delay(event); //如果事件在超时等待队列中,取出
event->event_status.bit.wait_overtime = 0;
event->last_status.all = event->event_status.all;//备份事件状态
event->event_status.bit.wait_mutex = 0; //清除等待状态
__y_event_ready(event);
}
if(mutex->prio_bak != cn_prio_invalid) //该互斥量发生了优先级继承
{
__y_cut_ready_event(pg_event_running); //取出running事件
pg_event_running->prio = mutex->prio_bak; //恢复优先级
mutex->prio_bak = cn_prio_invalid;
__y_event_ready(pg_event_running); //重新把running插入就绪队列(新位置)
}
int_restore_asyn_signal();
}
//----请求一盏信号灯-----------------------------------------------------------
//功能:请求然后熄灭一盏信号灯,表示可用资源数减1。
//参数:mutex,信号量指针
// timeout,超时设置,单位是毫秒,cn_timeout_forever=无限等待,0则立即按
// 超时返回。非0值将被向上调整为cn_tick_ms的整数倍
//返回:true=取得信号返回或资源不受信号灯保护(mutex == NULL),semp==NULL时返回
// true是有意义的,如果你希望代码在不管是否受信号灯保护都保持一致,把semp
// 设为NULL是明智的选择,比如你要构建一个不受信号灯保护的设备,可把该设备
// struct pan_device的semp成员设为NULL。
// false=没有取得信号(超时返回或其他原因)
//-----------------------------------------------------------------------------
bool_t mutex_pend(struct mutex_LCB *mutex,uint32_t timeout)
{
struct event_script *pl_ecb;
bool_t lamp;
if(mutex == NULL)
return true;
int_save_asyn_signal(); //以下读取信号灯数量,必须保证原子操作,故关中断
if(mutex->enable == true) //信号灯可用
{
lamp = true;
mutex->enable = false;
mutex->prio_bak = cn_prio_invalid;
mutex->owner = pg_event_running;
}else //信号灯不可用
{
lamp = false;
}
int_restore_asyn_signal();
if(lamp == true)
return true; //取得信号灯返回
else if(!y_query_sch() || (timeout == 0))//禁止调度时,不能阻塞.或timeout为0
return false; //没有取得信号灯返回
int_save_asyn_signal();
__y_cut_ready_event(pg_event_running);
pg_event_running->previous = NULL;
pg_event_running->next = NULL;
pg_event_running->sync_head = &mutex->mutex_sync;
if(mutex->mutex_sync == NULL)
{//同步队列空,running事件自成双向循环链表
pg_event_running->multi_next = pg_event_running;
pg_event_running->multi_previous = pg_event_running;
mutex->mutex_sync = pg_event_running;
}else
{//同步队列非空,按优先级排序
pl_ecb = mutex->mutex_sync;
do
{ //找到一个优先级低于新事件的事件.
if(pl_ecb->prio <= pg_event_running->prio)
pl_ecb = pl_ecb->multi_next;
else
break;
}while(pl_ecb != mutex->mutex_sync);
pg_event_running->multi_next = pl_ecb;
pg_event_running->multi_previous = pl_ecb->multi_previous;
pl_ecb->multi_previous->multi_next = pg_event_running;
pl_ecb->multi_previous = pg_event_running;
if(mutex->mutex_sync->prio > pg_event_running->prio)
mutex->mutex_sync = mutex->mutex_sync->multi_previous;
}
pg_event_running->last_status.all = pg_event_running->event_status.all;
pg_event_running->event_status.bit.wait_mutex = 1; //事件状态设为等待信号量
if(timeout != cn_timeout_forever)
{
pg_event_running->event_status.bit.wait_overtime = 1;
__y_addto_delay((timeout + cn_tick_ms -1)/cn_tick_ms);
}
//下面看看是否要做优先级继承
pl_ecb = mutex->owner;
if(pl_ecb->prio > pg_event_running->prio) //需要继承优先级
{//1、处于就绪态,2、处于某种阻塞态。
if(pl_ecb->event_status.bit.event_ready ==1)//占用互斥量的事件处于就绪态
{
__y_cut_ready_event(pl_ecb);
//prio_bak应该保留事件的原始优先级,防止出现多次继承中被修改为中间优先级
if(mutex->prio_bak != cn_prio_invalid)
mutex->prio_bak = pl_ecb->prio;
pl_ecb->prio = pg_event_running->prio;
__y_event_ready(pl_ecb);
}else //占用互斥量的事件处于某种阻塞态,暂不处理
{
}
}
int_restore_asyn_signal(); //恢复中断,将触发上下文切换
int_save_asyn_signal(); //此时,已经是重新获得信号量,上下文切回
//检查从哪里返回,是超时还是同步事件完成。
if(pg_event_running->event_status.bit.wait_mutex)
{//说明同步条件未到,从超时返回,应从目标事件的同步队列中取出事件。
//此时,被同步的事件肯定还没有完成。
pg_event_running->event_status.bit.wait_mutex = 0;
int_restore_asyn_signal();
return false;
}else
{//说明是得到互斥量返回
int_restore_asyn_signal();
return true;
}
}
//----删除一个信号量-----------------------------------------------------------
//功能:删除一个信号量
//参数:mutex,被删除的信号量
//返回:无
//-----------------------------------------------------------------------------
bool_t mutex_delete(struct mutex_LCB *mutex)
{
if(mutex == NULL) //参数错误
return false;
if(mutex->mutex_sync != NULL) //没有事件在等待信号灯
{
rsc_del_node(&mutex->node); //删除信号量结点
mb_free(pg_lock_pool,mutex); //释放内存
return true;
}else
return false;
}
//----查询一个信号量-----------------------------------------------------------
//功能:查询信号灯已经被使用的数量,
//参数:mutex,被查询的信号量
//返回:点亮的信号灯的数量
//-----------------------------------------------------------------------------
bool_t mutex_query_used(struct mutex_LCB *mutex)
{
return mutex->enable;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -