· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Thread Design

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

¸ñÂ÷



ÀÛ¼ºÀÚ : Á¶ÀçÇõ (minzkn, Mminzkn_at_infoeq.com)

1.2. °³¿ä

  • ÀÌ ¹®¼­´Â ÀϹÝÀûÀ¸·Î KernelÀÇ ÁøÀÔÁ¡°ú ±âŸ »óȲ¿¡¼­ÀÇ ÃÖ´ëÇÑ °£´ÜÇÑ ThreadÀÇ ±âÃʱ¸ÇöÀ» À§ÇÑ ³»¿ëÀ» Àû¾îº¼±î ÇÕ´Ï´Ù.
  • ºñ¼±Á¡Çü ThreadÀÇ °æ¿ì´Â Á» º¹ÀâÇÒ»Ó ÀÌ ³»¿ëÀ» ÀÌÇØÇÑ µ¶ÀÚ¶ó¸é ÃæºÐÈ÷ °³¼ºÀÖ´Â ¼Ò½º¸¦ âÁ¶ÇϽǼö ÀÖÀ»°Å¶ó ¹Ï¾î ÀǽÉÄ¡ ¾Ê½À´Ï´Ù.
  • ¼³¸í°ú ¿¹Á¦´Â C·Î ±¸¼ºÇÏ·Á°í ³ª¸§´ë·Î ³ë·ÂÇÏ°ÚÁö¸¸ ÇÊÀÚ°¡ ±¸ÇöÇÑ ½ÇÁ¦´Â 100% ¾î¼Àºí¸® ÀÔ´Ï´Ù. ±×·¯ÇÑ °úÁ¤¿¡¼­ ÀϺΠ¼º´É»ó ÃÖÀûÈ­°¡ ±â´ëÄ¡¸¸Å­ ÀÌ·ïÁöÁö ¾ÊÀ»¼ö ÀÖ°í ÄÄÆÄÀϽÿ¡ ÃÖÀûÈ­ ¿É¼ÇÀ» "-O0" ·Î ÇÏ¿© ÃÖÀûÈ­¿¡ ÀÇÇÑ SideEffect¸¦ ¸·¾Æ¾ß ÇÕ´Ï´Ù. ¹°·Ð SideEffect ¸¦ auto, attribute ±¸¹®À¸·Î ¸·À»¼öµµ ÀÖ¾úÁö¸¸ ÀÌ°ÍÀ» C·Î Æ÷ÆÃÇÒ ´ç½Ã¿¡´Â ±×·¯ÇÑ ¹æ¹ýÀ» ¸ô¶ú¾ú½À´Ï´Ù. ¤Ñ¤Ñ;
  • ¼±Á¡Çü°ú ºñ¼±Á¡ÇüÀ» »ó´çÈ÷ ´Ù¸¥ ¼³°è·Î º¸½Ã´Â ½Ã°¢ÀÌ ¸¹Áö¸¸ ÇÊÀÚ »ý°¢À¸·Î´Â (´Ù¸¥ ÀÌ°ßÀÌ ¸¹°ÚÁö¸¸) ¼³°è±¸Á¶´Â °°°í ÀÌ¿ëÇÏ´Â ¹æ¹ý·Ð¿¡¼­ Â÷À̸¦ º¸ÀÎ´Ù°í »ý°¢Çϳ׿ä. ¶§¹®¿¡ ¾Æ·¡ÀÇ ¿¹Á¦¸¦ ÀûÀýÇÑ (ºñµ¿±âÀû Á¦¾îÁ¡À» ÀÌ¿ëÇÑ´Ù´Â Àǹ̷Î) Timer interrupt¿¡¼­ Sleep(ContextSwitch) À» ÇÏ¸é ºñ¼±Á¡ÇüÀÌ µÇ´Â°ÍÀÌ°í ÇöÀç ÀÛ¾÷ Task¿¡¼­ SleepÀ» Á÷Á¢ »ç¿ëÇÏ¸é ¼±Á¡Çü Á¦¾î°¡ µÇ´Â°ÍÀÌ°ÚÁÒ. ¾î¶² OS´Â ¼±Á¡ÇüÀÌ´Ù ºñ¼±Á¡ÇüÀÌ´Ù ¶ó°í ¿¹±âÇϱ⵵ Çϴµ¥ RTOS°¡ ¾Æ´Ñ ÀÌ»óÀº ´ëºÎºÐÀÇ OS´Â ¼±Á¡Çü°ú ºñ¼±Á±ÇüÀÌ ÀûÀýÈ÷ È¥ÇÕÇØ »ç¿ëÇÏ´Â°Ô ´ëºÎºÐÀεí ÇÕ´Ï´Ù.
  • ¾î¼Àºí¸® ÀÇÁ¸À» ÇÏÁö ¾Ê°í ¸¸µé±â À§Çؼ­ longjmp ¸¦ ÀÌ¿ëÇØ º¼¼ö ÀÖÀ½Á÷ Çѵ¥ ¾ðÁ¨°¡ ½Ã°£³ª¸é ±¸ÇöÇØ ºÁ¾ß ÇÒµí ÇÕ´Ï´Ù. °¡´ÉÇÒÁö´Â ¹ÌÁö¼ö ¤Ñ¤Ñ;

1.3. Thread design

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

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

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

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

1.3.3. How to swap

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

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

1.5. ¿¹Á¦

/*
[ GPL ]
Code by JaeHyuk Cho <mailto:minzkn@infoeq.com> KOREA

MZ Local Thread library v0.0.1b

- Simple is best !
*/

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define t_inline_asm __asm__ __volatile__
#define ML_Alloc(m_size) malloc(m_size)
#define ML_Free(m_ptr) free(m_ptr)
#define ML_PeekPtr(m_cast,m_base,m_offset) ((m_cast)(((unsigned char *)(m_base)) + (m_offset)))
#define ML_PeekDoubleWord(m_ptr,m_offset) *ML_PeekPtr(unsigned long *,m_ptr,m_offset)
#define ML_PokeDoubleWord(m_ptr,m_offset,m_value) *ML_PeekPtr(unsigned long *,m_ptr,m_offset) = m_value

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




#if 1 /* TEST ------------------------------- */
void * (test_0)(void *s_thread_handle, void *s_argument)
{
 int s_count = 0;
 while((s_count++) < 100)
 {
  (void)printf("test_0 : %3d (\"%s\")\n", s_count, (char *)s_argument);
  (void)ML_SleepTHREAD((t_THREAD *)s_thread_handle);  /* context switch */
 }
 return(s_argument);
}

void * (test_1)(void *s_thread_handle, void *s_argument)
{
 int s_count = 0;
 while((s_count++) < 100)
 {
  (void)printf("test_1 : %3d (\"%s\")\n", s_count, (char *)s_argument);
  (void)ML_SleepTHREAD((t_THREAD *)s_thread_handle);  /* context switch */
 }
 return(s_argument);
}

void * (test_2)(void *s_thread_handle, void *s_argument)
{
 int s_count = 0;
 while((s_count++) < 100)
 {
  (void)printf("test_2 : %3d (\"%s\")\n", s_count, (char *)s_argument);
  (void)ML_SleepTHREAD((t_THREAD *)s_thread_handle);  /* context switch */
 }
 return(s_argument);
}

void * (test_3)(void *s_thread_handle, void *s_argument)
{
 int s_count = 0;
 while((s_count++) < 100)
 {
  (void)printf("test_3 : %3d (\"%s\")\n", s_count, (char *)s_argument);
  (void)ML_SleepTHREAD((t_THREAD *)s_thread_handle);  /* context switch */
 }
 return(s_argument);
}

int main(void)
{
 t_THREAD *s_thread;
 s_thread = ML_CreateTHREAD();

 ML_AddTHREAD(s_thread, test_0, "USER ARGUMENT - 0", (8 << 10));
 ML_AddTHREAD(s_thread, test_1, "USER ARGUMENT - 1", (8 << 10));
 ML_AddTHREAD(s_thread, test_2, "USER ARGUMENT - 2", (8 << 10));
 ML_AddTHREAD(s_thread, test_3, "USER ARGUMENT - 3", (8 << 10));

 (void)printf("Run.\n");
 ML_RunTHREAD(s_thread);
 (void)printf("End.\n");
 
 s_thread = ML_DestroyTHREAD(s_thread);
 return(0);
}
#endif /* TEST ------------------------------- */




#if 0 /* TEST ------------------------------- */
void * (test_0)(void *s_thread_handle, void *s_argument)
{
 int s_context = *((int *)s_argument);
 int s_count;
 int s_color;
 s_color = (s_context % 6) + 31;
 (void)printf("[color=%d] \x1b[1;%dmbegin thread (id=%d)\x1b[0m\n", s_color, s_color, s_context);
 for(s_count = 0;s_count < 100;s_count++)
 {
  (void)printf("[color=%d] \x1b[1;%dmtest thread (id=%d, count=%d)\x1b[0m\n", s_color, s_color, s_context, s_count);
  (void)ML_SleepTHREAD((t_THREAD *)s_thread_handle);  /* context switch */
 }
 (void)printf("[color=%d] \x1b[1;%dmend thread (id=%d)\x1b[0m\n", s_color, s_color, s_context);
 return(s_argument);
}

int main(void)
{
 t_THREAD *s_thread;
 int s_count;
 int s_context[ 10 ];
 s_thread = ML_CreateTHREAD();

 for(s_count = 0;s_count < (sizeof(s_context) / sizeof(int));s_count++)
 {
  s_context[s_count] = s_count;
  ML_AddTHREAD(s_thread, test_0, &s_context[s_count], (8 << 10));
 }

 (void)printf("Run.\n");
 ML_RunTHREAD(s_thread);
 (void)printf("End.\n");
 
 s_thread = ML_DestroyTHREAD(s_thread);
 return(0);
}
#endif /* TEST ------------------------------- */





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.6. ¹®¼­¸¦ ¸¶Ä¡¸ç


  • ThreadÀÇ ¼³°è´Â ´Ù¾çÇÑ ¹æ¹ýÀÌ Á¸ÀçÇÒ¼ö ÀÖ°í ¿©·¯°¡Áö Æ®¸¯ÀÌ ÀÖ´Ù°í ÇÊÀÚ´Â »ý°¢ÇÕ´Ï´Ù. Ȥ½Ã¶óµµ ¶Ç ´Ù¸¥ Á¢±Ù¹ýÀÌ ÀÖ´Ù¸é ¼Ò°³ÇØÁÖ¼¼¿ä.
  • ÀÌ ¹®¼­ÀÇ ÃÖ±Ù¹öÁ¯Àº [http]http://www.minzkn.com:2744/ ¿¡¼­ ±¸ÇÒ¼ö ÀÖ½À´Ï´Ù.



ID
Password
Join
It is a poor judge who cannot award a prize.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-02-06 19:20:53
Processing time 0.0089 sec