Skip to content

xv6 LWP Wiki (2. LWP Result)

SanghyoKim edited this page Jul 19, 2023 · 3 revisions

2 - 1. thread_create, thread_exit, thread_join

thread_create, thread_exit, thread_join이 올바르게 작동하는지 알아보기 위해서 아래와 같은 테스트 코드를 작성했습니다.

int k = 100;
void* loop(void* num)
{   
  thread_t thread6;
  int i = 6;
  char *retval[5];
  retval[0] = "d";
  static char *args[5];
  args[0] = "hihihihihi";
  args[1] = "ddddddd";

  while(k-- > 0) { 
    printf(1, "%d\n", k);
  }
  thread_exit((void*)NULL);
  return NULL;
}

int main(int argc, char* argv[])
{
   int i = 1;
    int j = 2;
    int a = 3;
    int b = 4;
    int c = 5;
    thread_t thread1;
    thread_t thread2;
    thread_t thread3;
    thread_t thread4;
    thread_t thread5;

    char* retVal[5];
    retVal[0] = "ls";
    
    thread_create(&thread1, loop, &i);
    thread_create(&thread2, loop, &j);
    thread_create(&thread3, loop, &a); 
    thread_create(&thread4, loop, &b);
    thread_create(&thread5, loop, &c);
    
    thread_join(thread1, (void**)retVal);
    thread_join(thread2, (void**)retVal);
    thread_join(thread3, (void**)retVal);
    thread_join(thread4, (void**)retVal);
    thread_join(thread5, (void**)retVal);
    
    exit();
}

이와 같은 유저프로그램이 올바르게 동작한다면 thread_join에서 자원이 회수되는 순서는 차례대로 1, 2, 3, 4, 5번일 것입니다. 각각의 tid값이 4번부터 시작했기 때문에 자원이 회수되는 tid 순서는 아래의 그림처럼 4, 5 , 6, 7, 7이 나옵니다.

Untitled 16

그렇다면 thread_join(thread3, retval) 이 thread3을 제대로 회수하지 못하고 sleep 상태에 있다면 그 아래의 join구문들은 올바르게 작동하여야합니다. 이 상황이 올바르게 동작하는지 확인해보겠습니다.

위의 코드에서 loop 함수를 아래와같이 변경했습니다.

3번 thread에서 while문 무한 loop를 돌기 때문에 thread_exit이 호출되지 않고 thread_join(thread3, retval)은 올바르게 자원을 회수하지 못한채 sleep 상태에 머물 것 입니다.

이에 따른 결과를 보겠습니다.

int k = 100;
void* loop(void* num)
{   
  thread_t thread6;
  int i = 6;
  char *retval[5];
  retval[0] = "d";
  static char *args[5];
  args[0] = "hihihihihi";
  args[1] = "ddddddd";

  if(*(int*)num == 3) {
    while(1) { };
  }
  while(k-- > 0) { 
    printf(1, "%d\n", k);
  }
  thread_exit((void*)NULL);
  return NULL;
}
Untitled 16

4, 5번 join 이후에 6번이 sleep 상태에 빠져있기 때문에 더이상 처리하지 못하고 무한 loop에 빠져있는 것을 볼 수 있습니다.

2 - 2. systemcall (exec)

올바르게 exec이 작동하고, 단 하나의 thread만 남아있는지 알아보기 위해서 아래와 같은 코드를 작성했습니다.

아래의 코드가 올바르게 작동한다면 exec이 단 한번만 호출되고, 프로그램은 종료될 것 입니다.

그 이후에 확인했을 때 thread들의 자원은 회수되어있을 것 입니다.

void*
execthreadmain(void *arg)
{
  char *args[3] = {"echo", "echo is executed!", 0}; 
  printf(1, "execute start\n");
  exec("echo", args);

  printf(1, "panic at exec thread main\n");
  thread_exit((void*)NULL);
  exit();
}

int
main(int argc, char* argv[])
{
  thread_t threads[THREADNUM];
  int i;
  void *retval;

  for (i = 0; i < THREADNUM; i++){
    if (thread_create(&threads[i], execthreadmain, (void*)0) != 0){
      printf(1, "panic at thread_create\n");
      return -1;
    }
  }
  for (i = 0; i < THREADNUM; i++){
    if (thread_join(threads[i], &retval) != 0){
      printf(1, "panic at thread_join\n");
      return -1;
    }
  }
  printf(1, "panic at exectest\n");
  return 0;
}

execute가 시작된 직후 쓰레드는 3, 4, 5, 6, 7, 8번이 존재했습니다.

thread를 정리하는 코드를 실행한 이후에 exec을 호출한 5번 쓰레두만 놔두고 나머지 쓰레드들을 모두 정리하였고 올바르게 execute가 실행된 것을 볼 수 있습니다.

Untitled 18

2 - 3. systemcall (exit & kill)

exit과 kill을 호출했을 때 같은 pid값을 갖고있는 모든 thread들은 정리되어야합니다.

아래와 같은 exit, kill test 코드를 작성했습니다.

그에 따른 결과를 그림으로 확인해보겠습니다.

exit test code

int k = 100;
void* loop(void* num)
{   
  thread_t thread6;
  int i = 6;
  char *retval[5];
  retval[0] = "d";
  static char *args[5];
  args[0] = "hihihihihi";
  args[1] = "ddddddd";

  if(*(int*)num == 3) {
    exit();
  }
  while(k-- > 0) { 
    printf(1, "%d\n", k);
  }
  thread_exit((void*)NULL);
  return NULL;
}

int main(int argc, char* argv[])
{
   int i = 1;
    int j = 2;
    int a = 3;
    int b = 4;
    int c = 5;
    thread_t thread1;
    thread_t thread2;
    thread_t thread3;
    thread_t thread4;
    thread_t thread5;

    char* retVal[5];
    retVal[0] = "ls";
    
    thread_create(&thread1, loop, &i);
    thread_create(&thread2, loop, &j);
    thread_create(&thread3, loop, &a); 
    thread_create(&thread4, loop, &b);
    thread_create(&thread5, loop, &c);
    
    thread_join(thread1, (void**)retVal);
    thread_join(thread2, (void**)retVal);
    thread_join(thread3, (void**)retVal);
    thread_join(thread4, (void**)retVal);
    thread_join(thread5, (void**)retVal);
    
    exit();
}

kill test code

int k = 100;
void* loop(void* num)
{   
  thread_t thread6;
  int i = 6;
  char *retval[5];
  retval[0] = "d";
  static char *args[5];
  args[0] = "hihihihihi";
  args[1] = "ddddddd";

  if(*(int*)num == 3) {
    kill(2);
  }
  while(k-- > 0) { 
    printf(1, "%d\n", k);
  }
  thread_exit((void*)NULL);
  return NULL;
}

int main(int argc, char* argv[])
{
   int i = 1;
    int j = 2;
    int a = 3;
    int b = 4;
    int c = 5;
    thread_t thread1;
    thread_t thread2;
    thread_t thread3;
    thread_t thread4;
    thread_t thread5;

    char* retVal[5];
    retVal[0] = "ls";
    
    thread_create(&thread1, loop, &i);
    thread_create(&thread2, loop, &j);
    thread_create(&thread3, loop, &a); 
    thread_create(&thread4, loop, &b);
    thread_create(&thread5, loop, &c);
    
    thread_join(thread1, (void**)retVal);
    thread_join(thread2, (void**)retVal);
    thread_join(thread3, (void**)retVal);
    thread_join(thread4, (void**)retVal);
    thread_join(thread5, (void**)retVal);
    
    exit();
}

원래는 전역변수 k의 값 100이 0이 될 때 까지 모든 값이 출력되고, thread_join도 올바르게 작동하여 자원들이 회수되었다는 메세지가 출력되어야 합니다.

하지만 3번 쓰레드 생성과 동시에 start_routine에서 exit()과 kill(3)을 호출했기 때문에 모든 쓰레드들이 종료되어 아무 메세지도 출력하지 못하고, k값을 어느정도까지만 감소시키다가 종료합니다.

아래의 그림과 같이 남아있는 쓰레드들도 없는 결과를 볼 수 있습니다.

Untitled 19