SMC-RTOS之semaphore

数据结构

typedef struct smc_sem {
    smc_list_head_t slist;                        /* Thread that is suspended for waiting for a semaphore */ 
    smc_uint16_t    value;                        /* semaphore value */
} smc_sem_t;

操作函数

对sem的操作主要是初始化、获取、释放。

void smc_sem_init(smc_sem_t *sem, smc_uint16_t value);/*sem的初始化*/
smc_int32_t smc_sem_pend(smc_sem_t *sem, smc_int32_t time_out);/*sem的获取*/
smc_int32_t smc_sem_release(smc_sem_t *sem);/*sem的释放*/

在SMC-RTOS中,一些接口函数的实现相对于ucosii来说是十分简洁的,比如在获取信号量时候分阻塞式和非阻塞式,ucosii实现了将阻塞式和非阻塞式两个接口,在SMC-RTOS中则十分简洁,只用了一个接口,通过传参的方式来实现阻塞式和非阻塞式获取信号量。

  • 初始化
void smc_sem_init(smc_sem_t *sem, smc_uint16_t value)
{
    smc_list_node_init(&sem->slist);/*初始化被sem阻塞的链表,实际就是将前后节点指针指向自己*/
    sem->value = value;/*sem的本质还是个计数类型的数据,初始化sem的value*/
}
  • 获取
smc_int32_t smc_sem_pend(smc_sem_t *sem, smc_int32_t time_out)
{
    smc_uint32_t status;

    /* disable interrupt */
    status = smc_cpu_disable_interrupt();

    if (sem->value > 0) {/* 如果信号量的值大于0,不管阻塞式还是非阻塞式,将sem->value减一即可返回 */
        sem->value--;
        /* enable interrupt */
        smc_cpu_enable_interrupt(status);
    } else {
        if (time_out == SMC_SEM_NO_WAIT) {/* 如果信号量的值小于0,且是非阻塞式的获取,立即返回获取失败*/
            smc_cpu_enable_interrupt(status);
            return -SMC_TIMEOUT;
        } else {/* 如果信号量的值小于0,且是阻塞式的获取,就先要将本thread挂起,并设置超时时间,然后将本thread添加到sem的rlist等待信号量的链表中,然后触发一次schedule(如果到了超时时间也没有信号量可以获取,就会返回获取失败,在没有到超时时间前就有信号量可以获取的话,就会返回成功)*/
            /* reset thread error number */
            smc_thread_current->error_num = SMC_OK;

            /* suspend the current thread and do schedule */
            smc_thread_suspend(smc_thread_current);/*将本任务挂起*/

            if (time_out != SMC_SEM_WAIT_FOREVER) {/*设置超时时间*/
                smc_uint8_t flag = SMC_TIMER_ONCE;

                /* set timer timeout tick */
                smc_timer_command(&smc_thread_current->timer,
                                  SMC_TIMER_SET_TIMEOUT_TICK_IMMEDIATELY,
                                  &time_out);

                /* set timer flag */
                smc_timer_command(&smc_thread_current->timer,
                                  SMC_TIMER_SET_OPERATION_MODE,
                                  &flag);

                /* timer startup */
                smc_timer_enable(&smc_thread_current->timer);
            }

            /* add the current thread to semaphore list */
            smc_list_add(&smc_thread_current->rlist, &sem->slist);/*将本thread添加到sem->rlist等待链表中去*/

            smc_scheduler();

            /* enable interrupt, and will make contex switch */
            smc_cpu_enable_interrupt(status);

            if (smc_thread_current->error_num != SMC_OK)
                return smc_thread_current->error_num;
        }
    }

    return SMC_OK;
}
  • 释放
smc_int32_t smc_sem_release(smc_sem_t *sem)
{
    smc_uint32_t status;

    /* disable interrupt */
    status = smc_cpu_disable_interrupt();
/*根据sem->slist的等待链表是否为空决定是唤醒一个任务还是释放信号量给sem->value自加1*/
    if (!smc_list_is_empty(&sem->slist)) {/*如果sem_rlist为空就resume他头节点指向的thread,先来后到,ucosii是resume等待队列中优先级最高的thread*/
        smc_thread_t *thread;

        thread = smc_list_entry(sem->slist.next, smc_thread_t, rlist);

        /**
         * resume the first thread in the pending thread list waiting for 
         * the special semaphore.
         */
        smc_thread_resume(thread);
    } else {
        sem->value++;
    }

    /* enable interrupt */
    smc_cpu_enable_interrupt(status);

    return SMC_OK;
}

所有关于sem的源代码就这么多,其中没有实现防止信号量翻转的功能,下一步我会去实现这个功能,这部分之后再补充。
还有就是在释放信号量的时候是根据等待队列中哪个thread先申请信号量就唤醒哪个thread,还是唤醒等待队列中优先级最高的thread…没有定论吧,下面想实现两个可以供用户通过宏开关选择的接口。后续补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值