加入了基于简单优先级的任务调度,看着好像跟时间片轮转没什么区别


int k_reenter = -1;
// Descriptor

typedef struct descriptor {
	short limit_low;
	short base_low;
	char base_mid;
	char access_right;
	char limit_high;
	char base_high;
}descriptor, *Descriptor;

typedef struct gate {
	short offset_low;
	short selector;
	char dw_count;
	char access_right;
	short offset_high;
}gate, *Gate;

// start process data struct

typedef struct tss {
	int backlink;
	int esp0;
	int ss0;
	int esp1;
	int ss1;
	int esp2;
	int ss2;
	int cr3;
	int eip;
	int eflags;
	int eax;
	int ecx;
	int edx;
	int ebx;
	int esp;
	int ebp;
	int esi;
	int edi;
	int es;
	int cs;
	int ss;
	int ds;
	int fs;
	int gs;
	int ldt_sel;
	short trap;
	short iobase;
}tss, *Tss;

typedef struct proc_stack {
	int gs;
	int fs;
	int es;
	int ds;
	int edi;
	int esi;
	int ebp;
	int kernel_esp;
	int ebx;
	int edx;
	int ecx;
	int eax;
	int retaddr;
	int eip;
	int cs;
	int eflags;
	int esp;
	int ss;
}proc_stack;

typedef struct process {
	proc_stack procstack;
	
	short ldt_selector;
	descriptor ldt[0x10];
	int pid;
	char name[32];
	unsigned int ticks;
	unsigned int priority;
}process, *Process;

// end process data struct


void print_s(char *str, char color, int j);
void halt(void);

void delay(int count);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
void asm_inthandler_all(void);
void asm_inthandler_0xd(void);
void asm_inthandler_0x20(void);
void asm_inthandler_0x21(void);
void ud2(void);

void testa(void);
void testb(void);
void testc(void);
void testd(void);
void teste(void);
void testf(void);
void testg(void);
void testh(void);

void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib);
void set_gate(Gate gd, int offset, int selector, int attrib);

// S:copy from multiboot2 os example.
#define COLUMNS 80
#define LINES 24
#define ATTRIBUTE 7
#define VIDEO 0xb8000
     
static int xpos;
static int ypos;
static volatile unsigned char *video;
     
static void cls (void);
static void itoa (char *buf, int base, int d);
static void putchar (int c);
void printf (const char *format, ...);


void out(int port, int value);
int in(int port);
void sti(void);
void cli(void);
void init_8259a(void);
void init_8254(void);

int mycount = 0;

char *func_stack = (char *)0x800000;

process p_proc[8];
Process p_proc_ready, myproc;
tss tss0;
Tss mytss = &tss0;


typedef void (*task_f)(void);

typedef struct s_task {
	task_f initial_eip;
	int stacksize;
	char name[0x20];
}task, *Task;

task task_table[8] = {{testa, 0x400, "testa"}, \
					  {testb, 0x400, "testb"}, \
					  {testc, 0x400, "testc"}, \
					  {testd, 0x400, "testd"}, \
					  {teste, 0x400, "teste"}, \
					  {testf, 0x400, "testf"}, \
					  {testg, 0x400, "testg"}, \
					  {testh, 0x400, "testh"}};
					  

void goto_ring3(void);
void ltr(int tr);
void init_tss(Tss mytss, Descriptor mygdt);
void init_proc_table(Process myproc, Task mytask, Descriptor mygdt);
void schedule(Process p);

int kernel_main(int eax, int ebx) {
	cls();	
	
	Process myproc;
	myproc = p_proc;
	
	Descriptor mygdt = (Descriptor) 0x7c00;
	Gate myidt = (Gate) 0x0;
	set_descriptor(mygdt + 0, 0, 0, 0); //0 * 8
	set_descriptor(mygdt + 1, 0xffffffff, 0x0, 0xc09a); //1 * 8
	set_descriptor(mygdt + 2, 0xffffffff, 0x0, 0xc092); //2 * 8
	load_idtr(256 * 8 - 1, (int) myidt);
	load_gdtr(256 * 8 - 1, (int) mygdt);
	
	Task p_task = task_table;
	init_proc_table(myproc, p_task, mygdt);
	int i;

	for(i = 0; i < 256; i++) {
		set_gate(myidt + i, (int) asm_inthandler_all, 0x8, 0x8e);
	}
	set_gate(myidt + 0xd, (int) asm_inthandler_0xd, 0x8, 0x8e);	
	set_gate(myidt + 0x20, (int) asm_inthandler_0x20, 1 * 8, 0x8e);
	set_gate(myidt + 0x21, (int) asm_inthandler_0x21, 1 * 8, 0x8e);
//	set_gate(myidt + 0x80, (int) system_interrupt, 1 * 8, 0xee);


	init_tss(mytss, mygdt);
	
	init_8259a();
	init_8254();
	
	out(0x21, 0xf8);
	out(0xa1, 0xff);
	p_proc_ready = p_proc;
	goto_ring3();
	
	
	while(1) {
			print_s("Sys!", 0xf, 17);
	}
	return 0;
}

void print_s(char *str, char color, int j) {
	int i = 0;
	while(*str) {
		while(*str == '\n') {
			str++;
			i = 0;
			j++;
		}
		if(!(*str)) {
			return;
		}
		*(video + i + j * 80 * 2) = *str++;
		*(video + i + 1 + j * 80 * 2) = color;
		i += 2;
	}
	return;
}
 
 
/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
static void cls (void) {
	int i;
	video = (unsigned char *) VIDEO;
	for (i = 0; i < COLUMNS * LINES * 2; i++)
		*(video + i) = 0;
	xpos = 0;
	ypos = 0;
	return;
}
     
/*  Convert the integer D to a string and save the string in BUF. If
BASE is equal to 'd', interpret that D is decimal, and if BASE is
equal to 'x', interpret that D is hexadecimal. */
static void itoa (char *buf, int base, int d) {
	char *p = buf;
	char *p1, *p2;
	unsigned long ud = d;
	int divisor = 10;

/*  If %d is specified and D is minus, put `-' in the head. */
	if (base == 'd' && d < 0) {
		*p++ = '-';
		buf++;
		ud = -d;
	}
	else if (base == 'x')
		divisor = 16;

/*  Divide UD by DIVISOR until UD == 0. */
	do {
		int remainder = ud % divisor;
		*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
	} while (ud /= divisor);

/*  Terminate BUF. */
	*p = 0;

/*  Reverse BUF. */
	p1 = buf;
	p2 = p - 1;
	while (p1 < p2) {
		char tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2--;
	}
}

/*  Put the character C on the screen. */
static void putchar (int c) {
	if (c == '\n' || c == '\r') {
newline:
		xpos = 0;
		ypos++;
		if (ypos >= LINES)
			ypos = 0;
		return;
	}

	*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
	*(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;

	xpos++;
	if (xpos >= COLUMNS)
		goto newline;
}
     
/*  Format a string and print it on the screen, just like the libc
function printf. */
void printf (const char *format, ...) {
	char **arg = (char **) &format;
	int c;
	char buf[20];
	arg++;

	while ((c = *format++) != 0) {
		if (c != '%')
			putchar (c);
		else {
			char *p, *p2;
			int pad0 = 0, pad = 0;
			c = *format++;
			if (c == '0') {
				pad0 = 1;
				c = *format++;
			}

			if (c >= '0' && c <= '9')
				{
				pad = c - '0';
				c = *format++;
				}

			switch (c) {
				case 'd':
				case 'u':
				case 'x':
					itoa (buf, c, *((int *) arg++));
					p = buf;
					goto string;
					break;
				case 's':
					p = *arg++;
					if (! p)
					p = "(null)";
string:
					for (p2 = p; *p2; p2++);
					for (; p2 < p + pad; p2++)
					putchar (pad0 ? '0' : ' ');
					while (*p)
					putchar (*p++);
					break;
				default:
					putchar (*((int *) arg++));
					break;
			}
		}
	}
}

void *memcpy(void *dest, void *source, int count) {
	int i;
	void *temp = dest;
	for(i = 0; i < count; i++) {
		 *((char *)dest++) = *((char *)source++);
	}
	return temp;
}

void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib) {
	if(limit > 0xfffff) {
		attrib |= 0x8000;
		limit /= 0x1000;
	}
	sd->limit_low = limit & 0xffff;
	sd->base_low = base & 0xffff;
	sd->base_mid = (base >> 16) & 0xff;
	sd->access_right = attrib & 0xff;
	sd->limit_high = ((limit >> 16) & 0x0f) | ((attrib >> 8) & 0xf0);
	sd->base_high = (base >> 24) & 0xff;
	return;
}

void set_gate(Gate gd, int offset, int selector, int attrib) {
	gd->offset_low = offset & 0xffff;
	gd->selector = selector;
	gd->dw_count = (attrib >> 8) & 0xff;
	gd->access_right = attrib & 0xff;
	gd->offset_high = (offset >> 16) & 0xffff;
	return;
}

void inthandler_all(int *esp) {
	printf("Exception! 0x%x", esp);
	while(1) {
		halt();
	}
	return;
}

void inthandler_0xd(int *esp) {
	printf("general protection! 0x%x", esp);
	while(1) {
		halt();
	}
	return;
}




void inthandler_0x21(int *esp) {
	out(0x20, 0x61);
	int key = in(0x60);
	char buf[0x40];
	print_s("keyboard interrupt!", 0xf, 21);
	print_s("     ", 0xf, 22);
	itoa(buf, 10, key);
	print_s(buf, 0xf, 22);
	return;
}


int ia = 0;
void testa(void) {
	char buf[0x20];
	while (1) {
		print_s("testa", 0x9, 0);
		itoa(buf, 10, ia++);
		print_s(buf, 0x9, 1);
//		delay(0xfffff);
	}
	return;
}

int ib = 0;
void testb(void) {
	char buf[0x20];
	while (1) {
		print_s("testb", 0xd, 2);
		itoa(buf, 10, ib++);
		print_s(buf, 0xd, 3);
//		delay(0xfff);
	}
	return;
}

int ic = 0;
void testc(void) {
	char buf[0x20];
	while (1) {
		print_s("testc", 0xf, 4);
		itoa(buf, 10, ic++);
		print_s(buf, 0xf, 5);
//		delay(0x888);
	}
	return;
}

int id = 0;
void testd(void) {
	char buf[0x20];
	while (1) {
		print_s("testd", 0xe, 6);
		itoa(buf, 10, id++);
		print_s(buf, 0xe, 7);
//		delay(0x88);

	}
	return;
}

int ie = 0;
void teste(void) {
	char buf[0x20];
	while (1) {
		print_s("teste", 0x4, 8);
		itoa(buf, 10, ie++);
		print_s(buf, 0x4, 9);
//		delay(0xffff);

	}
	return;
}

int iff = 0;
void testf(void) {
	char buf[0x20];
	while (1) {
		print_s("testf", 0x8, 10);
		itoa(buf, 10, iff++);
		print_s(buf, 0x8, 11);
//		delay(0xf);

	}
	return;
}

int ig = 0;
void testg(void) {
	char buf[0x20];
	while (1) {
		print_s("testg", 0x6, 12);
		itoa(buf, 10, ig++);
		print_s(buf, 0x6, 13);
//		delay(0xaaaaa);

	}
	return;
}

int ih = 0;
void testh(void) {
	char buf[0x20];
	while (1) {
		print_s("testh", 0x7, 14);
		itoa(buf, 10, ih++);
		print_s(buf, 0x7, 15);
//		delay(0xccc);

	}
	return;
}



void init_8254(void) {
	out(0x43, 0x36);
	out(0x40, 0x9c);
	out(0x40, 0x2e);
	return;
}


void init_proc_table(Process myproc, Task mytask, Descriptor mygdt) {
	int i;
	for(i = 0; i < 8; i++) {
		myproc->ticks = myproc->priority = 2 + i;
		myproc->pid = i;
		myproc->ldt_selector = (3 + i) * 8;
		set_descriptor(mygdt + (3 + i), 8 * 0x10 - 1, (int)myproc->ldt, 0xc0e2);
		set_descriptor(myproc->ldt + 0, 0xffffffff, 0x0, 0xc0fa); //0 * 8 + 7
		set_descriptor(myproc->ldt + 1, 0xffffffff, 0x0, 0xc0f2); //1 * 8 + 7
		myproc->procstack.gs = 0xf;
		myproc->procstack.fs = 0xf;
		myproc->procstack.es = 0xf;
		myproc->procstack.ds = 0xf;	
		myproc->procstack.edi = 0x0;
		myproc->procstack.esi = 0x0;
		myproc->procstack.ebp = 0x0;
		myproc->procstack.kernel_esp = 0;	
		myproc->procstack.ebx = 0x0;
		myproc->procstack.edx = 0x0;
		myproc->procstack.ecx = 0x0;
		myproc->procstack.eax = 0x0;
		myproc->procstack.retaddr = 0x0;	
		myproc->procstack.eip = (int)mytask->initial_eip;
		myproc->procstack.cs = 0x7;
		myproc->procstack.eflags = 0x202;
		myproc->procstack.esp = (int)func_stack;
		myproc->procstack.ss = 0xf;
		
		myproc++;
		mytask++;
		func_stack -= 0x400;
	}
	return;
}

void init_tss(Tss mytss, Descriptor mygdt) {
	set_descriptor(mygdt + 20, sizeof(tss0), (int)mytss, 0xc0e9); //20 * 8
	mytss->backlink = 0;
	mytss->esp0 = 0;
	mytss->ss0 = 2 * 8;
	mytss->esp1= 0;
	mytss->ss1 = 0;
	mytss->esp2 = 0;
	mytss->ss2 = 0;
	mytss->cr3 = 0;
	mytss->eflags = 0;
	mytss->eax = 0;
	mytss->ecx = 0;
	mytss->edx = 0;
	mytss->esp = 0;
	mytss->ebp = 0;
	mytss->esi = 0;
	mytss->edi = 0;
	mytss->es = 0xf;
	mytss->cs = 0x7;
	mytss->ss = 0xf;
	mytss->ds = 0xf;
	mytss->fs = 0xf;
	mytss->gs = 0xf;
	mytss->ldt_sel = 0;
	mytss->trap = 0;
	mytss->iobase = sizeof(tss);
	ltr(20 * 8);
	return;
}

void inthandler_0x20(int *esp) {
	char buf[0x40];
	print_s("timer interrupt!", 0xc, 23);
	itoa(buf, 10, mycount++);
	print_s(buf, 0xc, 24);

	p_proc_ready->ticks--;
	if(p_proc_ready->ticks > 0)
		return;
	schedule(p_proc);
	return;
}

void schedule(Process p) {
//	p_proc_ready++;  // 时间片轮转法
//	if(p_proc_ready >= p_proc + 8)
//		p_proc_ready = p_proc;
	int myticks = 0; // 简单优先级法
	while(!myticks) {
		for(p = p_proc; p < p_proc + 8; p++) {
			if(p->ticks > myticks) {
				myticks = p->ticks;
				p_proc_ready = p;
			}
		}
		if(!myticks) {
			for(p = p_proc; p < p_proc + 8; p++) {
				p->ticks = p->priority;
			}
		}
	}
	return;
}

猜你喜欢

转载自blog.csdn.net/weixin_39410618/article/details/84593745