· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
minzkn/thread

¹®¼­ÀÇ ¼öÁ¤
  • ¾î¶²ÀÌ¶óµµ ÇØ´ç ¹®¼­¿¡¼­ À߸øµÈ ºÎºÐÀÌ ÀÖÀ¸¸é ±â²¨È÷ ¼öÁ¤À» ºÎŹµå¸³´Ï´Ù. ¸¹Àº Âü¿©¸¦ ÅëÇØ ÀÌ ¹®¼­°¡ µçµçÇÑ ¹Þħ¸ñÀÌ µÇ±â¸¦ ÇÊÀÚ´Â °£ÀýÈ÷ ¹Ù¶ó°í ÀÖ½À´Ï´Ù.
  • °³ÀÎÀûÀÎ ÀÇ°ßÀ̳ª Áß¿äÇÑ design»óÀÇ ¾ÆÀ̵ð¾î°¡ ÀÖÀ¸¸é ²À ±Û ³²°ÜÁÖ½Ã±æ ¼Ò¸ÁÇÕ´Ï´Ù.

¼±Á¡Çü ThreadÀÇ ±¸Çö

¸ñÂ÷

1.2. °³¿ä

  • ÀÌ ¹®¼­´Â ÀϹÝÀûÀ¸·Î KernelÀÇ ÁøÀÔÁ¡°ú ±âŸ »óȲ¿¡¼­ÀÇ ÃÖ´ëÇÑ °£´ÜÇÑ ThreadÀÇ ±âÃʱ¸ÇöÀ» À§ÇÑ ³»¿ëÀ» Àû¾îº¼±î ÇÕ´Ï´Ù.
  • ºñ¼±Á¡Çü ThreadÀÇ °æ¿ì´Â Á» º¹ÀâÇÒ»Ó ÀÌ ³»¿ëÀ» ÀÌÇØÇÑ µ¶ÀÚ¶ó¸é ÃæºÐÈ÷ °³¼ºÀÖ´Â ¼Ò½º¸¦ âÁ¶ÇϽǼö ÀÖÀ»°Å¶ó ¹Ï¾î ÀǽÉÄ¡ ¾Ê½À´Ï´Ù.
  • ¼³¸í°ú ¿¹Á¦´Â C·Î ±¸¼ºÇÏ·Á°í ³ª¸§´ë·Î ³ë·ÂÇÏ°ÚÁö¸¸ ÇÊÀÚ°¡ ±¸ÇöÇÑ ½ÇÁ¦´Â 100% ¾î¼Àºí¸® ÀÔ´Ï´Ù. ±×·¯ÇÑ °úÁ¤¿¡¼­ ÀϺΠ¼º´É»ó ÃÖÀûÈ­°¡ ±â´ëÄ¡¸¸Å­ ÀÌ·ïÁöÁö ¾ÊÀ»¼ö ÀÖ½À´Ï´Ù.

1.3. ThreadÀÇ °³¿ä

  • ÀÌ°ÍÀÌ ¹«¾ùÀΰí?

1.4. Thread design

1.4.1. ÄÄÆÄÀÏ·¯ÀÇ ÃÖÀûÈ­¿¡ µû¸¥ ºñÀǵµÀû °á°ú

ÃÖÀûÈ­¿¡ ÀÇÇÑ Thread codeÀÇ ÀǵµµÇÁö ¾ÊÀº Çö»óÀÌ ¹ß»ýÇÒ¼öÀÖ½À´Ï´Ù. ÀÏ´Ü ±×·¯ÇÑ ºÎºÐ¿¡ ´ëÇؼ­´Â ºÒ°¡ÇÇÇÏ°Ô Assembly·Î ±¸ÇöÇÏ¿© Àú´Â ÇØ°á¹æ¹ýÀ» ¸ð»öÇÏ¿´½À´Ï´Ù. ±×·¯³ª ÇÔ¼ö ÀÚüÀÇ FrameÀÇ ÃÖÀûÈ­°¡ ÀÌ·ïÁú¶§¸é ¹æ¹ýÀÌ ³­ÇØÇÕ´Ï´Ù. ÀÌ¿¡ ´ëÇÑ °í¹ÎÀº ¹Ýµå½Ã ÇÊ¿äÇÕ´Ï´Ù. ÀÌ¿¡ ´ëÇÑ ÃæºÐÇÑ °í·Á°¡ µÇÁö ¾ÊÀ¸¸é ¿ÀÁ÷ ÀÚ½ÅÀÇ PC¿¡¼­¸¸ ½ÇÇàµÇ´Â ±âÇüÀûÀÎ Thread code°¡ µÉ°ÍÀÔ´Ï´Ù.

1.4.2. StackÀÇ °¡º¯Àû °ËÃâ

°¢ Thread´Â °íÀ¯ÀÇ StackÀ» ¼ÒÀ¯ÇÏ°Ô ¼³°èµË´Ï´Ù. ÇÏÁö¸¸ ±×°ÍÀÌ °íÁ¤ÀûÀ̶ó¸é Áö¿ªº¯¼ö·Î Ä¿´Ù¶õ ¹è¿­À» ¼±¾ðÇÏ¿© »ç¿ëÇϴµ¥ ºÎ´ãÀÌ ¾Æ´Ò¼ö ¾ø°Ú½À´Ï´Ù. ¶§¹®¿¡ StackÀ» °¡º¯ÀûÀ¸·Î ´Ã·ÁÁÙ¼ö ÀÖ´Â ¹æ¹ýÀÌ ¿ä±¸µË´Ï´Ù.

1.4.3. How to swap

ÀÌ°ÍÀº StackÀÌ SwapµÇ´Â°Í¿¡ ´ëÇÑ °í¹ÎÀÌ ÇÊ¿äÇϴٴµ¥ ÀÖ½À´Ï´Ù. ¹«Åδë°í ¸ðµÎ SwapÀÌ ¾Ë¾Æ¼­ µÇ¸é ÁÁ°ÚÁö¸¸ Àß »ý°¢Çغ¸½Ã¸é ThreadÀÇ StackÀº °ú¿¬ SwapÀÌ ÇÊ¿äÇÑ°¡¸¦ »ý°¢ÇغÁ¾ß ÇÕ´Ï´Ù. À߸øÇÏ¸é ¿ÀÈ÷·Á ºÎÀÛ¿ëÀÌ ¸¸¸¸Ä¡ ¾Ê´Ù´Âµ¥ ÁßÁ¡À» µÎ°í »ý°¢Çغ¼ ¹®Á¦ÀÓÀÌ ºÐ¸íÇÕ´Ï´Ù. ÇÊÀÚÀÇ ¼Ò°ßÀº "StackÀº Heap°ú ´Ù¸£´Ù" ÀÔ´Ï´Ù. °áÄÚ SwapÀÌ µÇÁö ¾Ê°í ¾Æ¿¹ °í·ÁµÇÁö ¾Ê´Â°ÍÀÌ ÁÁ´Ù´Â »ý°¢ÀÔ´Ï´Ù. ¿©·¯ºÐµéÀÇ »ý°¢Àº ¾î¶°½ÅÁö¿ä? °¢ÀÚ ¸¸µé¾îº¸°í ¼º´ÉÀÇ Æò°¡¸¦ ÇÒ¼ö ÀÖ´Â ±âȸ°¡ ¾ðÁ¨°¡ ÁÖ¾îÁ³À¸¸é ÁÁ°Ú±º¿ä.

1.5. Stack(Process)ÀÇ °ü¸®¿ä¼Ò

1.6. ¿¹Á¦

¾Æ·¡ÀÇ ¿¹Á¦ ¼Ò½º´Â ½ÇÁ¦ ÇÊÀÚ°¡ ¸¸µé°í ÀÖ´Â ¿î¿µÃ¼Á¦ÀÇ ÀϺθ¦ ¹ßÃéÇÑ°ÍÀÔ´Ï´Ù. ¹ßÃéÇϸ鼭 ¾à°£ÀÇ ºÒÇÊ¿äÇÑ ºÎºÐ°ú ³ª¸§´ë·ÎÀÇ ÁÖ¿ä ¼Ò½º´Â ¹ßÃéÇÏÁö ¾Ê¾Ò½À´Ï´Ù. Â÷ÈÄ¿¡´Â ¿ÏÀüÇÑ Thread¿¹Á¦¸¦ °ø°³Çϵµ·Ï ³ë·ÂÇÏ°Ú½À´Ï´Ù. ÇÏÁö¸¸ Çö½ÃÁ¡¿¡¼­´Â ÀÌ ÀÌ»óÀÇ ¼Ò½º´Â °ø°³ÇÏÁö ¾ÊÀ» ¹æħÀÔ´Ï´Ù.
/*
 Copyright (c) Information Equipment co.,LTD.
 Code by JaeHyuk Cho <mailto:minzkn@infoeq.co.kr> KOREA

 MZ Local Thread library v0.0.1b

 - Simple is best !
*/

#if !defined(DEF_SOURCE_thread_c)
#define DEF_SOURCE_thread_c "thread.c"

typedef struct ts_STACK
{
 void *Stack;
 int StackSize, StackPointer;
}t_STACK;

typedef struct ts_THREAD_TASK
{
 struct ts_THREAD_TASK *Next;
 t_STACK *Stack;
 unsigned int TaskID, ESP, Tick, Active;
 void * (*Entry)(void *, void *);
 void *Argument;
}t_THREAD_TASK;

typedef struct ts_THREAD
{
 t_THREAD_TASK *Task;
 t_THREAD_TASK *CurrentTask;
 unsigned int TaskCount, MakeID;
}t_THREAD;

t_THREAD *ML_CreateTHREAD(void);
t_THREAD *ML_DestroyTHREAD(t_THREAD *s_THREAD);
t_THREAD *ML_AddTHREAD(t_THREAD *s_THREAD, void * (*s_ThreadFunction)(void *, void *), void *s_Argument, int s_StackSize);
t_THREAD *ML_RunTHREAD(t_THREAD *s_THREAD);
int ML_SleepTHREAD(t_THREAD *s_THREAD);

t_STACK *ML_CreateSTACK(int s_StackSize);
t_STACK *ML_DestroySTACK(t_STACK *s_STACK);
int ML_PushSTACK(t_STACK *s_STACK, int s_Value);
int ML_PopSTACK(t_STACK *s_STACK, int *s_Value);
int ML_SetSTACK(t_STACK *s_STACK, int s_StackPointer);

void __ML_ReturnTHREAD__(void);

static void *__ML_ManagerTHREAD__(void *s_ThreadHandle, void *s_Argument)
{
 static t_THREAD *sg_THREAD = (t_THREAD *)0;    
 if(sg_THREAD != (t_THREAD *)s_ThreadHandle)sg_THREAD = (t_THREAD *)s_ThreadHandle;
 ML_SleepTHREAD((t_THREAD *)s_ThreadHandle);
 if(((t_THREAD *)s_ThreadHandle)->Task->Active == 0)return(s_Argument);
 t_inline_asm(
  "__ML_ReturnTHREAD__:\n\t"
  "pushl $__ML_ReturnTHREAD__\n\t" /* Retry push return address */
 );
 t_inline_asm(
  "\n\t"
  : "=a"(((t_THREAD *)s_ThreadHandle)->CurrentTask->Argument)
 );
 ((t_THREAD *)s_ThreadHandle)->CurrentTask->Active = 0;
 ML_SleepTHREAD((t_THREAD *)s_ThreadHandle);
 return(s_Argument);
}

t_THREAD *ML_CreateTHREAD(void)
{
 t_THREAD *s_Return;
 s_Return = (t_THREAD *)ML_Alloc(sizeof(t_THREAD));
 if(s_Return)
 {
  s_Return->Task = s_Return->CurrentTask = (t_THREAD_TASK *)0;
  s_Return->TaskCount = s_Return->MakeID = 0u;
  s_Return = ML_AddTHREAD(s_Return, __ML_ManagerTHREAD__, (void *)0, (4 << 10));
 }
 return(s_Return);
}

t_THREAD *ML_DestroyTHREAD(t_THREAD *s_THREAD)
{
 t_THREAD_TASK *s_THREAD_TASK;  
 if(s_THREAD)
 {
  while(s_THREAD->Task && s_THREAD->TaskCount--)
  {
   s_THREAD_TASK = s_THREAD->Task;
   s_THREAD->Task = s_THREAD->Task->Next;
   if(s_THREAD_TASK->Stack)(void)ML_DestroySTACK(s_THREAD_TASK->Stack);
   (void)ML_Free(s_THREAD_TASK);
  }
  (void)ML_Free(s_THREAD);
  s_THREAD = (t_THREAD *)0;
 }      
 return(s_THREAD);
}

t_THREAD *ML_AddTHREAD(t_THREAD *s_THREAD, void * (*s_ThreadFunction)(void *, void *), void *s_Argument, int s_StackSize)
{
 t_THREAD_TASK *s_THREAD_TASK;  
 if(s_THREAD == (t_THREAD *)0)s_THREAD = ML_CreateTHREAD();
 if(s_THREAD)
 {
  if(s_THREAD->Task)
  {
   s_THREAD_TASK = s_THREAD->Task;
   while(s_THREAD_TASK->Next && s_THREAD_TASK->Next != s_THREAD->Task)s_THREAD_TASK = s_THREAD_TASK->Next;  
   s_THREAD_TASK->Next = (t_THREAD_TASK *)ML_Alloc(sizeof(t_THREAD_TASK));
   s_THREAD_TASK = s_THREAD_TASK->Next;
   if(s_THREAD->CurrentTask == (t_THREAD_TASK *)0)s_THREAD->CurrentTask = s_THREAD->Task;
  }
  else s_THREAD->Task = s_THREAD->CurrentTask = s_THREAD_TASK = (t_THREAD_TASK *)ML_Alloc(sizeof(t_THREAD_TASK));
  if(s_THREAD_TASK)
  {
   if(s_StackSize < ( 4 << 10 ))s_StackSize = ( 4 << 10 );        
   s_THREAD_TASK->Next = s_THREAD->Task;
   s_THREAD_TASK->Stack = ML_CreateSTACK(s_StackSize);
   s_THREAD_TASK->TaskID = (s_THREAD->MakeID++);
   s_THREAD_TASK->Tick = 0;
   s_THREAD_TASK->Active = 1;
   s_THREAD_TASK->Entry = s_ThreadFunction;
   s_THREAD_TASK->Argument = s_Argument;
   s_THREAD_TASK->ESP = (unsigned int)s_THREAD_TASK->Stack->Stack + s_THREAD_TASK->Stack->StackPointer;
   s_THREAD->TaskCount++;
  }
 }
 return(s_THREAD);
}      

t_THREAD *ML_RunTHREAD(t_THREAD *s_THREAD)
{
 struct { unsigned int eax, ebx, ecx, edx, esi, edi, ebp, esp, flags; }s_Register;
 t_THREAD_TASK *s_THREAD_TASK;
 unsigned int s_RegisterAddress, s_TempEBX;
 if(s_THREAD)
 {
  if(s_THREAD->Task)
  {
   s_RegisterAddress = (unsigned int)(&s_Register);      
   t_inline_asm(
    "\n\t"
    "movl %%ebx, %1\n\t"
    "movl %0, %%ebx\n\t" 
    "movl %%eax, 0(%%ebx)\n\t"
    "movl %1, %%eax\n\t"
    "movl %%eax, 4(%%ebx)\n\t"
    "movl 0(%%ebx), %%eax\n\t"
    "movl %%ecx, 8(%%ebx)\n\t"
    "movl %%edx, 12(%%ebx)\n\t"
    "movl %%esi, 16(%%ebx)\n\t"
    "movl %%edi, 20(%%ebx)\n\t"
    "movl %%ebp, 24(%%ebx)\n\t"
    "movl %%esp, 28(%%ebx)\n\t"
    "pushfl\n\t"
    "popl 32(%%ebx)\n\t"
    "movl 4(%%ebx), %%ebx\n\t"
    "\n\t"
    :
    : "m"(s_RegisterAddress), "m"(s_TempEBX)
   );
   s_THREAD_TASK = s_THREAD->Task;
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.flags);
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.esp);
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.ebp);    
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.edi);    
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.esi);    
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.edx);    
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.ecx);    
   ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.ebx);    
   ML_PushSTACK(s_THREAD_TASK->Stack, (int)s_THREAD_TASK->Argument);      
   ML_PushSTACK(s_THREAD_TASK->Stack, (int)s_THREAD);
   s_THREAD_TASK->ESP = (unsigned int)s_THREAD_TASK->Stack->Stack + s_THREAD_TASK->Stack->StackPointer;
   s_THREAD_TASK = s_THREAD_TASK->Next;
   while(s_THREAD_TASK && s_THREAD_TASK != s_THREAD->Task)
   {
    ML_PushSTACK(s_THREAD_TASK->Stack, (int)s_THREAD_TASK->Argument);      
    ML_PushSTACK(s_THREAD_TASK->Stack, (int)s_THREAD);
    ML_PushSTACK(s_THREAD_TASK->Stack, (int)__ML_ReturnTHREAD__);

    ML_PushSTACK(s_THREAD_TASK->Stack, (int)s_THREAD_TASK->Argument);      
    ML_PushSTACK(s_THREAD_TASK->Stack, (int)s_THREAD);
    ML_PushSTACK(s_THREAD_TASK->Stack, (int)__ML_ReturnTHREAD__);

    ML_PushSTACK(s_THREAD_TASK->Stack, (int)s_THREAD_TASK->Entry);  /* First swich entry */
    
    ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.flags);          
    ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.ebp);    
    ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.edi);    
    ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.esi);    
    ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.edx);    
    ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.ecx);    
    ML_PushSTACK(s_THREAD_TASK->Stack, s_Register.ebx);    
    s_THREAD_TASK->ESP = (unsigned int)s_THREAD_TASK->Stack->Stack + s_THREAD_TASK->Stack->StackPointer;
    s_THREAD_TASK = s_THREAD_TASK->Next;
   }
   t_inline_asm(
    "\n\t"
    "movl %1, %%ecx\n\t"
    "movl %0, %%ebp\n\t"
    "movl %%ebp, %%esp\n\t"
    "call *%%ecx\n\t"
    "addl $4 + 4, %%esp\n\t"
    "popl %%ebx\n\t"
    "popl %%ecx\n\t"
    "popl %%edx\n\t"
    "popl %%esi\n\t"
    "popl %%edi\n\t"
    "popl %%ebp\n\t"
    "popl %%eax\n\t" /* Change stack (x86) */
    "popfl\n\t"
    "movl %%eax, %%esp\n\t"
    "\n\t"
    :
    : "m"(s_THREAD->Task->ESP), "m"(s_THREAD->Task->Entry)
   );
  }
 }
 return(s_THREAD);
}

int ML_SleepTHREAD(t_THREAD *s_THREAD)
{
 s_THREAD->CurrentTask->Tick++;
 t_inline_asm(
  "\n\t"
  "movl %%esp, %%eax\n\t"
  "subl $28, %%eax\n\t"
  "\n\t"
  : "=a"(s_THREAD->CurrentTask->ESP)
 );
 do
 {
  s_THREAD->CurrentTask = s_THREAD->CurrentTask->Next;  
  if(s_THREAD->CurrentTask == s_THREAD->Task)
  {
   if(s_THREAD->Task->Active == 1)
   {
    s_THREAD->CurrentTask->Active = 0;    
    continue;
   }
   else break;
  }
 }while(s_THREAD->CurrentTask->Active == 0);
 if(s_THREAD->CurrentTask != s_THREAD->Task)s_THREAD->Task->Active = 1;  
 t_inline_asm(
  "\n\t"
  "pushfl\n\t"
  "pushl %%ebp\n\t"
  "pushl %%edi\n\t"
  "pushl %%esi\n\t"
  "pushl %%edx\n\t"
  "pushl %%ecx\n\t"
  "pushl %%ebx\n\t"
  "movl %0, %%esp\n\t"
  "popl %%ebx\n\t"
  "popl %%ecx\n\t"
  "popl %%edx\n\t"
  "popl %%esi\n\t"
  "popl %%edi\n\t"
  "popl %%ebp\n\t"
  "popfl\n\t"
  "\n\t"
  :
  : "a"(s_THREAD->CurrentTask->ESP)
 );
 return(1);
}

t_STACK *ML_CreateSTACK(int s_StackSize)
{
 t_STACK *s_Return;
 if(s_StackSize < (4 << 10))s_StackSize = (4 << 10);
 s_Return = (t_STACK *)ML_Alloc(sizeof(t_STACK));
 if(s_Return)
 {
  s_Return->Stack = (void *)ML_Alloc(s_StackSize);      
  s_Return->StackSize = s_Return->StackPointer = s_StackSize;
 }
 return(s_Return);
}

t_STACK *ML_DestroySTACK(t_STACK *s_STACK)
{
 if(s_STACK)
 {
  if(s_STACK->Stack && s_STACK->StackSize > 0)(void)ML_Free(s_STACK->Stack);
  (void)ML_Free(s_STACK);
  s_STACK = (t_STACK *)0;
 }      
 return(s_STACK);
}

int ML_PushSTACK(t_STACK *s_STACK, int s_Value)
{
 if(s_STACK)
 {
  if(s_STACK->Stack && s_STACK->StackSize >= sizeof(s_Value) && s_STACK->StackPointer >= sizeof(s_Value))
  {
   s_STACK->StackPointer -= sizeof(s_Value);      
   ML_PokeDoubleWord(s_STACK->Stack, s_STACK->StackPointer, s_Value);
   return(s_STACK->StackPointer);
  }
 }      
 return(0);
}

int ML_PopSTACK(t_STACK *s_STACK, int *s_Value)
{
 int s_Return = (-1);
 if(s_STACK)
 {
  if(s_STACK->Stack && s_STACK->StackSize >= sizeof(int) && s_STACK->StackPointer <= (s_STACK->StackSize - sizeof(int)))
  {
   s_Return = ML_PeekDoubleWord(s_STACK->Stack, s_STACK->StackPointer);          
   s_STACK->StackPointer += sizeof(int);
  }
 }
 if(s_Value)*(s_Value) = s_Return;
 return(s_Return);
}

int ML_SetSTACK(t_STACK *s_STACK, int s_StackPointer)
{
 if(s_STACK)
 {
  s_STACK->StackPointer = s_StackPointer;
  return(s_STACK->StackPointer);
 }
 return(0);
}

#endif

/* End of source */

1.7. Âü°íÀÚ·á

  • ¾ÆÁ÷Àº ¾øÁö¸¸ ã¾Æº¼²²¿ä~

1.8. ¹®¼­¸¦ ¸¶Ä¡¸é¼­

ÀÌ ¹®¼­¿¡¼­ Ʋ¸° ºÎºÐÀ̳ª °íÃÄ¾ß ÇҺκÐÀÌ ÀÖÀ¸¸é ²À ¾Ë·ÁÁֽʽÿä. À̱ÛÀÇ ÃÖ±Ù ¹®¼­´Â http://doc.kldp.org ¿¡¼­ ¸¸³ªº¸½Ç¼ö ÀÖ½À´Ï´Ù. ÇÊÀÚÀÇ È¨ÆäÀÌÁö: [http]http://minzkn.pe.ky

1.9. ÀúÀÛ±Ç

º» ¹®¼­´Â [http]GFDLÀÇ ¶óÀ̼¾½º¸¦ ±â¹ÝÀ¸·Î ÀÛ¼ºµÇ¾ú°í À¯ÁöµË´Ï´Ù.


ID
Password
Join
It is better to wear out than to rust out.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2003-09-11 08:34:35
Processing time 0.0078 sec