第24章 任务中定时器的设计与实现

来源:互联网 发布:mac装win10会毁电脑吗 编辑:程序博客网 时间:2024/06/07 10:31

目标:实现定时器功能,实现系统调用sleep。


定时器的定义如下所示,系统使用定时器链表管理定时器。

struct timer{    struct task_struct *task;    struct timer *next, *prev;    int time_slice;};struct timer_list{    unsigned long timer_nr;    struct timer *head, *tail;};


任务调用sleep(int ms)函数时,会在定时器链表上插入一个定时器,然后任务挂起。每次时钟中断,内核都会检查定时器链表上的定时器,假如定时器到点,则删除定时器,并唤醒与该定时器关联的任务。定时器插入算法就是遍历链表,算法复杂度为O(n)。定时器检查算法的复杂度为O(1)。
假设
任务A睡20秒
任务B睡5秒
任务C睡9秒
任务D睡2秒
任务E睡14秒
任务F睡40秒
任务 DBCEAF时刻0259142040定时器的时间长度值 2345620


也就是在定时器链表上,第1个定时器的时间值是2秒,对应的任务是D;第2个定时器的时间值是3秒,对应的任务是B;
定时器插入函数如下所示
//把定时器插入到定时器链表中//每个定时器代表一段距离,表示离左边定时器的时间片距离struct timer * add_timer(struct timer *t){   if(!t)      return NULL;   //当定时器链表为空时   if(task_timer_list.head == NULL)   {    task_timer_list.head = task_timer_list.tail = t;    ++task_timer_list.timer_nr;    return t;   }   //当定时器不为空时   struct timer *p = NULL;   p = task_timer_list.head;   while(p && p->time_slice <= t->time_slice)   {    t->time_slice -= p->time_slice;    p = p->next;   }   if(p == task_timer_list.head) //插在最前面   {        p->time_slice -= t->time_slice;    p->prev = t;    t->next = p;    t->prev = NULL;    task_timer_list.head = t;   }   else if(p == NULL) //插在最后面   {    task_timer_list.tail->next = t;    t->prev = task_timer_list.tail;    t->next = NULL;    task_timer_list.tail = t;   }   else  //插在中间   {        p->time_slice -= t->time_slice;        p->prev->next = t;    t->next = p;    t->prev = p->prev;    p->prev = t;       }   ++task_timer_list.timer_nr;   return t;}

定时器检查函数如下所示

void check_timer(){    struct timer *p = NULL , *tmp = NULL;    p = task_timer_list.head;    //检查定时器链表    if(p)    //链表上有定时器    {    //定时器到点    if(--(p->time_slice) == 0)    {        //可能有多个定时器到点        while(p && p->time_slice == 0)        {            if(p->next == NULL)    //只剩下一个定时器        {            task_timer_list.head = task_timer_list.tail = NULL;        }        else     //剩下多个定时器        {           task_timer_list.head = p->next;           task_timer_list.head->prev = NULL;         }                    //定时器的任务为空可能是因为该任务已被删除(sys_remove_task)        //定时器指定的任务有可能已经被其他任务唤醒了(使用resume_task系统调用)        if(p->task && p->task->state == TASK_STATE_SUSPEND)        {            //从挂起队列中移除任务            remove_task_from_suspend(p->task);            //把任务插入到运行队列            insert_task_to_running(p->task, cpu0.expired);        }                    tmp = p;        p = p->next;                //初始化定时器        init_task_timer(tmp);        }    }    }}

timer.c源代码如下所示

#include "asm.h"#include "io.h"#include "idt.h"#include "video.h"#include "kernel.h"#include "8259.h"#include "timer.h"#include "task.h"void init_timer(unsigned int hz){    unsigned int divisor = CLOCK_RATE/hz;    outportb(0x43, 0x36);        //选择计数器0,输出模式3    outportb(0x40, divisor&0xff);   //把初始值的低字节写入LSB中    outportb(0x40, (divisor>>8)&0xff);    //把初始值的高字节写入MSB中}volatile unsigned long  timer_ticks = 0;void do_timer(void){    timer_ticks++;    //检查定时器链表    check_timer();    //管理当前任务的时间片    manage_time_slice();    outportb(M_PIC, EOI);   //告诉PIC1,中断处理函数已经结束,可以处理新来的中断。                //因为定时器是连接到PIC1的IRQ0上,所以不许要通知PIC2    //调度    scheduler();}


最终的task.c源代码如下所示

#include "define.h"#include "task.h"#include "kernel.h"#include "asm.h"#include "video.h"static unsigned long task0_stack[1024] = {0};struct task_struct task0 = {    //tss    {    //back_link    0,    //esp0, ss0    (unsigned int)&(task0_stack[1023]), DATA_SEL,    //esp1, ss1    0, 0,    //esp2, ss2    0, 0,    //cr3    0,    //eip    0,    //eflags    0,    //eax,ecx,edx,ebx    0, 0, 0, 0,    //esp,ebp    0, 0,    //esi,edi    0, 0,    //es,cs,ss,ds,fs,gs    USER_DATA_SEL, USER_CODE_SEL, USER_DATA_SEL, USER_DATA_SEL, USER_DATA_SEL, USER_DATA_SEL,    //ldt    0x20,    //trace_iobitmap    0x0    },    //tss_descriptor    0,    //ldt_descriptor    0,    //ldt[2];    {DEFAULT_LDT_CODE, DEFAULT_LDT_DATA},    //task_function    0,    //stack0    NULL,    //stack3    NULL,    //stack0_size    0,    //stack3_size    0,    //state    TASK_STATE_RUNNING,        //priority    0,    //time_slice    INITIAL_TIME_SLICE,    //pid    0,    //ppid    0,    //next    NULL,    //prev    NULL,    //hnext    NULL,    //hprev    NULL,    //prio_array *    NULL,    //timer    {    //strcut task_struct *task    NULL,    //struct timer *next, *prev    NULL,NULL,    //int slice    0    },    //msgbox    {    //msg_nr    0,    //msg_start    0,    //msg_end    0,    //box    {}    }};struct task_struct *current = &task0;struct run cpu0;static int newpid = 0;static int get_newpid(){    return ++newpid;}unsigned long long set_tss(unsigned long long tss_offset){    unsigned long long tss_descriptor = 0x0000890000000067ULL;    tss_descriptor |= (tss_offset<<16)&0xffffff0000ULL;    tss_descriptor |= (tss_offset<<32)&0xff00000000000000ULL;    return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_TSS] = tss_descriptor;}unsigned long long set_ldt(unsigned long long ldt_offset){    unsigned long long ldt_descriptor = 0x000082000000000fULL;    ldt_descriptor |= (ldt_offset<<16)&0xffffff0000ULL;    ldt_descriptor |= (ldt_offset<<32)&0xff00000000000000ULL;    return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_LDT] = ldt_descriptor;}unsigned long long get_tss(void){    return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_TSS];}unsigned long long get_ldt(void){    return ((unsigned long long *)GDT_ADDR)[CURRUENT_TASK_LDT];}void init_task_timer(struct timer *timer){    if(!timer)    return NULL;    timer->task = NULL;  //表示当前定时器非使用状态    timer->next = timer->prev = NULL;    timer->time_slice = 0;}struct timer_list task_timer_list = {0, NULL, NULL};//初始化定时器链表void init_task_timer_list(){    task_timer_list.timer_nr = 0;    task_timer_list.head = task_timer_list.tail = NULL;}//把定时器插入到定时器链表中//每个定时器代表一段距离,表示离左边定时器的时间片距离struct timer * add_timer(struct timer *t){   if(!t)      return NULL;   //当定时器链表为空时   if(task_timer_list.head == NULL)   {    task_timer_list.head = task_timer_list.tail = t;    ++task_timer_list.timer_nr;    return t;   }   //当定时器不为空时   struct timer *p = NULL;   p = task_timer_list.head;   while(p && p->time_slice <= t->time_slice)   {    t->time_slice -= p->time_slice;    p = p->next;   }   if(p == task_timer_list.head) //插在最前面   {        p->time_slice -= t->time_slice;    p->prev = t;    t->next = p;    t->prev = NULL;    task_timer_list.head = t;   }   else if(p == NULL) //插在最后面   {    task_timer_list.tail->next = t;    t->prev = task_timer_list.tail;    t->next = NULL;    task_timer_list.tail = t;   }   else  //插在中间   {        p->time_slice -= t->time_slice;        p->prev->next = t;    t->next = p;    t->prev = p->prev;    p->prev = t;       }   ++task_timer_list.timer_nr;   return t;}//从定时器链表上移除指定任务的定时器//被sys_delete_task sys_resume_task sys_suspend_task 函数调用void remove_task_timer(struct task_struct *task){    if(!task)    return ;    if(!(task->timer.task))    return ;    //定时器在链表中的位置有三种:表头;表尾;表中间    if(task_timer_list.head == &(task->timer)) //表头    {    if(task_timer_list.tail == &(task->timer))    {        task_timer_list.head = task_timer_list.tail = NULL;    }    else    {        task_timer_list.head = task->timer.next;        task_timer_list.head->prev = NULL;        task_timer_list.head->time_slice += task->timer.time_slice;  //这条语句是必须的    }    }    else if(task_timer_list.tail == &(task->timer))  //表尾    {    task_timer_list.tail = task->timer.prev;    task_timer_list.tail->next = NULL;    }    else  //表中间    {    task->timer.prev->next = task->timer.next;    task->timer.next->prev = task->timer.prev;    task->timer.next->time_slice += task->timer.time_slice;  //这条语句是必须的    }    init_task_timer(&(task->timer));}//添加任务到任务链表尾部void add_task(struct list_pcd * list, struct task_struct *task){        if(list->head == NULL) //队列为空    {    list->head = list->tail = task;    task->next = task->prev = NULL;    }    else    //队列不为空    {    list->tail->next = task;    task->prev = list->tail;    task->next = NULL;    list->tail = task;    }}//从任务链表中删除任务void remove_task(struct list_pcd * list, struct task_struct *task){    //该任务在队列中有三种情况:队头;队尾;队中    if(list->head == task)  //队头    {    if(task->next)//队列有多个任务    {        list->head = task->next;        list->head->prev = NULL;    }    else //队列只有一个任务    {        list->head = list->tail = NULL;    }    }    else if(list->tail == task) //队尾    {    if(task->prev) //队列有多个任务    {        list->tail = task->prev;        list->tail->next = NULL;    }    else //队列只有一个任务    {        list->head = list->tail = NULL;    }    }    else //队中    {    task->prev->next = task->next;    task->next->prev = task->prev;    }    }//把任务插入优先级数组中//被sys_create_task()和manage_time_slice()函数调用//本函数访问共享资源cpu0,因此要保证调用本函数时不能被打断void insert_task_to_running(struct task_struct *task, struct prio_array *py){    //都是把任务插在链表尾部    add_task(py->queue + task->priority, task);    //更新任务结构    task->py = py;    task->state = TASK_STATE_RUNNING;    //更新优先级数组    ++(py->task_nr);    py->bitmap |= (1 << task->priority);}//把任务从优先级数组上移除void remove_task_from_running(struct task_struct* task){    if(task->state != TASK_STATE_RUNNING)    return;    struct list_pcd *list = NULL;    list = (struct list_pcd*)(task->py->queue + task->priority);    //把任务从运行队列中移除    remove_task(list, task);            //更新优先级数组    --(task->py->task_nr);    //假如任务所在的优先级链表已空,则更新优先级位图    if(list->head == NULL)    task->py->bitmap &= ~(1 << task->priority);    }//初始化CPU0,把任务0插入active优先级数组中void init_cpu0(void){    struct list_pcd * list_pcd_ptr = NULL;    int i = 0, j = 0;    for(i = 0; i < 2; i++)    {    cpu0.pa[i].task_nr = 0;    cpu0.pa[i].bitmap = 0x0;    for(j = 0; j < PRIO_NR; j++)    {        cpu0.pa[i].queue[j].head = NULL;        cpu0.pa[i].queue[j].tail = NULL;    }    }        cpu0.active = cpu0.pa;    cpu0.expired = cpu0.pa+1;        //把任务0插入active优先级数组中去,一定要插入active优先级数组,这很重要    insert_task_to_running(&task0, cpu0.active);        //把任务0插到任务HASH表中去    add_task_to_hash(&task0);}void init_tasks(void){    //设置GDT中的TSS和LDT    set_tss((unsigned long long)&(task0.tss));    set_ldt((unsigned long long)&(task0.ldt));    __asm__("ltrw %%ax\n\t"::"a"(TSS_SEL));    __asm__("lldt %%ax\n\t"::"a"(LDT_SEL));    //初始化CPU0,把任务0插入expired优先级数组中    init_cpu0();    //初始化定时器链表    init_task_timer_list();}//系统调用,创建新的任务//返回新任务的PIDint  sys_create_task(unsigned int task_function, unsigned int stack0_size, unsigned int stack3_size){    int pid = 0;    struct task_struct *task = NULL;    void *stack0 = NULL, *stack3 = NULL;    stack0_size = (stack0_size ? stack0_size : DEFAULT_STACK_SIZE);    stack3_size = (stack3_size ? stack3_size : DEFAULT_STACK_SIZE);    task = (struct task_struct *)malloc(sizeof(struct task_struct));    stack0 = malloc(stack0_size);    stack3 = malloc(stack3_size);    if(!task || !stack0 || !stack3)    {    free(task);    free(stack0);    free(stack3);    return -1;    }    *task = task0;    task->tss.esp0 = stack0 + stack0_size;    task->tss.eip = task_function;    //task->tss.eflags = 0x3202;    // I(中断位)=1,使能INTR引脚,开中断                        // IOPL(i/o优先级)=3,当任务的优先级高于或等于IOPL时,I/O指令才能顺利执行。    task->tss.eflags = 0x202;        //不需要设置IOPL了,通过系统调用执行I/O指令    task->tss.esp = stack3 + stack3_size;    task->task_function = task_function;    task->stack0 = stack0 + stack0_size;    task->stack3 = stack3 + stack3_size;    task->stack0_size = stack0_size;    task->stack3_size = stack3_size;    task->state = TASK_STATE_RUNNING;    //设置时间片    task->time_slice = INITIAL_TIME_SLICE;    //设置PID和PPID    pid = task->pid = get_newpid();    task->ppid = current->pid;    //设置优先级    task->priority = ( task->pid % PRIO_NR);    //task->priority = INITIAL_PRIO;    //初始化定时器    init_task_timer(&(task->timer));    //初始化任务的信箱    task->msgbox.msg_nr = 0;    task->msgbox.msg_start = task->msgbox.msg_end = 0;    //插入到cpu0中的expired优先级数组中    cli();    insert_task_to_running(task, cpu0.expired);        //插到任务HASH表中    add_task_to_hash(task);    sti();    return pid;}//计算当前任务的时间片,假如当前任务的时间片用完,则从新分配时间片,并把任务插入到expired优先级数组中//这里存在一个假设,即当前任务是所在优先级队列的第一个任务;//本函数需要访问共享资源cpu0,因此需要保证该调用该函数时不能被打断void manage_time_slice(void){    struct list_pcd * list_pcd_ptr = NULL;    list_pcd_ptr = cpu0.active->queue + current->priority;  //指向当前任务所在的优先级队列    //计算当前任务的时间片    if(--current->time_slice > 0) //当前任务还有时间片    {    if(list_pcd_ptr->head != list_pcd_ptr->tail) //该优先级上还有>1个任务    {        //轮转算法,把当前任务插到队尾        list_pcd_ptr->head = current->next;        list_pcd_ptr->tail->next = current;        current->prev = list_pcd_ptr->tail;        list_pcd_ptr->tail = current;        current->next = NULL;        list_pcd_ptr->head->prev = NULL;    }    }    else  //当前任务没有时间片,从队列中摘掉该任务    {    //摘取当前任务    if(list_pcd_ptr->head != list_pcd_ptr->tail) //该优先级上还有>1个任务    {        list_pcd_ptr->head = current->next;        list_pcd_ptr->head->prev = NULL;    }    else    //该优先级上只有当前任务    {        list_pcd_ptr->head = list_pcd_ptr->tail = NULL;        //更新优先级数组位图        cpu0.active->bitmap &= ~(1 << current->priority);    }    //更替新优先级数组    --(cpu0.active->task_nr);    //重新给任务分配时间片    current->time_slice = INITIAL_TIME_SLICE;    //把任务插入expired优先级数组中    insert_task_to_running(current,cpu0.expired);    }}static inline unsigned long  sched_find_first_bit(const unsigned long word){    unsigned long index = word;    __asm__ ("bsfl %1, %0 \n\t" \    :"=r"(index):"rm"(index));    return index;}//时间片轮转调度算法//本函数需要访问共享资源cpu0,因此需要保证该调用该函数时不能被打断,该函数必须在临界区内,不能开中断。//而且scheduler调用的函数也不能开中断void scheduler(void){    struct task_struct *v = NULL;    struct list_pcd * list_pcd_ptr = NULL;    struct prio_array *py = NULL;    unsigned long index = 0;    //加入active优先级数组中没有可运行的任务,则调换active和expired的指针。    py = cpu0.active;    if(py->task_nr == 0)    {    cpu0.active = cpu0.expired;    cpu0.expired = py;    py = cpu0.active;    }    if(py->task_nr == 0)    {        sys_kprint(char_attr(BLACK,RED),"\tScheduler Error: no running task in priority array.\n");        while(1);    }    //在active优先级数组中找到具有任务的优先级最高的任务队列,取得任务队列的头个任务    index = sched_find_first_bit(py->bitmap);    list_pcd_ptr = py->queue + index;    v = list_pcd_ptr->head;    if(v != current)    {    current->tss_descriptor = get_tss();    current->ldt_descriptor = get_ldt();    v->tss_descriptor = set_tss((unsigned long long)&(v->tss));    v->ldt_descriptor = set_ldt((unsigned long long)&(v->ldt));    current = v;    __asm__ volatile("ljmp  {1}quot; TSS_SEL_STR ", $0\n\t");    }}//挂起任务队列struct task_list suspend_tasks;//死亡任务队列struct task_list  dead_tasks;void init_suspend_tasks(){    suspend_tasks.task_nr = 0;    suspend_tasks.list.head = NULL;    suspend_tasks.list.tail = NULL;}void init_dead_tasks(){    dead_tasks.task_nr = 0;    dead_tasks.list.head = NULL;    dead_tasks.list.tail = NULL;}//插入任务到挂起任务队列队尾void insert_task_to_suspend(struct task_struct *task){    task->state = TASK_STATE_SUSPEND;    add_task(&(suspend_tasks.list), task);    ++suspend_tasks.task_nr;}//插入任务到死亡任务队列队尾void insert_task_to_dead(struct task_struct *task){    task->state = TASK_STATE_DEAD;    add_task(&(dead_tasks.list), task);    ++dead_tasks.task_nr;}//从挂起任务队列中删除指定的任务void remove_task_from_suspend(struct task_struct *task){    if(task->state != TASK_STATE_SUSPEND)    return ;    remove_task(&(suspend_tasks.list), task);    --suspend_tasks.task_nr;}void remove_task_from_dead(struct task_struct *task){    if(task->state != TASK_STATE_DEAD)    return ;    remove_task(&(dead_tasks.list), task);    --dead_tasks.task_nr;}struct task_hash tasks_hash;void init_tasks_hash(){    tasks_hash.task_nr = 0;    int i = 0;    for(i = 0; i < TASK_HASH_NR;i++)    {    tasks_hash.table[i].head = tasks_hash.table[i].tail = NULL;    }}void add_task_to_hash(struct task_struct *task){        struct list_pcd *list = NULL;    list = &(tasks_hash.table[task->pid%TASK_HASH_NR]);    if(list->head == NULL) //队列为空    {    list->head = list->tail = task;    task->hnext = task->hprev = NULL;    }    else    //队列不为空    {    list->tail->hnext = task;    task->hprev = list->tail;    task->hnext = NULL;    list->tail = task;    }    ++tasks_hash.task_nr;}void remove_task_from_hash(struct task_struct *task){    struct list_pcd *list = NULL;    list = &(tasks_hash.table[task->pid%TASK_HASH_NR]);    //该任务在队列中有三种情况:队头;队尾;队中    if(list->head == task)  //队头    {    if(task->hnext)//队列有多个任务    {        list->head = task->hnext;        list->head->hprev = NULL;    }    else //队列只有一个任务    {        list->head = list->tail = NULL;    }    }    else if(list->tail == task) //队尾    {    if(task->hprev) //队列有多个任务    {        list->tail = task->hprev;        list->tail->hnext = NULL;    }    else //队列只有一个任务    {        list->head = list->tail = NULL;    }    }    else //队中    {    task->hprev->hnext = task->hnext;    task->hnext->hprev = task->hprev;    }        --tasks_hash.task_nr;    }struct task_struct * query_task_from_hash(int pid){    struct task_struct *t;    t = tasks_hash.table[pid%TASK_HASH_NR].head;    for(; t; t = t->hnext )    {    if(t->pid == pid)        return t;        }    return NULL;}//挂起任务//该函数访问共享资源,因此需要关中断int sys_suspend_task(int pid){    int ret = 0;    struct task_struct *task = NULL;    cli();    if(pid < 0)    {    ret = 1;    goto end;    }        //查询是否存在这个pid的任务    task = query_task_from_hash(pid);    if(!task)    {    ret = 2;    goto end;    }        //判断该任务的状态,是否是RUNNING态    if(task->state != TASK_STATE_RUNNING)    {    ret = 3;    goto end;    }    //把该任务从运行队列移除    remove_task_from_running(task);            //把该任务添加到挂起队列    insert_task_to_suspend(task);        //判断当前运行队列是否为空,假如为空则唤醒任务0    if(cpu0.active->task_nr == 0 && cpu0.expired->task_nr == 0)    {    //把该任务从挂起队列删除    remove_task_from_suspend(&task0);        //删除任务0上的定时器    remove_task_timer(&task0);            //把该任务添加到运行队列    insert_task_to_running(&task0, cpu0.expired);    }    //判断该PID是否是当前任务的PID    if(task == current)    {    scheduler();    }    end:    sti();    return ret;}//把任务从挂起态唤醒//该函数访问共享资源,因此需要关中断int sys_resume_task(int pid){    int ret = 0;    struct task_struct *task = NULL;    cli();    if(pid < 0)    {    ret = 1;    goto end;    }        //查询是否存在这个pid的任务    task = query_task_from_hash(pid);    if(!task)    {    ret = 2;    goto end;    }        //判断该任务的状态,是否是SUSPEND态    if(task->state != TASK_STATE_SUSPEND)    {    ret = 3;    goto end;    }    //把该任务从挂起队列删除    remove_task_from_suspend(task);        //删除任务上的定时器    remove_task_timer(task);        //把该任务添加到运行队列    insert_task_to_running(task, cpu0.expired);        end:    sti();    return ret;}//删除任务//该函数访问共享资源,因此需要关中断int sys_delete_task(int pid){    int ret = 0;    struct task_struct *task = NULL;    cli();    if(pid <= 0)  //不能删除任务0,因为任务0有回收死亡任务的作用      {    ret = 1;    goto end;    }        //查询是否存在这个pid的任务    task = query_task_from_hash(pid);    if(!task)    {    ret = 2;    goto end;    }        //判断该任务的状态    switch(task->state)    {    case TASK_STATE_RUNNING:        //把该任务从运行队列移除        remove_task_from_running(task);            break;    case TASK_STATE_SUSPEND:        //把该任务从挂起队列删除        remove_task_from_suspend(task);        break;    case TASK_STATE_DEAD:        ret = 3;        goto end;        break;    default:        break;    }        //删除该任务上的定时器    remove_task_timer(task);    //把该任务添加到死亡队列    insert_task_to_dead(task);    //判断当前运行队列是否为空,假如为空则唤醒任务0    if(cpu0.active->task_nr == 0 && cpu0.expired->task_nr == 0)    {    //把该任务从挂起队列删除    remove_task_from_suspend(&task0);            //删除任务0上的定时器    remove_task_timer(&task0);        //把该任务添加到运行队列    insert_task_to_running(&task0, cpu0.expired);    }        //判断该PID是否是当前任务的PID    if(task == current)    {    scheduler();    }    end:    sti();    return ret;}//移除死亡任务,从任务HASH表上删除,并释放任务所占的资源(比如内存)//该函数访问共享资源,因此需要关中断int sys_clear_dead_task(){    //关中断    cli();    int ret = 0;        //查看死亡队列是否为空    if(dead_tasks.list.head == NULL)    {    ret = 1;    goto end;    }    //遍历死亡队列    struct task_struct *p = dead_tasks.list.head;    struct task_struct *tmp = NULL;    while(p)    {    printf("clear dead task pid=%d\n", p->pid);    //从hash表中移除该任务    remove_task_from_hash(p);    //从死亡队列中移除该任务    remove_task_from_dead(p);        //回收死亡任务所占的资源    //回收内存    free((void*)(p->stack0 - p->stack0_size));    free((void*)(p->stack3 - p->stack3_size));    tmp = p;    p = p->next;    free((void*)tmp);    }end:    //开中断    sti();    return ret;}//睡眠函数,已ms为单位 1s = 1000ms//参数ms == 0时表示该任务需要挂起,然后等待其他任务唤醒int sys_sleep(int ms){    int ret = 0;    if(ms < 0)        return 1;    //先把睡眠时间转换为时间片    int time_slice = 0;    time_slice = ms*HZ/1000;    if(time_slice == 0)    time_slice = 1;    //初始化定时器    current->timer.task = current;    current->timer.next = current->timer.prev = NULL;    current->timer.time_slice = time_slice;    //关中断    cli();    //把定时器插入定时器链表    add_timer(&(current->timer));    //调用sys_suspend_task函数,把自己挂起    ret = sys_suspend_task(current->pid);    //开中断    sti();    return ret;}void check_timer(){    struct timer *p = NULL , *tmp = NULL;    p = task_timer_list.head;    //检查定时器链表    if(p)    //链表上有定时器    {    //定时器到点    if(--(p->time_slice) == 0)    {        //可能有多个定时器到点        while(p && p->time_slice == 0)        {            if(p->next == NULL)    //只剩下一个定时器        {            task_timer_list.head = task_timer_list.tail = NULL;        }        else     //剩下多个定时器        {           task_timer_list.head = p->next;           task_timer_list.head->prev = NULL;         }                    //定时器的任务为空可能是因为该任务已被删除(sys_remove_task)        //定时器指定的任务有可能已经被其他任务唤醒了(使用resume_task系统调用)        if(p->task && p->task->state == TASK_STATE_SUSPEND)        {            //从挂起队列中移除任务            remove_task_from_suspend(p->task);            //把任务插入到运行队列            insert_task_to_running(p->task, cpu0.expired);        }                    tmp = p;        p = p->next;                //初始化定时器        init_task_timer(tmp);        }    }    }}int sys_send_msg(int pid, struct msg *msg){        int ret = 0;    struct task_struct *task = NULL;    cli();    if(pid < 0 || !msg)    {    ret = 1;    goto end;    }        //查询是否存在这个pid的任务    task = query_task_from_hash(pid);    if(!task)    {    ret = 2;    goto end;    }    //查看任务的信箱是否有空位    if(task->msgbox.msg_nr < TASK_MSG_NR) //有空位    {    //复制消息到任务的信箱的空位中    task->msgbox.msg_end = ++(task->msgbox.msg_end)%TASK_MSG_NR;    task->msgbox.box[task->msgbox.msg_end] = *msg;    //消息数目增1    ++(task->msgbox.msg_nr);     }    else //无空位    {    ret = 3;    goto end;    }end:    sti();    return ret;}int sys_receive_msg(struct msg *msg){    int ret = 0;    cli();    if(!msg)    {    ret = 1;    goto end;    }    //查看任务的信箱是否有消息    if(current->msgbox.msg_nr > 0) //有消息    {    //复制任务信箱中的消息到msg中    current->msgbox.msg_start = ++(current->msgbox.msg_start)%TASK_MSG_NR;        *msg =     current->msgbox.box[current->msgbox.msg_start];    //消息数目减1    --(current->msgbox.msg_nr);     }    else //无消息    {    ret = 2;    goto end;    }end:    sti();    return ret;}


原创粉丝点击