thread.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) 2009 Corey Tabaka
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files
  6. * (the "Software"), to deal in the Software without restriction,
  7. * including without limitation the rights to use, copy, modify, merge,
  8. * publish, distribute, sublicense, and/or sell copies of the Software,
  9. * and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <sys/types.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <debug.h>
  27. #include <kernel/thread.h>
  28. #include <arch/x86.h>
  29. #include <arch/x86/descriptor.h>
  30. /*struct context_switch_frame {
  31. uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
  32. uint32_t ds, es, fs, gs;
  33. uint32_t eip, cs, eflags;
  34. };*/
  35. struct context_switch_frame {
  36. uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
  37. uint32_t eflags;
  38. uint32_t eip;
  39. };
  40. extern void x86_context_switch(addr_t *old_sp, addr_t new_sp);
  41. static void initial_thread_func(void) __NO_RETURN;
  42. static void initial_thread_func(void)
  43. {
  44. int ret;
  45. // dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
  46. // dump_thread(current_thread);
  47. /* exit the implicit critical section we're within */
  48. exit_critical_section();
  49. ret = current_thread->entry(current_thread->arg);
  50. // dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
  51. thread_exit(ret);
  52. }
  53. void arch_thread_initialize(thread_t *t)
  54. {
  55. // create a default stack frame on the stack
  56. vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
  57. // make sure the top of the stack is 8 byte aligned for EABI compliance
  58. stack_top = ROUNDDOWN(stack_top, 8);
  59. struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
  60. frame--;
  61. // fill it in
  62. memset(frame, 0, sizeof(*frame));
  63. frame->eip = (vaddr_t) &initial_thread_func;
  64. frame->eflags = 0x3002; // IF = 0, NT = 0, IOPL = 3
  65. //frame->cs = CODE_SELECTOR;
  66. //frame->fs = DATA_SELECTOR;
  67. //frame->gs = DATA_SELECTOR;
  68. //frame->es = DATA_SELECTOR;
  69. //frame->ds = DATA_SELECTOR;
  70. // set the stack pointer
  71. t->arch.esp = (vaddr_t)frame;
  72. }
  73. void arch_context_switch(thread_t *oldthread, thread_t *newthread)
  74. {
  75. //dprintf(DEBUG, "arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
  76. __asm__ __volatile__ (
  77. "pushl $1f \n\t"
  78. "pushf \n\t"
  79. "pusha \n\t"
  80. "movl %%esp,(%%edx) \n\t"
  81. "movl %%eax,%%esp \n\t"
  82. "popa \n\t"
  83. "popf \n\t"
  84. "ret \n\t"
  85. "1: \n\t"
  86. :
  87. : "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
  88. );
  89. /*__asm__ __volatile__ (
  90. "pushf \n\t"
  91. "pushl %%cs \n\t"
  92. "pushl $1f \n\t"
  93. "pushl %%gs \n\t"
  94. "pushl %%fs \n\t"
  95. "pushl %%es \n\t"
  96. "pushl %%ds \n\t"
  97. "pusha \n\t"
  98. "movl %%esp,(%%edx) \n\t"
  99. "movl %%eax,%%esp \n\t"
  100. "popa \n\t"
  101. "popl %%ds \n\t"
  102. "popl %%es \n\t"
  103. "popl %%fs \n\t"
  104. "popl %%gs \n\t"
  105. "iret \n\t"
  106. "1: "
  107. :
  108. : "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
  109. );*/
  110. }