⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 djyos.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                pl_ecbn->previous = pg_event_running;
            }
        }
    }
    return 0;
}

//----登记错误信息--------------------------------------------------------------
//功能:把系统错误信息登记到一个环形缓冲区里
//参数:error_type,错误类型
//      text,文字说明
//返回:无
//还需添加文本串的功能,---db
//-----------------------------------------------------------------------------
void y_error_login(uint32_t error_type,const char *text)
{
    pg_event_running->error_no = error_type;
}

//----提取最后一条错误信息-----------------------------------------------------
//功能:把系统错误信息登记到一个环形缓冲区里
//参数:text,返回该错误的文字说明
//返回:错误号
//还需添加文本串和时间的功能,时间使用ticks数---db
//-----------------------------------------------------------------------------
uint32_t y_get_last_error(char *text)
{
    return pg_event_running->error_no;
}

//----从ready队列中取出一个事件------------------------------------------------
//功能: 把一个事件从ready队列中取出,并使ready队列重新连接
//参数: event,待取出的事件指针
//返回: 无
//注: 调用者请保证在异步信号(调度)被禁止的情况下调用本函数
//-----------------------------------------------------------------------------
void __y_cut_ready_event(struct event_script *event)
{
    struct event_script *pl_ecb;
    if(event != pg_event_ready)         //event不是ready队列头
    {
        if(event->multi_next == NULL)   //不是相应优先级的首事件
        {
            event->next->previous = event->previous;
            event->previous->next = event->next;
        }else                           //是相应优先级的首事件
        {
            pl_ecb = event->next;
            event->next->previous = event->previous;
            event->previous->next = event->next;
            if(pl_ecb->prio == event->prio)     //相应优先级不止一个事件
            {
                event->multi_previous->multi_next = pl_ecb;
                pl_ecb->multi_previous = event->multi_previous;
                event->multi_next->multi_previous = pl_ecb;
                pl_ecb->multi_next = event->multi_next;
            }else                               //相应优先级只有一个事件
            {
                //pl_ecb即event->multi_next.
                pl_ecb->multi_previous = event->multi_previous;
                event->multi_previous->multi_next = pl_ecb;
            }
        }
    }else                               //event是ready队列头
    {
        pg_event_ready = event->next;
        pl_ecb = event->next;
        event->next->previous = event->previous;
        event->previous->next = event->next;
        if(pl_ecb->prio == event->prio)     //相应优先级不止一个事件
        {
            event->multi_previous->multi_next = pl_ecb;
            pl_ecb->multi_previous = event->multi_previous;
            event->multi_next->multi_previous = pl_ecb;
            pl_ecb->multi_next = event->multi_next;
        }else                               //相应优先级只有一个事件
        {
            //pl_ecb即event->multi_next.
            pl_ecb->multi_previous = event->multi_previous;
            event->multi_previous->multi_next = pl_ecb;
        }
    }
    event->event_status.bit.event_ready = 0;
}

//----设置轮转调度时间片-------------------------------------------------------
//功能: djyos总所有参与轮转调度的事件时间片都是相同的,在这里设置。如果设为0,
//      表示不允许时间片轮转。
//参数: slices,新的轮转调度时间片,毫秒数,将被向上取整为整数个ticks时间
//返回: 无
//-----------------------------------------------------------------------------
void y_set_RRS_slice(uint32_t slices)
{
#if (32 > cn_cpu_bits)
    //若处理器字长<32位,需要多个周期才能更新u32g_RRS_slice,该过程不能被时钟中断打断.
    int_save_asyn_signal( );
#endif

    u32g_RRS_slice =(slices + cn_tick_ms -1)/cn_tick_ms;

#if (32 > cn_cpu_bits)
    //若处理器字长<32位,需要多个周期才能更新u32g_RRS_slice,该过程不能被时钟中断打断.
    int_restore_asyn_signal( );
#endif
}

//----查询轮转调度时间片-------------------------------------------------------
//功能: djyos总所有参与轮转调度的事件时间片都是相同的,可用本函数查询。
//参数: 无
//返回: 当前时间片长度,毫秒数。
//-----------------------------------------------------------------------------
uint32_t y_get_RRS_slice(void)
{
    uint32_t temp;
#if (32 > cn_cpu_bits)
    //处理器字长<32位,需要多个周期才能读取u32g_RRS_slice,该过程不能被时钟中断打断.
    int_save_asyn_signal( );
#endif

    temp = u32g_RRS_slice * cn_tick_ms;

#if (32 > cn_cpu_bits)
    //处理器字长<32位,需要多个周期才能读取u32g_RRS_slice,该过程不能被时钟中断打断.
    int_restore_asyn_signal( );
#endif
    return temp * cn_tick_ms;
}

//----查找可运行线程----------------------------------------------------------
//功能: 在 pg_event_ready队列中获得一个可以运行的线程.
//      1.从pg_event_ready队列头开始查找,如果该事件还没有连接线程,则试图创建之.
//      2.如果不能建立,肯定是因内存不足,则把该事件放到内存等待表中,继续往下查找.
//      3.如此反复,直到找到一个可以运行的线程.然后把pg_event_ready指针指向该事件
//参数: 无
//返回: 无
//备注: 本函数由操作系统调用,调用前保证关异步信号。
//      由于系统服务事件总是ready,所以总是能找到可以运行的线程.
//----------------------------------------------------------------------------
void __y_select_event_to_run(void)
{
    struct  event_script *pl_ecb;
    struct  event_type *pl_evtt;  //被操作的事件的类型指针

    while(pg_event_ready->vm == NULL)
    {
        pl_evtt =& tg_evtt_table[pg_event_ready->evtt_id];
        if(pl_evtt->my_free_vm != NULL)     //该事件类型有空闲的线程,直接使用
        {
            pg_event_ready->vm = pl_evtt->my_free_vm;
            pl_evtt->my_free_vm = pl_evtt->my_free_vm->next;
        }else       //该事件类型没有空闲的线程,试图创建之
        {
            pg_event_ready->vm = __create_thread(pl_evtt);  //创建线程
            if(pg_event_ready->vm == NULL)                  //创建线程失败
            {
                pl_ecb = pg_event_ready;
                __y_cut_ready_event(pl_ecb);
                __m_wait_memory(pl_ecb);
            }else                                           //成功创建线程
            {
                pl_evtt->vpus++;
                //取此前被重复pop的次数
                pg_event_ready->repeats = pl_evtt->repeats;
            }
        }
    }
}

//----创建进程虚拟机-----------------------------------------------------------
//功能: 创建进程虚拟机。
//参数: 无
//返回: 无
//备注: 这只是占一个位而已,在mp模式才有实用价值
//-----------------------------------------------------------------------------
void y_create_process_vm(void)
{
    static struct process_vm my_process;
    pg_my_process = &my_process;
}

//----事件调度-----------------------------------------------------------------
//功能:剥夺running事件的cpu,把cpu交给ready队列的第一个事件.如果ready队列的第一
//      个事件尚未拥有线程,则建立之.建立线程时如果内存不足,则把这个事件放到
//      内存等待链表中,ready指针指向ready队列的下一个事件,依次推之,直到找到一个
//      线程虚拟机指针非空或者成功创建线程虚拟机的事件.
//参数:无
//返回:true = 成功切换,false = 未切换直接返回
//备注:1.本函数由操作系统调用
//      2.djyos系统认为,用户禁止中断就是为了能够连续执行,或者保护临界资源.
//      djyos中异步信号相当于高优先级线程,所以全局和异步信号禁止状态
//      下,是不允许事件调度的.
//      3.实时中断是否禁止,与调度无关.
//      4.本函数由操作系统调用,调用方保证调用时中断是允许的,不检查.
//      5.由于最低优先级的系统服务事件总是ready,因此本函数总是能够找到目标事件
//-----------------------------------------------------------------------------
bool_t __schedule(void)
{
    struct  event_script *event;

    if(tg_int_global.nest_asyn_signal != 0)
        return false;
    int_save_asyn_signal();   //在上下文切换期间不能发生异步信号中断
    __y_select_event_to_run();
    if(pg_event_ready != pg_event_running)
    {//当running事件仍在ready队列中,且内存不足以建立新虚拟机时,可能会出现优先
     //级高于running的事件全部进入内存等待队列的可能.此时执行else子句.
        u32g_running_start=y_get_time();
        event = pg_event_running;
        pg_event_running=pg_event_ready;
        __asm_switch_context(pg_event_ready->vm ,event->vm);
    }else
    {//优先级高于running的事件全部进入内存等待队列,下一个要处理的事件就是
     //running事件,无须执行任何操作
        int_restore_asyn_signal();
        return false;
    }
    return true;
}

//----中断内执行的事件调度------------------------------------------------------
//功能:剥夺running事件的cpu,把cpu交给ready队列的第一个事件.如果ready队列的第一
//      个事件尚不拥有线程,则创建之.建立线程时如果内存不足,则把这个事件放到
//      内存等待链表中,ready指针指向ready队列的下一个事件,依次推之,直到找到一个
//      线程虚拟机指针非空或者成功创建线程虚拟机的事件.
//参数:无
//返回:无
//备注:本函数由操作系统在异步信号引擎返回前调用
//      由于最低优先级的y_idle_service事件总是ready,因此总是能够找到调度对象的.
//-----------------------------------------------------------------------------
void __schedule_asyn_signal(void)
{
    struct  event_script *event;

    __y_select_event_to_run();
    if(pg_event_ready != pg_event_running)
    {//当running事件仍在ready队列中,且内存不足以建立新虚拟机时,可能会出现优先
     //级高于running的事件全部进入内存等待队列的可能.此时执行else子句.
        u32g_running_start=y_get_time();
        event=pg_event_running;
        pg_event_running=pg_event_ready;
        __asm_switch_context_int(pg_event_ready->vm,event->vm);
    }else
    {//优先级高于running的事件全部进入内存等待队列,下一个要处理的事件就是
     //running事件,无须执行任何操作
    }
    return;
}

//----登记事件类型------------------------------------------------------------
//功能:登记一个事件类型到系统中,事件类型经过登记后,就可以pop了,否则,系统会
//      拒绝pop该类型事件
//参数:mark,本事件类型是否mark型事件,true = 是,false = 否
//      overlay,若是mark型事件,新事件参数是否覆盖队列中已有事件,非mark事件无效
//      default_prio,本事件类型的默认优先级。
//      vpus_limit,同一事件本类型事件所能拥有的线程数量的最大值
//      thread_routine,线程入口函数(事件处理函数)
//      stack_size,执行thread_routine需要的栈尺寸,不包括thread_routine函数可能
//          调用的系统服务。
//      evtt_name,事件类型名,不同模块之间要交叉弹出事件的话,用事件类型名。
//          本参数允许是NULL,但只要非NULL,就不允许与事件类型表中已有的名字重名
//返回:新事件类型的类型号
//------------------------------------------------------------------------------
uint16_t y_evtt_regist(bool_t mark,bool_t overlay,
                       ufast_t default_prio,
                       uint16_t vpus_limit,
                       void (*thread_routine)(struct event_script *),
                       uint32_t stack_size,
                       char *evtt_name)
{
    uint16_t i,evtt_id;
    char *temp_name;
    if((default_prio >= cn_prio_sys_service) || (default_prio == 0))
    {
        y_error_login(enum_knl_invalid_prio,"事件类型优先级非法");
        return cn_invalid_evtt_id;
    }
    int_save_asyn_signal();      //禁止调度也就是禁止异步事件
    for(evtt_id=0; evtt_id<cn_evtts_limit; evtt_id++)   //查找空闲的事件控制块
        if( tg_evtt_table[evtt_id].property.registered == 0)
            break;
    if(evtt_id == cn_evtts_limit)     //没有空闲事件控制块

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -