目标:实现定时器功能,实现系统调用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秒
任务 | D | B | C | E | A | F | |
时刻 | 0 | 2 | 5 | 9 | 14 | 20 | 40 |
定时器的时间长度值 | 2 | 3 | 4 | 5 | 6 | 20 |
也就是在定时器链表上,第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();
}
//系统调用,创建新的任务
//返回新任务的PID
int 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;
}