/*
OS Scheduler Simulator
** 連絡先: 琉球大学情報工学科 河野 真治
** (E-Mail Address: kono@ie.u-ryukyu.ac.jp)
**
** このソースのいかなる複写,改変,修正も許諾します。ただし、
** その際には、誰が貢献したを示すこの部分を残すこと。
** 再配布や雑誌の付録などの問い合わせも必要ありません。
** 営利利用も上記に反しない範囲で許可します。
** バイナリの配布の際にはversion messageを保存することを条件とします。
** このプログラムについては特に何の保証もしない、悪しからず。
**
** Everyone is permitted to do anything on this program
** including copying, modifying, improving,
** as long as you don't try to pretend that you wrote it.
** i.e., the above copyright notice has to appear in all copies.
** Binary distribution requires original version messages.
** You don't have to ask before copying, redistribution or publishing.
** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
Simple Event Driven Simulator
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "queue.h"
#include "event.h"
#include "task.h"
static int by_period(QueuePtr q,QueuePtr r);
static char buf[BUFSIZ];
static EventPtr rate_monotonic(EventPtr task,QueuePtr *queue_ptr,int quantum);
static void simulate(EventPtr task,int limit);
static int get_quantum(EventPtr list);
static int limit = 400;
int
main()
{
int time; char name[BUFSIZ]; int length; int priority;
EventPtr task_list = NULL;
QueuePtr q,queue;
char *name1;
char type;
int period;
init_queue(100);
init_event(100);
task_count = 0;
while(fgets(buf,BUFSIZ,stdin)!=NULL) {
if (buf[0]=='#') continue;
if (buf[0]!='p') continue;
sscanf(buf,"%c %d %s %d %d %d",
&type,&time,name,&length,&priority,&period);
if ((name1=malloc(strlen(name)))==0) {
die("Can't allocate name\n");
}
strcpy(name1,name);
q = new_queue(name1, length, priority);
if (!q) {
die("Can't allocate queue\n");
}
q->type = type;
q->period = period;
q->task_length = length;
q->length = 0; /* not missed at first time */
queue = append_queue(queue,q);
task_count++;
}
queue = sort_queue(queue,by_period);
task_list = new_event(0, rate_monotonic, &queue);
if (!task_list) {
die("Can't allocate task\n");
}
simulate(task_list,limit);
printf("%d\tend:\n",task_clock);
return 0;
}
static void
simulate(EventPtr task,int limit)
{
EventPtr e;
int quantum;
while(task) {
task=get_event(task,&e);
task_clock = e->time;
if (limit && task_clock>limit) {
break;
}
quantum = get_quantum(task);
task = e->event(task,e->param,quantum);
free_event(e);
}
}
int
get_quantum(EventPtr list)
{
if (!list) {
return 0;
} else {
return list->time - task_clock;
}
}
static EventPtr
rate_monotonic(EventPtr task,QueuePtr *queue_ptr,int quantum)
{
QueuePtr q;
// task が優先度順に並んでいるとする
// 再投入を先にチェックして、一番短いquantumを見つける
for(q= *queue_ptr;q;q=q->next) {
if (q->type!='p') continue;
// もし、再投入時間ならば再投入する
if (q->next_time==task_clock) {
q->next_time=task_clock+q->period;
task = insert_event1(task,
new_event(q->next_time, rate_monotonic, queue_ptr));
if (quantum==0 || quantum > q->period) quantum = q->period;
if (q->length>0) {
report_dead_line_miss(q);
}
q->length = q->task_length;
}
}
for(q= *queue_ptr;q;q=q->next) {
if (q->type!='p') continue;
// 一番優先順位が高いものを実行する
if (q->length) {
quantum -= exec_task(q,quantum);
if (quantum <= 0)
return task;
}
}
/* other task (may be non-periodic one ) */
return task;
}
static int by_period(QueuePtr q,QueuePtr r)
{
return q->period > r->period;
}
/* end */