📄 djyos.c
字号:
{
y_error_login(enum_knl_no_free_etcb,"没有空闲事件控制块");
int_restore_asyn_signal();
return cn_invalid_evtt_id;
}else if(evtt_name != NULL) //新类型有名字,需检查有没有重名
{
for(i=0; i<cn_evtts_limit; i++)
{
if(strcmp(tg_evtt_table[i].evtt_name,evtt_name) == 0)
{
y_error_login(enum_knl_evtt_homonymy,"事件类型重名");
int_restore_asyn_signal();
return cn_invalid_evtt_id;
}
}
if(rtstrlen(evtt_name,31) != cn_limit_uint32)
strcpy(tg_evtt_table[evtt_id].evtt_name,evtt_name);
else
{
memcpy(tg_evtt_table[evtt_id].evtt_name,evtt_name,31);
tg_evtt_table[evtt_id].evtt_name[31] = '\0';
}
}
tg_evtt_table[evtt_id].property = (struct evtt_property){0,0,1,0};
tg_evtt_table[evtt_id].property.mark = mark;
tg_evtt_table[evtt_id].property.overlay = overlay;
tg_evtt_table[evtt_id].my_free_vm = NULL;
tg_evtt_table[evtt_id].default_prio = default_prio;
tg_evtt_table[evtt_id].pop_sum = 0;
tg_evtt_table[evtt_id].done_sum = 0;
tg_evtt_table[evtt_id].repeats = 0;
tg_evtt_table[evtt_id].vpus_limit = vpus_limit;
tg_evtt_table[evtt_id].thread_routine = thread_routine;
tg_evtt_table[evtt_id].stack_size = stack_size;
tg_evtt_table[evtt_id].mark_unclear = NULL;
tg_evtt_table[evtt_id].done_sync = NULL;
tg_evtt_table[evtt_id].pop_sync = NULL;
if((cn_run_mode!=cn_mode_mp)||(default_prio<0x80))
{//运行模式为si或dlsp,或该事件类型拥有紧急优先级,需预先创建一个线程虚拟机
tg_evtt_table[evtt_id].my_free_vm =
__create_thread(&tg_evtt_table[evtt_id]);
if(tg_evtt_table[evtt_id].my_free_vm == NULL)
{//内存不足,不能创建虚拟机
y_error_login(enum_mem_tried,"创建虚拟机时内存不足");
return cn_invalid_evtt_id;
}else
tg_evtt_table[evtt_id].vpus = 1;
}else
tg_evtt_table[evtt_id].vpus = 0;
int_restore_asyn_signal();
return evtt_id;
}
//----取事件类型id-------------------------------------------------------------
//功能:根据事件类型的名字,返回该事件类型的id号,不查找没名字的事件类型。
//参数:evtt_name,事件类型名
//返回:事件类型id号,如果没有找到则返回cn_invalid_id。
//备注:只能找到有名字的事件类型,没名字的事件类型又叫隐身事件类型。
//----------------------------------------------------------------------------
uint16_t y_get_evtt_id(char *evtt_name)
{
uint16_t loop;
if(evtt_name == NULL)
return cn_invalid_evtt_id;
for(loop = 0; loop < cn_evtts_limit; loop++)
{
if(strcmp(tg_evtt_table[loop].evtt_name,evtt_name) ==0)
return loop;
}
return cn_invalid_evtt_id;
}
//----删除事件类型-------------------------------------------------------------
//功能: 删除一个事件类型,如果队列中还有该类型事件(in_use == 1),只标记该类型为被
// 删除,真正的删除工作是在 done函数里完成的.如果队列中已经没有该类型事件了,
// 将会执行真正的删除操作.无论哪种情况,系统均会拒绝弹出该类型的新事件.
//参数: evtt_id,待删除的事件类型号
//返回: true = 成功,包括成功标记;false = 失败
//-----------------------------------------------------------------------------
bool_t y_evtt_unregist(uint16_t evtt_id)
{
struct thread_vm *next_vm,*temp;
struct event_type *evtt;
bool_t result = true;
if(evtt_id >= cn_evtts_limit)
return false;
evtt = &tg_evtt_table[evtt_id];
if((evtt->property.in_use)||(evtt->done_sync != NULL)
|| (evtt->pop_sync != NULL))
{
//事件类型正在使用或完成同步和弹出同步队列非空,不允许删除
result = false;
}else
{
next_vm = evtt->my_free_vm;
//回收事件类型控制块,只需把registered属性清零。
evtt->property.registered = 0;
evtt->evtt_name[0] = '\0'; //清空事件类型名
while(next_vm != NULL) //释放该事件类型拥有的空闲虚拟机
{
temp = next_vm;
next_vm = next_vm->next;
m_free((void *)temp);
}
}
return result;
}
//----建立事件链表-------------------------------------------------------------
//功能:1.根据系统设定初始化操作系统虚拟机和事件表指针
// 2.把 cn_events_limit 个事件控制块结构连接成一个空闲队列,队列的结构参见
// 文档,由指针pg_free_event索引,
//参数:无
//返回:无
//-----------------------------------------------------------------------------
void __y_init_sys(void)
{
uint16_t i;
struct thread_vm *vm;
pg_event_delay=NULL; //延时事件链表空
//把事件类型表全部置为没有注册,0为系统服务类型
for(i=1; i<cn_evtts_limit; i++)
{
tg_evtt_table[i].property.registered = 0;
}
for(i = 1; i < cn_events_limit; i++) //i=0为系统服务事件
{
if(i==(cn_events_limit-1))
tg_event_table[i].next = NULL;
else
tg_event_table[i].next = &tg_event_table[i+1];
//向前指针指向pg_event_free的地址,说明这事个空闲事件块.
//没有别的含义,只是找一个唯一且不变的数值,全局变量地址在整个运行期
//是不会变化的.
tg_event_table[i].previous = (struct event_script*)&pg_event_free;
tg_event_table[i].event_id = i; //本id号在程序运行期维持不变
}
pg_event_free = &tg_event_table[1];
tg_evtt_table[0].property = (struct evtt_property){1,0,1,1};
tg_evtt_table[0].my_free_vm = NULL;
tg_evtt_table[0].evtt_name[0] = '\0';
tg_evtt_table[0].default_prio = cn_prio_sys_service;
tg_evtt_table[0].pop_sum = 0;
tg_evtt_table[0].done_sum = 0;
tg_evtt_table[0].repeats = 1;
tg_evtt_table[0].vpus_limit =1;
tg_evtt_table[0].vpus = 1;
tg_evtt_table[0].thread_routine = __os_service;
tg_evtt_table[0].stack_size = 1024;
tg_evtt_table[0].mark_unclear = tg_event_table;
tg_evtt_table[0].done_sync = NULL;
tg_evtt_table[0].pop_sync = NULL;
vm = __create_thread(&tg_evtt_table[0]);
if(vm == NULL) //内存不足,不能创建常驻虚拟机
{
y_error_login(enum_mem_tried,"创建虚拟机时内存不足");
tg_evtt_table[0].vpus = 0;
return ;
}
//以下模拟popup函数,弹出系统服务事件.当事件队列为空时,调用popup的结果
//是不可预知的.由于系统运行时,系统服务事件总在队列中,所以事件队列是不会空
//的,这里模拟popup事件,而不是直接调用,可以使popup函数中省掉一个判断队列是否
//空的操作.
tg_event_table[0] = (struct event_script){
tg_event_table,tg_event_table, //next,previous
tg_event_table,tg_event_table,//multi_next,multi_previous
vm, //vm
NULL, //sync
NULL, //sync_head
0, //start_time
0, //consumed_time
0, //delay_start
0, //delay_end
enum_knl_no_error, //error_no
0,0, //parameter0,parameter1
0, //wait_mem_size
{0}, //last_status
{0}, //event_status
cn_prio_sys_service, //prio
0, //evtt_id
0, //sync_counter
0, //event_id
1, //repeats
NULL,0 //held_device,local_memory
};
tg_event_table[0].event_status.bit.event_ready = 1;
pg_event_ready = tg_event_table;
pg_event_running = pg_event_ready;
}
//--------检查是否允许调度------------------------------------------------------
//功能: 检查是否允许调度,允许异步信号且运行在线程态时,允许调度
//参数: 无
//返回: 允许调度返回true,否则返回false
//-----------------------------------------------------------------------------
bool_t y_query_sch(void)
{
return ((tg_int_global.en_asyn_signal)
&& (tg_int_global.nest_asyn_signal == 0)
&& (tg_int_global.en_trunk));
}
//----把事件插入就绪队列中----------------------------------------------------
//功能:把事件插入到就绪队列中合适的位置,该事件原来不在就绪队列中.
//参数:event_ready,待插入的事件,该事件原来不在就绪队列中
//返回:无
//------------------------------------------------------------------------------
void __y_event_ready(struct event_script *event_ready)
{
struct event_script *event;
int_save_asyn_signal();
event_ready->event_status.bit.event_ready = 1;
event = pg_event_ready;
do
{ //找到一个优先级低于新事件的事件.由于系统服务事件总是ready,因此总是能找到.
if(event->prio <= event_ready->prio)
event = event->next;
else
break;
}while(event != pg_event_ready);
event_ready->next = event;
event_ready->previous = event->previous;
event->previous->next = event_ready;
event->previous = event_ready;
//新插入的事件在同优先级的最后,故这样能够判断新事件是否该优先级的唯一事件。
//若是该优先级的唯一事件,也即是该优先级首事件,则需要将其插入首事件链表
if(event_ready->prio != event_ready->previous->prio)
{
event = event_ready->next;
event->multi_previous->multi_next = event_ready;
event_ready->multi_previous = event->multi_previous;
event->multi_previous = event_ready;
event_ready->multi_next = event;
}else //不是该优先级的首事件
{
event_ready->multi_next = NULL;
event_ready->multi_previous = NULL;
}
if(event_ready->prio < pg_event_ready->prio)
pg_event_ready = event_ready;
int_restore_asyn_signal();
}
//----退出闹钟同步队列---------------------------------------------------------
//功能: 把一个事件从闹钟同步队列中取出,不管闹铃时间是否已经到达.用在带超时的同步
// 功能中,当同步条件先于超时时限到达时,从闹钟同步队列取出事件。
//参数: delay_event,待处理的事件.
//返回: 无
//备注: 1.本函数不开放给用户,仅仅是操作系统内部使用.操作系统不给用户提供提前
// 退出延时的功能,这样可以防止事件间互相干涉
// 2.本函数应该在关闭调度条件下调用,调用者保证,函数内部不检查中断状态.
// 3.本函数只把事件从闹钟同步链表中取出,并不放到就绪队列中。
//-----------------------------------------------------------------------------
void __y_resume_delay(struct event_script *delay_event)
{
if(pg_event_delay->next == pg_event_delay) //队列中只有一个事件
pg_event_delay = NULL;
else
{
if(delay_event == pg_event_delay)
pg_event_delay = pg_event_delay->previous;
delay_event->next->previous = delay_event->previous;
delay_event->previous->next = delay_event->next;
}
delay_event->next = NULL;
delay_event->previous = NULL;
delay_event->delay_end = y_get_time();
}
//----加入延时队列------------------------------------------------------------
//功能:由正在执行的事件调用,直接把自己加入延时队列,不引起调度也不操作ready
// 队列,一般由同步函数调用,在timeout!=0时把事件加入闹钟同步队列实现
// timeout功能,是特定条件下对y_timer_sync函数的简化。
//参数:u32l_mS,延迟时间,单位是毫秒,将被向上调整为cn_tick_ms的整数倍
//返回:无
//备注:1、操作系统内部使用的函数,且需在关闭中断(禁止调度)的条件下使用。
// 2、调用本函数是running事件已经从就绪表中取出,本函数不改变就绪表。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -