Snail OS 0.03的thread目录是内核线程

内核线程参考的是郑钢先生《操作系统真相还原》,主要是觉得这种实现线程和进程的方式非常的巧妙,另外在这方面想要创新的话,空间也是很小的。

为了编程方便,thread当中包含了进程的阻塞和唤醒以及二元信号量和锁,这些是实现互斥和同步的基础。

// thread.h
#ifndef __THREAD_H
#define __THREAD_H
#include "list.h"
#include "sync.h"

typedef void thread_func(void*);

enum task_status {
	RUNNING, READY, BLOCKED, WAITING, HANDING, DIED
};

/*
_exit:
	pop gs
	pop fs
	pop es
	pop ds
	popa
	add esp, 2 * 4
	iret
*/


struct mem_desc {
	struct list_elem tag; //用它来串成链表
	unsigned int start, size; // start页的起始地址,size内存的字节大小
	int status; // status 正在被free使用0,或者正在被used使用1,或者空闲-1
};

struct mem_man {
	struct mem_desc* md_a;
	struct list free, used; // 两个链表一个是空闲,一个是使用
	struct lock lock;
};

struct intr_stack {
	unsigned int gs, fs, es, ds;
	unsigned int edi, esi, ebp, esp_dummy;
	unsigned int ebx, edx, ecx, eax;
	unsigned int vector_no_dummy, err_code_dummy;
	unsigned int eip, cs, eflags, esp, ss;
};

struct thread_stack {
	unsigned int edi, esi, ebp, esp_dummy;
	unsigned int ebx, edx, ecx, eax;
	unsigned int kernel_thread;
	unsigned int retaddr_dummy, func, func_arg;
};

struct task {
	unsigned int* self_kstack;
	unsigned int level;
	unsigned short pid;
	enum task_status status;
	char name[16];
	unsigned char priority;
	unsigned char ticks;
	unsigned int elapsed_ticks;
	struct list_elem general_tag;
	struct list_elem all_list_tag;
	unsigned int* pgdir;
	struct mem_man user_vir;
	unsigned int stack_magic;
};


struct task* running_thread(void);
void kernel_thread(thread_func* function, void* func_arg);
void thread_create(struct task* pthread, thread_func function,
				   void* func_arg);
void init_thread(struct task* pthread, char* name, int prio, unsigned int level);
struct task* thread_start(char* name, int prio, thread_func function, 
						  void * func_arg, unsigned int level);
void make_main_thread(void);
void schedule(void);
void thread_init(void);
void thread_block(enum task_status stat);
void thread_unblock(struct task* pthead);

struct task* main_thread;
struct list ready_list[8];
struct list* thread_ready_list;
struct list thread_all_list;
static struct list_elem* thread_tag;

void ticks_to_sleep(unsigned int sleep_ticks);
void mtime_sleep(unsigned int msecond);

struct lock pid_lock;


#endif
// thread.c
#include "list.h"
#include "thread.h"
#include "intr_status_op.h"
#include "memory.h"
#include "string.h"
#include "debug.h"
#include "sync.h"
#include "process.h"

extern void switch_to(struct task* cur, struct task* next);
extern unsigned int ticks;

struct task* running_thread(void) {
	unsigned int esp;
	__asm__ __volatile__("movl %%esp, %0":"=g"(esp));
	return (struct task*)(esp & 0xfffff000);
}

void kernel_thread(thread_func* function, void* func_arg) {
	intr_enable();
	function(func_arg);
}

void thread_create(struct task* pthread, thread_func function, void* func_arg) {
	pthread->self_kstack -= sizeof(struct intr_stack);
	pthread->self_kstack -= sizeof(struct thread_stack);
	struct thread_stack* kthread_stack =
	(struct thread_stack*)pthread->self_kstack;
	kthread_stack->kernel_thread = (unsigned int)kernel_thread;
	kthread_stack->func = (unsigned int)function;
	kthread_stack->func_arg = (unsigned int)func_arg;
	kthread_stack->eax = kthread_stack->ecx = kthread_stack->edx =
	kthread_stack->ebx = kthread_stack->esp_dummy = kthread_stack->ebp =
	kthread_stack->esi = kthread_stack->edi = 0;
}

unsigned short alloc_pid(void) {
	static unsigned int next_pid = 0;
	lock_acquire(&pid_lock);
	next_pid++;
	lock_release(&pid_lock);
	return next_pid;
}

void init_thread(struct task* pthread, char* name, int prio, unsigned int level) {
	memset_(pthread, 0, sizeof(*pthread));
	pthread->pid = alloc_pid();
	strcpy_(pthread->name, name);
	if(pthread == main_thread) {
		pthread->status = RUNNING;
	} else {
		pthread->status = READY;
	}
	pthread->self_kstack = (unsigned int*)((unsigned int)pthread + 4096);
	pthread->priority = prio;
	pthread->ticks = prio;
	pthread->level = level;
	pthread->elapsed_ticks = 0;
	pthread->pgdir = NULL;
	pthread->stack_magic = 0x19810602;
}

struct task* thread_start(char* name, int prio, thread_func function, 
void * func_arg, unsigned int level) {
	struct task* thread = get_kernel_pages(1);
	init_thread(thread, name, prio, level);
	thread_create(thread, function, func_arg);
	ASSERT((level >= 0) && (level <= 7));
	thread_ready_list = &ready_list[thread->level];
	ASSERT(!elem_find(thread_ready_list, &thread->general_tag));
	list_append(thread_ready_list, &thread->general_tag);
	ASSERT(!elem_find(&thread_all_list, &thread->all_list_tag));
	list_append(&thread_all_list, &thread->all_list_tag);
	return thread;
}

void make_main_thread(void) {
	main_thread = running_thread();
	init_thread(main_thread, "main", 31, 0);
	ASSERT(!elem_find(&thread_all_list, &main_thread->all_list_tag));
	list_append(&thread_all_list, &main_thread->all_list_tag);
}

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));
		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_init(void) {
	int i;
	for(i = 0; i < 8; i++) {
		list_init(&ready_list[i]);		
	}
	list_init(&thread_all_list);
	lock_init(&pid_lock);
	make_main_thread();
}


void thread_block(enum task_status stat) {
	enum intr_status old_status = intr_disable();
	ASSERT(((stat == BLOCKED) || (stat == HANDING) || (stat == WAITING)));
	struct task* cur = running_thread();
	cur->status = stat;
	schedule();
	intr_set_status(old_status);
}

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");
		}
		list_push(thread_ready_list, &pthread->general_tag);
		pthread->status = READY;
	}
	intr_set_status(old_status);
}

void yield(void) {
	struct task* cur = running_thread();
	enum intr_status old_status = intr_disable();
	ASSERT(!elem_find(thread_ready_list, &cur->general_tag));
	list_append(thread_ready_list, &cur->general_tag);
	cur->status = READY;
	schedule();
	intr_set_status(old_status);
}

void ticks_to_sleep(unsigned int sleep_ticks) {
	unsigned int short start_ticks = ticks;
	while(ticks - start_ticks < sleep_ticks) {
		yield();
	}
}

void mtime_sleep(unsigned int msecond) {
	unsigned sleep_ticks = msecond / 10 + 1;
	ASSERT(sleep_ticks > 0);
	ticks_to_sleep(sleep_ticks);
}



// sync.h
#ifndef __SYNC_H
#define __SYNC_H
#include "list.h"
#include "thread.h"

struct semaphore {
	unsigned char value;
	struct list waiters;
};

struct lock {
	struct task* holder;
	struct semaphore semaphore;
	unsigned int holder_repeat_nr;
};


void sema_init(struct semaphore* psema, unsigned char value);
void lock_init(struct lock* plock);
void sema_down(struct semaphore* psema);
void sema_up(struct semaphore* psema);
void lock_acquire(struct lock* plock);
void lock_release(struct lock* plock);

#endif

 

// sync.c
#include "memory.h"
#include "intr_status_op.h"
#include "debug.h"

void sema_init(struct semaphore* psema, unsigned char value) {
	psema->value = value;
	list_init(&psema->waiters);
}

void lock_init(struct lock* plock) {
	plock->holder = NULL;
	plock->holder_repeat_nr = 0;
	sema_init(&plock->semaphore, 1);
}

void sema_down(struct semaphore* psema) {
	enum intr_status old_status = intr_disable();
	while(psema->value == 0) {
		ASSERT(!elem_find(&psema->waiters, &running_thread()->general_tag));
		if(elem_find(&psema->waiters, &running_thread()->general_tag)) {
			PANIC("seam_down: thread blocked has been in waiters_list\n");
		}
		list_append(&psema->waiters, &running_thread()->general_tag);
		thread_block(BLOCKED);
	}
	psema->value--;
	ASSERT(psema->value == 0);
	intr_set_status(old_status);
}

void sema_up(struct semaphore* psema) {
	enum intr_status old_status = intr_disable();
	ASSERT(psema->value == 0);
	if(!list_empty(&psema->waiters)) {
		struct task* thread_blocked = elem2entry(struct task, general_tag,
									  list_pop(&psema->waiters));
		thread_unblock(thread_blocked);
	}
	psema->value++;
	ASSERT(psema->value == 1);
	intr_set_status(old_status);
}

void lock_acquire(struct lock* plock) {
	if(plock->holder != running_thread()) {
		sema_down(&plock->semaphore);
		plock->holder = running_thread();
		ASSERT(plock->holder_repeat_nr == 0);
		plock->holder_repeat_nr = 1;
	} else {
		plock->holder_repeat_nr++;
	}
}

void lock_release(struct lock* plock) {
	ASSERT(plock->holder == running_thread());
	if(plock->holder_repeat_nr > 1) {
		plock->holder_repeat_nr--;
		return;
	}
	ASSERT(plock->holder_repeat_nr == 1);
	plock->holder = NULL;
	plock->holder_repeat_nr = 0;
	sema_up(&plock->semaphore);
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_39410618

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值