最近在调试的过程中,发现进程或者线程的运行级别被改变。通过仔细研究进程调度程序还有相关阻塞(休眠)和唤醒函数,终于有了小小的发现。
同时在kernel.c中加入了新的信号量代码,从而简单地实现了线程的同步。
不过,系统调用却出现了问题,暂时真的不知道怎么处理。
void schedule(void) {
ASSERT((intr_get_status() == INTR_OFF));
struct task* cur = running_thread();
if(cur->status == RUNNING) {
ASSERT(!elem_find(thread_ready_list, &cur->general_tag));
// 处理器上运行的当前线程将被加入到就绪队列,这里要根据线程的
// 运行级别加入到相应的级别链表中
thread_ready_list = &ready_list[cur->level];
list_append(thread_ready_list, &cur->general_tag);
cur->ticks = cur->priority;
cur->status = READY;
} else {
}
int i;
for(i = 0; i < 8; i++) {
thread_ready_list = &ready_list[i];
if(!list_empty(thread_ready_list)) {
break;
}
}
ASSERT(!list_empty(thread_ready_list));
thread_tag = list_pop(thread_ready_list);
struct task* next = elem2entry(struct task, general_tag, thread_tag);
next->status = RUNNING;
process_activate(next);
switch_to(cur, next);
}
void thread_unblock(struct task* pthread) {
enum intr_status old_status = intr_disable();
// ASSERT(((pthread->status == BLOCKED) ||
// (pthread->status == HANDING) ||
// (pthread->status == WAITING)));
if(pthread->status != READY) {
ASSERT(!(elem_find(thread_ready_list, &pthread->general_tag)));
if(elem_find(thread_ready_list, &pthread->general_tag)) {
PANIC("thread_unblock: blocked thread in ready_list\n");
}
// 这里也是有同样的问题
thread_ready_list = &ready_list[pthread->level];
list_push(thread_ready_list, &pthread->general_tag);
pthread->status = READY;
}
intr_set_status(old_status);
}
void yield(void) {
enum intr_status old_status = intr_disable();
struct task* cur = running_thread();
ASSERT(!elem_find(thread_ready_list, &cur->general_tag));
// 还有这里
thread_ready_list = &ready_list[cur->level];
list_append(thread_ready_list, &cur->general_tag);
cur->status = READY;
schedule();
intr_set_status(old_status);
}
// kernel.c
// 全局描述表的基地址是0x6000,大小为256 * 8 - 1。
// 中断描述符表的基地址是0x7000,大小为256 * 8 - 1。
// 内核页目录表的基地址是0x8000,占用1个页。
// 内核页表的基地址是0x9000,共占用8个页。
#include "x.h"
#include "string.h"
#include "multiboot2.h"
#include "gdt_idt_init.h"
#include "memory.h"
#include "intr.h"
#include "intr_status_op.h"
#include "debug.h"
#include "thread.h"
#include "sync.h"
#include "console.h"
#include "tss.h"
#include "process.h"
#include "syscall.h"
#include "sheet.h"
#include "mouse.h"
#include "ioqueue.h"
#include "timer.h"
#include "hd.h"
#include "fs.h"
struct event {
void* msgptr;
int count;
unsigned int type;
struct list waiters;
};
struct event event_array[256];
struct event* pevent_, * pevent_1;
void event_init(struct event* event_, void* msg, int cnt, int type);
void event_array_init(struct event* event_array_);
struct event* get_event(struct event* event_array_);
void sema_pend(struct event* pevent);
void sema_post(struct event* pevent);
unsigned int mk = 0;
void k_thread_a(void* arg);
void k_thread_b(void* arg);
void k_thread_c(void* arg);
void idle(void* arg);
unsigned int mua, mub;
void ua(void);
void ub(void);
struct semaphore fs_sema;
void init_all(unsigned int magic, unsigned int addr);
extern unsigned int ppp;
void kernel_main(unsigned int magic, unsigned int addr) {
int i;
init_all(magic, addr);
sema_init(&fs_sema, 0);
event_array_init(event_array);
pevent_ = get_event(event_array);
event_init(pevent_, NULL, 0, 0);
pevent_1 = get_event(event_array);
event_init(pevent_1, NULL, 0, 0);
struct bmp_buf_info bbi;
save_bmp((char*)&ppp, &bbi);
unsigned int* v = (unsigned int*)(0xe0000000 + 1024 * 128 * 4);
put_bmp_buf(v, 1024, 40, 40, &bbi);
put_gb2312_buf(v, 1024, 300, 300, 0x00ffffff, "我爱你蜗牛系统!");
struct SHEET* sht_back, * sht_mouse, *sht_win, *sht_win1;
void* buf_back = get_kernel_pages(up_pgs(1024 * (768 - 128) * 4));
memcpy_((void*)buf_back, (void*)v, 1024 * (768 - 128) * 4);
fill_circle(buf_back, 1024, 200, 300, 80, 0x00ffff00);
int* buf_win = get_kernel_pages(up_pgs(500 * 300 * sizeof(int)));
int* buf_win1 = get_kernel_pages(up_pgs(300 * 250 * sizeof(int)));
for(i = 0; i < 500 * 300; i++) {
buf_win[i] = 0x00cccccc;
}
for(i = 0; i < 300 * 250; i++) {
buf_win1[i] = 0x00cccccc;
}
put_bmp_buf(buf_win, 500, 10, 10, &bbi);
put_bmp_buf(buf_win1, 300, 10, 10, &bbi);
fill_rectangle(buf_win1, 300, 180, 10, 80, 80, 0x00ff0000);
struct point a, b, c;
a.x = 80 + 200;
a.y = 5;
b.x = 20 + 200;
b.y = 200;
c.x = 150 + 200;
c.y = 210;
fill_triangle(buf_win, 500, &a, &b, &c, 0x00ffffff);
put_str_buf(buf_win, 500, 80, 80, 0x00ff0000,
"Hello, SnailOS. Good luck!...");
unsigned int buf_mouse[16 * 16];
make_mouse_pointer(buf_mouse, 0x003098df);
shtctl = shtctl_init(v, 1024, 768 - 128);
sht_back = sheet_alloc(shtctl);
sht_mouse = sheet_alloc(shtctl);
sht_win = sheet_alloc(shtctl);
sht_win1 = sheet_alloc(shtctl);
sheet_setbuf(sht_back, buf_back, 1024, 768 - 128, -1);
sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 0x003098df);
sheet_setbuf(sht_win, buf_win, 500, 300, -1);
sheet_setbuf(sht_win1, buf_win1, 300, 250, -1);
sheet_slide(sht_back, 0, 0);
sheet_slide(sht_win, 80, 200);
sheet_slide(sht_mouse, 300, 300);
sheet_slide(sht_win1, 2, 2);
sheet_updown(sht_back, 0);
sheet_updown(sht_mouse, 3);
sheet_updown(sht_win, 1);
sheet_updown(sht_win1, 2);
timer_set(t_m, 100, &main_ioq, 0x10000);
timer_set(t_m, 300, &main_ioq, 0x10001);
thread_ready_list = &ready_list[0];
out(0x21, 0xf8);
out(0xa1, 0xae);
intr_enable();
thread_start("k_thread_a", 10, k_thread_a, "argA ", 1);
thread_start("k_thread_b", 1, k_thread_b, "argB ", 1);
thread_start("k_thread_c", 2, k_thread_c, "argC ", 1);
process_execute(ua, "UA", 1);
process_execute(ub, "UB", 2);
thread_start("Idle", 1, idle, "idle ", 7);
int ioq_data, mx, my;
struct mouse_dec mdec;
int j, x, y, mmx = -1, mmy = -1;
struct SHEET* sht = NULL;
while(1) {
printf_(" %d ", running_thread()->level);
enum intr_status old_status = intr_disable();
if(ioq_empty(&main_ioq)) {
thread_block(BLOCKED);
// intr_set_status(old_status);
} else {
ioq_data = ioq_getint(&main_ioq);
intr_set_status(old_status);
if(mouse_decode(&mdec, ioq_data)) {
mx += mdec.x;
my += mdec.y;
if(mx < 0) {
mx = 0;
}
if(my < 0) {
my = 0;
}
if(mx > 1024 - 1) {
mx = 1024 - 1;
}
if(my > 768 - 1 - 128) {
my = 768 - 1 - 128;
}
sheet_slide(sht_mouse, mx, my);
int btn = mdec.btn;
if(btn & 1) {
if(mmx < 0) {
for(j = shtctl->top - 1; j > 0; j--) {
sht = shtctl->sheets[j];
x = mx - sht->vx0;
y = my - sht->vy0;
if(0 <= x && x < sht->bxsize &&
0 <= y && y < sht->bysize)
{
if(sht->buf[y * sht->bxsize + x]
!= sht->col_inv) {
sheet_updown(sht, shtctl->top - 1);
mmx = mx;
mmy = my;
}
break;
}
}
} else {
x = mx - mmx;
y = my - mmy;
sheet_slide(sht, sht->vx0 + x, sht->vy0 + y);
mmx = mx;
mmy = my;
}
} else {
mmx = -1;
}
if(btn & 2) {
}
if(btn & 4) {
}
}
if(ioq_data == 0x10000) {
put_gb2312_buf((int*)buf_win, 500, 20, 60, 0x00ff0000, "你好蜗牛操作系统!");
timer_set(t_m, 80, &main_ioq, 0x10001);
sheet_refresh(sht_win, 20, 60, 20 + 9 * 16, 60 + 16);
}
if(ioq_data == 0x10001) {
put_gb2312_buf((int*)buf_win, 500, 20, 60, 0x0000ff00, "你好蜗牛操作系统!");
timer_set(t_m, 90, &main_ioq, 0x10000);
sheet_refresh(sht_win, 20, 60, 20 + 9 * 16, 60 + 16);
}
if (ioq_data == 0x20000) {
}
}
}
}
void init_all(unsigned int magic, unsigned int addr) {
pos = 0;
ticks = 0;
info_area_cls();
screen_init();
// multiboot2_info(magic, addr);
gdt_init();
page_init();
idt_init();
i8259_init();
i8253_init();
mem_init();
thread_init();
console_init();
tss_init();
syscall_init();
keyboard_init();
mouse_init();
rtc_init();
ioqueue_init(&main_ioq);
timer_man_init();
hd_init();
}
void k_thread_a(void* arg) {
intr_enable();
struct fat32_krn_p fat32_p;
read_mbr_dbr(&fat32_p);
fat32_krn = fat32_p;
printf_("!!!%x %x %x!!!", fat32_krn.fat1_p, fat32_krn.root_dir_p,
fat32_krn.root_dir_start_sector);
// find_file(&fat32_p, "p.bmp");
// find_file(&fat32_p, "kernel");
// find_file(&fat32_p, "hello.txt");
// = file_read(&fat32_p, "hello.txt");
// console_put_str(s);
// enum intr_status old_status = intr_disable();
// ioq_putint(&main_ioq, 0x20000);
// intr_set_status(old_status);
// sema_up(&fs_sema);
sema_post(pevent_);
sema_post(pevent_);
while(1) {
// console_put_int(mua);
console_put_str(" Thread A ");
console_put_int(running_thread()->level);
// console_put_str(" ");
mtime_sleep(1000);
}
}
void k_thread_b(void* arg) {
// void* mkb = (void*)malloc_(1);
// hd_read(&hds[0], 0, (void*)mkb, 1);
// unsigned int* boot_sector_magic = (unsigned int*)
// ((unsigned int)mkb);
// console_put_int(*boot_sector_magic);
// sema_down(&fs_sema);
sema_pend(pevent_);
///*
char* s = file_read("p.bmp");
struct bmp_buf_info bbi;
save_bmp((char*)s, &bbi);
unsigned int* v = (unsigned int*)(0xe0000000 + 1024 * 128 * 4);
put_bmp_buf(v, 1024, 700, 400, &bbi);
//*/
while(1) {
// out(0x1f7, 0xec);
// const char* s = "kernel";
// console_put_str(format_filename(s));
// console_put_int(mub);
console_put_str(" Thread B ");
console_put_int(running_thread()->level);
// console_put_int(free_((void*)mk));
// console_put_str(" ");
mtime_sleep(1000);
}
}
void k_thread_c(void* arg) {
// void* mkb = (void*)malloc_(1);
// hd_read(&hds[0], 0, (void*)mkb, 1);
// unsigned int* boot_sector_magic = (unsigned int*)
// ((unsigned int)mkb);
// console_put_int(*boot_sector_magic);
// sema_down(&fs_sema);
sema_pend(pevent_);
///*
char* s = file_read("p.bmp");
struct bmp_buf_info bbi;
save_bmp((char*)s, &bbi);
unsigned int* v = (unsigned int*)(0xe0000000 + 1024 * 128 * 4);
put_bmp_buf(v, 1024, 500, 400, &bbi);
//*/
while(1) {
// out(0x1f7, 0xec);
// const char* s = "kernel";
// console_put_str(format_filename(s));
// console_put_int(mub);
console_put_str(" Thread C ");
console_put_int(running_thread()->level);
// console_put_int(free_((void*)mk));
// console_put_str(" ");
mtime_sleep(1000);
}
}
void ua(void) {
while(1) {
write(" UA ");
// mua = malloc_(1);
// msleep(3000);
}
}
void ub(void) {
while(1) {
write(" UB ");
// mub = malloc_(1);
// msleep(3000);
}
}
void idle(void* arg) {
unsigned char* s = arg;
console_put_str(s);
while(1) {
__asm__ __volatile__ ("sti; hlt;");
}
}
// event start
void event_init(struct event* event_, void* msg, int cnt, int type) {
enum intr_status old_status = intr_disable();
event_->msgptr = msg;
event_->count = cnt;
event_->type = type;
list_init(&event_->waiters);
intr_set_status(old_status);
}
void event_array_init(struct event* event_array_) {
int i;
for(i = 0; i < 256; i++) {
event_init(&event_array_[i], NULL, 0, -1);
}
}
struct event* get_event(struct event* event_array_) {
int i;
enum intr_status old_status = intr_disable();
for(i = 0; i < 256; i++) {
if(event_array[i].type == -1) {
break;
}
}
intr_set_status(old_status);
return &event_array_[i];
}
void sema_pend(struct event* pevent) {
struct task* cur;
enum intr_status old_status = intr_disable();
if(pevent->count == 0) {
cur = running_thread();
list_append(&pevent->waiters, &cur->general_tag);
cur->status = WAITING;
schedule();
intr_set_status(old_status);
} else {
pevent->count--;
intr_set_status(old_status);
}
}
void sema_post(struct event* pevent) {
struct list_elem* waiter;
enum intr_status old_status = intr_disable();
if(!list_empty(&pevent->waiters)) {
waiter = list_pop(&pevent->waiters);
struct task* next = elem2entry(struct task, general_tag, waiter);
thread_ready_list = &ready_list[next->level];
list_append(thread_ready_list, waiter);
intr_set_status(old_status);
} else {
pevent->count++;
intr_set_status(old_status);
}
}
// event end