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

📄 lock.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        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 + -