enks
func.h
#include<stdio.h>
extern void mysleep(int sec);
void fun1() {
int i = 10;
while(i --) {
printf("fun1 is running now!\n");
mysleep(2);
}
}
void fun2() {
int i = 10;
while(i --) {
printf("fun2 is running now!\n");
mysleep(1);
}
}
void fun3() {
int i = 2;
while(i --) {
printf("fun3 if running now!\n");
mysleep(5);
}
}
void fun4() {
int i = 15;
while(i --) {
printf("fun4 is running now!\n");
for(int j = 1; j <= 1000; j ++) {
for(int k = 1; k <= 1000; k ++) {
//nothing to do just waste time
}
}
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "thread.h"
#include "func.h"
extern void schedule();
int main(){
int id1, id2, id3, id4;
thread_create(&id1,fun1);
printf("thread %d has been created \n",id1);
thread_create(&id2,fun2);
printf("thread %d has been created \n",id2);
thread_create(&id3,fun3);
printf("thread %d has been created \n",id3);
thread_create(&id4,fun4);
printf("thread %d has been created \n",id4);
int i=2;
while(i--) {
printf("main is running now!");
mysleep(3);
}
thread_join(id1);
thread_join(id2);
thread_join(id3);
thread_join(id4);
return 0;
}
schedule.c
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include "thread.h"
extern struct thread_struct *current;
extern struct thread_struct *task[thr_task];
void switch_to_next(struct thread_struct *next);
static unsigned int getmytime(){
struct timeval tv;
if(gettimeofday(&tv,NULL)<0){
perror("gettimeofday");
exit(-1);
}
return tv.tv_sec*1000+tv.tv_usec/1000;
}
static struct thread_struct *pick(){
int next,c;
for(int i = 0; i < thr_task; i ++) {
if(task[i] && task[i]->status != status_exit && getmytime() > task[i]->waketime){
task[i] -> status = status_running;
}
}
while(1){
c = -1;
next=0;
for(int i = 0; i < thr_task; i ++){
if(!task[i])continue;
if(task[i]->status == status_running && task[i] ->counter > c){
c = task[i]->counter;
next=i;
}
}
if(c)break;
if(c == 0){
for(int i = 0; i < thr_task; i ++) {
if(task[i]) {
task[i]-> counter = task[i]->priority+(task[i]->counter>>1);
}
}
}
}
return task[next];
}
void closealrm() {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
{
perror("sigprocmask BLOCK");
}
}
void openalarm()
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0)
{
perror("sigprocmask BLOCK");
}
}
void schedule() {
struct thread_struct *next = pick();
if(next) {
switch_to_next(next);
}
}
void mysleep(int sec){
current->waketime=getmytime()+1000*sec;
current->status=status_sleep;
schedule();
}
static void do_timer() {
if(--current->counter > 0 ) return;
current->counter = 0;
schedule();
}
__attribute__((constructor)) //Clock interrupt
static void
init()
{
struct itimerval value;
value.it_value.tv_sec = 0;
value.it_value.tv_usec = 1000;
value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = 1000 * 10; // vulue is 10 ms
if (setitimer(ITIMER_REAL, &value, NULL) < 0)
{
perror("setitimer");
}
signal(SIGALRM, do_timer);
}
switch.s
.section .text
.global switch_to_next
switch_to_next:
push %ebp
mov %esp,%ebp
push %edi
push %esi
push %ebx
push %edx
push %ecx
push %eax
pushfl
mov current,%eax
mov %esp,8(%eax)
mov 8(%ebp),%eax
mov %eax,current
mov 8(%eax),%esp
popfl
popl %eax
popl %edx
popl %ecx
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
thread.c
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include "thread.h"
static struct thread_struct init_task =
{0, NULL, status_running, 0, 0, 15, 15, {0}};
struct thread_struct *current = &init_task;
struct thread_struct *task[thr_task]={&init_task,};
void schedule();
void start(struct thread_struct *tsk){
tsk->thread_fun();
tsk->status =status_exit;
printf("thread %d excited\n",tsk->id);
task[tsk->id]=NULL;
schedule();
}
int thread_create(int *tid, void (*start_routine)()){
int id = -1;
struct thread_struct *tsk=(struct thread_struct *)malloc(sizeof(struct thread_struct));
while(++ id < thr_task && task[id]);
if(id == thr_task)return -1;
task[id] = tsk;
if(tid) *tid = id;
tsk->id = id;
tsk->thread_fun = start_routine;
int *stack = tsk->stack;
tsk->esp = (int)(stack = stack_size - 11);
tsk->status = status_running;
tsk->waketime = 0;
tsk->counter = 15;
tsk->priority = 15;
stack[stack_size- 11] = 7;
stack[stack_size- 10] = 6;
stack[stack_size- 9] = 5;
stack[stack_size- 8] = 4;
stack[stack_size- 7] = 3;
stack[stack_size- 6] = 2;
stack[stack_size- 5] = 1;
stack[stack_size- 4] = 0;
stack[stack_size- 3] = (int)start;
stack[stack_size- 2] = 100;
stack[stack_size- 1] = (int)tsk;
return 0;
}
int thread_join(int tid) {
while(task[tid]->status!=status_exit){
schedule();
}
free(task[tid]);
task[tid] = NULL;
}
thread.h
#define stack_size 1024
#define thr_task 32
#define status_running 0
#define status_sleep 1
#define status_ready 2
#define status_exit 4
struct thread_struct{
int id;
void (*thread_fun)();
int esp;
unsigned int waketime;
int status;
int counter;
int priority;
int stack[stack_size];
};
int thread_create(int *tid,void (*start_routine)());
int thread_join(int tid);
void mysleep(int sec);