thread.c 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright (c) 2008 Travis Geiselbrecht
  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/arm.h>
  29. struct context_switch_frame {
  30. vaddr_t r4;
  31. vaddr_t r5;
  32. vaddr_t r6;
  33. vaddr_t r7;
  34. vaddr_t r8;
  35. vaddr_t r9;
  36. vaddr_t r10;
  37. vaddr_t r11;
  38. vaddr_t lr;
  39. vaddr_t usp;
  40. vaddr_t ulr;
  41. };
  42. extern void arm_context_switch(addr_t *old_sp, addr_t new_sp);
  43. static void initial_thread_func(void) __NO_RETURN;
  44. static void initial_thread_func(void)
  45. {
  46. int ret;
  47. // dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
  48. // dump_thread(current_thread);
  49. /* exit the implicit critical section we're within */
  50. exit_critical_section();
  51. ret = current_thread->entry(current_thread->arg);
  52. // dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
  53. thread_exit(ret);
  54. }
  55. void arch_thread_initialize(thread_t *t)
  56. {
  57. // create a default stack frame on the stack
  58. vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
  59. // make sure the top of the stack is 8 byte aligned for EABI compliance
  60. stack_top = ROUNDDOWN(stack_top, 8);
  61. struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
  62. frame--;
  63. // fill it in
  64. memset(frame, 0, sizeof(*frame));
  65. frame->lr = (vaddr_t)&initial_thread_func;
  66. // set the stack pointer
  67. t->arch.sp = (vaddr_t)frame;
  68. }
  69. void arch_context_switch(thread_t *oldthread, thread_t *newthread)
  70. {
  71. // dprintf("arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
  72. arm_context_switch(&oldthread->arch.sp, newthread->arch.sp);
  73. }