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);

posted @ 2022-06-19 12:10  LiAnG24  阅读(47)  评论(0)    收藏  举报