1. 코드 분석
1. tlpi-dist/procpri/sched_set.c
1. 코드
#include <sched.h>
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
int j, pol;
struct sched_param sp;
if (argc < 3 || strchr("rfo"
#ifdef SCHED_BATCH
"b"
#endif
#ifdef SCHED_IDLE
"i"
#endif
, argv[1][0]) == NULL)
usageErr("%s policy priority [pid...]\n"
" policy is 'r' (RR), 'f' (FIFO), "
#ifdef SCHED_BATCH
"'b' (BATCH), "
#endif
#ifdef SCHED_IDLE
"'i' (IDLE), "
#endif
"or 'o' (OTHER)\n",
argv[0]);
pol = (argv[1][0] == 'r') ? SCHED_RR :
(argv[1][0] == 'f') ? SCHED_FIFO :
#ifdef SCHED_BATCH
(argv[1][0] == 'b') ? SCHED_BATCH :
#endif
#ifdef SCHED_IDLE
(argv[1][0] == 'i') ? SCHED_IDLE :
#endif
SCHED_OTHER;
sp.sched_priority = getInt(argv[2], 0, "priority");
for (j = 3; j < argc; j++)
if (sched_setscheduler(getLong(argv[j], 0, "pid"), pol, &sp) == -1)
errExit("sched_setscheduler");
exit(EXIT_SUCCESS);
}
2. 동작 모습

3. 디버깅 및 분석

2. tlpi-dist/procpri/sched_view.c
1. 코드
#include <sched.h>
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
int j, pol;
struct sched_param sp;
for (j = 1; j < argc; j++) {
pol = sched_getscheduler(getLong(argv[j], 0, "pid"));
if (pol == -1)
errExit("sched_getscheduler");
if (sched_getparam(getLong(argv[j], 0, "pid"), &sp) == -1)
errExit("sched_getparam");
printf("%s: %-5s ", argv[j],
(pol == SCHED_OTHER) ? "OTHER" :
(pol == SCHED_RR) ? "RR" :
(pol == SCHED_FIFO) ? "FIFO" :
#ifdef SCHED_BATCH
(pol == SCHED_BATCH) ? "BATCH" :
#endif
#ifdef SCHED_IDLE
(pol == SCHED_IDLE) ? "IDLE" :
#endif
"???");
printf("%2d\n", sp.sched_priority);
}
exit(EXIT_SUCCESS);
}
2. 동작 모습

3. 디버깅 및 분석

2. 유저 레벨 스레드 예제 코드 분석
1. 코드
1. schedule.c
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/user.h>
#include <stdio.h>
#include <stdlib.h>
#define FREE 0x0
#define RUNNING 0x1
#define RUNNABLE 0x2
#define STACK_SIZE 8192
#define MAX_THREAD 4
typedef struct task_struct task_struct_t, *task_struct_p;
typedef struct mutex mutex_t, *mutex_p;
struct task_struct {
int sp;
char stack[STACK_SIZE];
int state;
};
static task_struct_t all_thread[MAX_THREAD];
task_struct_p current_thread;
task_struct_p next_thread;
extern void context_switch(void);
void thread_init(void)
{
current_thread = &all_thread[0];
current_thread->state = RUNNING;
}
static void __schedule(void)
{
task_struct_p t;
next_thread = 0;
for (t = all_thread; t < all_thread + MAX_THREAD; t++) {
if (t->state == RUNNABLE && t != current_thread) {
next_thread = t;
break;
}
}
if (t >= all_thread + MAX_THREAD && current_thread->state == RUNNABLE) {
next_thread = current_thread;
}
if (next_thread == 0) {
printf("다음 스레드가 없습니다. 종료합니다.\n");
exit(1);
}
if (current_thread != next_thread) {
next_thread->state = RUNNING;
context_switch();
} else
next_thread = 0;
}
void thread_create(void (*func)())
{
task_struct_p t;
for (t = all_thread; t < all_thread + MAX_THREAD; t++) {
if (t->state == FREE) break;
}
t->sp = (int) (t->stack + STACK_SIZE);
t->sp -= 4;
* (int *) (t->sp) = (int)func;
t->sp -= 32;
t->state = RUNNABLE;
}
void schedule(void)
{
current_thread->state = RUNNABLE;
__schedule();
}
static void mythread(void)
{
int i;
for (i = 0; i < 100; i++) {
printf("thread 0x%x\n", (int) current_thread);
schedule();
}
printf("thread: exit\n");
current_thread->state = FREE;
__schedule();
}
int main(int argc, char *argv[])
{
thread_init();
thread_create(mythread);
thread_create(mythread);
__schedule();
return 0;
}
2. context_switch.S
.text
.globl context_switch
context_switch:
pushal // CPU 레지스터를 스택에 저장
movl current_thread, %eax // 현재 스레드 주소를 eax 레지스터에 임시 저장
movl %esp, (%eax) // esp 스택 포인터를 eax 주소 값(eax는 current_thread 포인터임)에 저장
movl next_thread, %eax // next_thread를 eax에 저장
movl %eax, current_thread // next_thread를 current_thread로 수정
movl $0, next_thread // next thread는 0으로 초기화
movl current_thread, %eax // 스택 포인터를 변경하기 위해 current_thread를 eax에 저장, task_struct의 최상의 변수가 stack pointer임.
movl (%eax), %esp
popal
ret
2. 동작 모습

3. 디버깅 및 분석

