pthread.cpp 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #include <AK/Assertions.h>
  2. #include <AK/Atomic.h>
  3. #include <AK/StdLibExtras.h>
  4. #include <Kernel/Syscall.h>
  5. #include <pthread.h>
  6. #include <stdio.h>
  7. #include <sys/mman.h>
  8. #include <unistd.h>
  9. extern "C" {
  10. static int create_thread(void* (*entry)(void*), void* argument, void* stack)
  11. {
  12. int rc = syscall(SC_create_thread, entry, argument, stack);
  13. __RETURN_WITH_ERRNO(rc, rc, -1);
  14. }
  15. static void exit_thread(void* code)
  16. {
  17. syscall(SC_exit_thread, code);
  18. ASSERT_NOT_REACHED();
  19. }
  20. int pthread_create(pthread_t* thread, pthread_attr_t* attributes, void* (*start_routine)(void*), void* argument_to_start_routine)
  21. {
  22. if (!thread)
  23. return -EINVAL;
  24. UNUSED_PARAM(attributes);
  25. const size_t stack_size = 4 * MB;
  26. auto* stack = (u8*)mmap_with_name(nullptr, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 0, 0, "Thread stack");
  27. if (!stack)
  28. return -1;
  29. int rc = create_thread(start_routine, argument_to_start_routine, stack + stack_size);
  30. if (rc < 0)
  31. return rc;
  32. *thread = rc;
  33. return 0;
  34. }
  35. void pthread_exit(void* value_ptr)
  36. {
  37. exit_thread(value_ptr);
  38. }
  39. int pthread_join(pthread_t thread, void** exit_value_ptr)
  40. {
  41. int rc = syscall(SC_join_thread, thread, exit_value_ptr);
  42. __RETURN_WITH_ERRNO(rc, rc, -1);
  43. }
  44. int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attributes)
  45. {
  46. // FIXME: Implement mutex attributes
  47. UNUSED_PARAM(attributes);
  48. *mutex = 0;
  49. return 0;
  50. }
  51. int pthread_mutex_lock(pthread_mutex_t* mutex)
  52. {
  53. auto* atomic = reinterpret_cast<Atomic<u32>*>(mutex);
  54. for (;;) {
  55. u32 expected = false;
  56. if (atomic->compare_exchange_strong(expected, true, AK::memory_order_acq_rel))
  57. return 0;
  58. sched_yield();
  59. }
  60. }
  61. int pthread_mutex_unlock(pthread_mutex_t* mutex)
  62. {
  63. auto* atomic = reinterpret_cast<Atomic<u32>*>(mutex);
  64. atomic->store(false, AK::memory_order_release);
  65. return 0;
  66. }
  67. }