2005년 10월 12일
세마포어 구현 ^^

2005년 10월 10일 - 세마포어
-----------------------------------------------------------------------
process state를 갖도록 하여 세마포어 wait()이 일어날때 process state를
block으로 주어 schedule에 빠지도록 구현하였다. semaphore.post()가 일어나면
semaphore에 저장된 wait queue에서 해당 process를 끄내와 block된 상태에서
ready 상태로 변경해주었다.
모든 프로세스가 block된 상태라면 현재 scheduler는 무조건 첫번째 process를
block 상태임에도 선택해와서 running상태로 만드는 버그가 있었다.
현재는 idle process개념을 두지 않고 세마포어 테스트시 dummy process를
같이 생성하여 이 문제를 당분간 해결하였다. 차 후에 커널의 모든 프로세스가
멈춰있을때 돌아가는 idle process를 두어야 겠다.
스크린샷을 보면 동기화 객체 세마포어에 의해 task_sem1과 task_sem2는
서로 상호배제적으로 실행되게 된다.
kernel_start() 에서
semaphore g_sem1;
sem_open( &g_sem1, 1 );
create_process( task_dummy );
create_process( task_sem1 );
create_process( task_sem2 );
void task_dummy()
{
while(1)
{
_asm int 0x30
}
}
void task_sem1()
{
while(1)
{
sem_wait( &g_sem1 );
crt_printf( "[sem%d] = 1 ", ps_get_current()->pid );
sleep();
crt_printf( "[sem%d] = 2 ", ps_get_current()->pid );
sleep();
sem_post( &g_sem1 );
}
}
void task_sem2()
{
while(1)
{
sem_wait( &g_sem1 );
crt_printf( "[sem%d] = 1 ", ps_get_current()->pid );
sleep();
crt_printf( "[sem%d] = 2 ", ps_get_current()->pid );
sleep();
crt_printf( "[sem%d] = 3 ", ps_get_current()->pid );
sleep();
sem_post( &g_sem1 );
}
}
더 해야할 일
mutex, event 정도는 마련해야 할듯하다.
typedef struct _wait_queue
{
LPPROCESS ps;
struct _wait_queue* next;
}wait_queue;
// kernel object
typedef struct _kernel_object
{
char name[10];
}kernel_object;
// semaphore object
typedef struct _semaphore
{
kernel_object object;
wait_queue wait_head;
int counter;
}semaphore;
void sem_open( semaphore* s, int counter );
void sem_wait( semaphore* s );
void sem_post( semaphore* s );
void sem_open( semaphore* s, int counter )
{
ENTER_CRITICAL_SECTION();
memset( s, 0, sizeof(semaphore) );
if( counter == 0 )
counter = 1;
s->wait_head.next = 0;
s->counter = counter;
EXIT_CRITICAL_SECTION();
}
wait_queue* wq_get_last( wait_queue* wq )
{
while( wq && wq->next )
wq = wq->next;
return wq;
}
void sem_wait( semaphore* s )
{
ENTER_CRITICAL_SECTION();
//crt_printf("(%d) sem_wait call ", ps_get_current()->pid );
if( s->counter > 0 )
{
s->counter--;
//crt_printf("(%d) sem.counter = %d ", ps_get_current()->pid, s->counter );
//crt_printf("(%d) sem_wait return ", ps_get_current()->pid );
EXIT_CRITICAL_SECTION();
}
else
{
// add wait queue
wait_queue* wq_last = wq_get_last( &s->wait_head );
wait_queue* wq = (wait_queue*)mm_alloc( sizeof(wait_queue) );
s->counter--;
wq_last->next = wq;
wq->next = 0;
wq->ps = ps_get_current();
wq->ps->state = block;
//crt_printf("(%d) -> block ", ps_get_current()->pid );
//crt_printf("(%d) sem_wait return ", ps_get_current()->pid );
EXIT_CRITICAL_SECTION();
_asm int 0x30;
}
}
void sem_post( semaphore* s )
{
wait_queue* wq;
ENTER_CRITICAL_SECTION();
//crt_printf("(%d) sem_post call ", ps_get_current()->pid );
wq = s->wait_head.next;
//crt_printf("(%d) sem.counter = %d ", ps_get_current()->pid, s->counter );
if( wq != 0 )
{
s->wait_head.next = wq->next;
wq->ps->state = ready;
//crt_printf("(%d) -> ready ", wq->ps->pid );
mm_free(wq);
//crt_printf("(%d) sem_post return ", ps_get_current()->pid );
EXIT_CRITICAL_SECTION();
_asm int 0x30;
return;
}
s->counter++;
//crt_printf("(%d) sem_post return ", ps_get_current()->pid );
EXIT_CRITICAL_SECTION();
}
# by | 2005/10/12 11:27 | OS만들기 | 트랙백 | 덧글(1)




제가 파일 시스템을 맡게 되었는데. fat12를 써서 하려고 합니다.
하지만 관련 자료를 구하는 것이 만만치않아서 구글링을 하다가 여가까지 오게 되었습니다...
죄송하지만 혹시 관련 자료가 있으시면 좀 보내주셨으면 감사하겠습니다.
종종 코멘트를 얻기 위헤 찾아 오겠습니다
skwhdks@naver.com