Thread.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibThreading/Thread.h>
  7. #include <pthread.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. namespace Threading {
  11. Thread::Thread(Function<intptr_t()> action, StringView thread_name)
  12. : Core::Object(nullptr)
  13. , m_action(move(action))
  14. , m_thread_name(thread_name.is_null() ? ""sv : thread_name)
  15. {
  16. register_property("thread_name", [&] { return JsonValue { m_thread_name }; });
  17. #if defined(AK_OS_SERENITY) || defined(AK_OS_LINUX)
  18. // FIXME: Print out a pretty TID for BSD and macOS platforms, too
  19. register_property("tid", [&] { return JsonValue { m_tid }; });
  20. #endif
  21. }
  22. Thread::~Thread()
  23. {
  24. if (m_tid && !m_detached) {
  25. dbgln("Destroying thread \"{}\"({}) while it is still running!", m_thread_name, m_tid);
  26. [[maybe_unused]] auto res = join();
  27. }
  28. }
  29. ErrorOr<void> Thread::set_priority(int priority)
  30. {
  31. // MacOS has an extra __opaque field, so list initialization will not compile on MacOS Lagom.
  32. sched_param scheduling_parameters {};
  33. scheduling_parameters.sched_priority = priority;
  34. int result = pthread_setschedparam(m_tid, 0, &scheduling_parameters);
  35. if (result != 0)
  36. return Error::from_errno(result);
  37. return {};
  38. }
  39. ErrorOr<int> Thread::get_priority() const
  40. {
  41. sched_param scheduling_parameters {};
  42. int policy;
  43. int result = pthread_getschedparam(m_tid, &policy, &scheduling_parameters);
  44. if (result != 0)
  45. return Error::from_errno(result);
  46. return scheduling_parameters.sched_priority;
  47. }
  48. DeprecatedString Thread::thread_name() const { return m_thread_name; }
  49. pthread_t Thread::tid() const { return m_tid; }
  50. bool Thread::is_started() const { return m_started; }
  51. void Thread::start()
  52. {
  53. int rc = pthread_create(
  54. &m_tid,
  55. nullptr,
  56. [](void* arg) -> void* {
  57. Thread* self = static_cast<Thread*>(arg);
  58. auto exit_code = self->m_action();
  59. self->m_tid = 0;
  60. return reinterpret_cast<void*>(exit_code);
  61. },
  62. static_cast<void*>(this));
  63. VERIFY(rc == 0);
  64. #ifdef AK_OS_SERENITY
  65. if (!m_thread_name.is_empty()) {
  66. rc = pthread_setname_np(m_tid, m_thread_name.characters());
  67. VERIFY(rc == 0);
  68. }
  69. #endif
  70. dbgln("Started thread \"{}\", tid = {}", m_thread_name, m_tid);
  71. m_started = true;
  72. }
  73. void Thread::detach()
  74. {
  75. VERIFY(!m_detached);
  76. int rc = pthread_detach(m_tid);
  77. VERIFY(rc == 0);
  78. m_detached = true;
  79. }
  80. }