· 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
Show your affection, which will probably meet with pleasant response.


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.0104 sec