AsyncDeviceRequest.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/IntrusiveList.h>
  8. #include <AK/NonnullRefPtr.h>
  9. #include <Kernel/Memory/ScopedAddressSpaceSwitcher.h>
  10. #include <Kernel/Process.h>
  11. #include <Kernel/Thread.h>
  12. #include <Kernel/UserOrKernelBuffer.h>
  13. #include <Kernel/WaitQueue.h>
  14. namespace Kernel {
  15. class Device;
  16. extern WorkQueue* g_io_work;
  17. class AsyncDeviceRequest : public RefCounted<AsyncDeviceRequest> {
  18. AK_MAKE_NONCOPYABLE(AsyncDeviceRequest);
  19. AK_MAKE_NONMOVABLE(AsyncDeviceRequest);
  20. public:
  21. enum [[nodiscard]] RequestResult {
  22. Pending = 0,
  23. Started,
  24. Success,
  25. Failure,
  26. MemoryFault,
  27. OutOfMemory,
  28. Cancelled
  29. };
  30. class RequestWaitResult {
  31. friend class AsyncDeviceRequest;
  32. public:
  33. RequestResult request_result() const { return m_request_result; }
  34. Thread::BlockResult wait_result() const { return m_wait_result; }
  35. private:
  36. RequestWaitResult(RequestResult request_result, Thread::BlockResult wait_result)
  37. : m_request_result(request_result)
  38. , m_wait_result(wait_result)
  39. {
  40. }
  41. RequestResult m_request_result;
  42. Thread::BlockResult m_wait_result;
  43. };
  44. virtual ~AsyncDeviceRequest();
  45. virtual StringView name() const = 0;
  46. virtual void start() = 0;
  47. void add_sub_request(NonnullRefPtr<AsyncDeviceRequest>);
  48. [[nodiscard]] RequestWaitResult wait(Time* = nullptr);
  49. void do_start(SpinlockLocker<Spinlock>&& requests_lock)
  50. {
  51. if (is_completed_result(m_result))
  52. return;
  53. m_result = Started;
  54. requests_lock.unlock();
  55. start();
  56. }
  57. void complete(RequestResult result);
  58. void set_private(void* priv)
  59. {
  60. VERIFY(!m_private || !priv);
  61. m_private = priv;
  62. }
  63. void* get_private() const { return m_private; }
  64. template<typename... Args>
  65. ErrorOr<void> write_to_buffer(UserOrKernelBuffer& buffer, Args... args)
  66. {
  67. if (in_target_context(buffer))
  68. return buffer.write(forward<Args>(args)...);
  69. ScopedAddressSpaceSwitcher switcher(m_process);
  70. return buffer.write(forward<Args>(args)...);
  71. }
  72. template<size_t BUFFER_BYTES, typename... Args>
  73. ErrorOr<size_t> write_to_buffer_buffered(UserOrKernelBuffer& buffer, Args... args)
  74. {
  75. if (in_target_context(buffer))
  76. return buffer.write_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  77. ScopedAddressSpaceSwitcher switcher(m_process);
  78. return buffer.write_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  79. }
  80. template<typename... Args>
  81. ErrorOr<void> read_from_buffer(UserOrKernelBuffer const& buffer, Args... args)
  82. {
  83. if (in_target_context(buffer))
  84. return buffer.read(forward<Args>(args)...);
  85. ScopedAddressSpaceSwitcher switcher(m_process);
  86. return buffer.read(forward<Args>(args)...);
  87. }
  88. template<size_t BUFFER_BYTES, typename... Args>
  89. ErrorOr<size_t> read_from_buffer_buffered(UserOrKernelBuffer const& buffer, Args... args)
  90. {
  91. if (in_target_context(buffer))
  92. return buffer.read_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  93. ScopedAddressSpaceSwitcher switcher(m_process);
  94. return buffer.read_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  95. }
  96. protected:
  97. AsyncDeviceRequest(Device&);
  98. RequestResult get_request_result() const;
  99. private:
  100. void sub_request_finished(AsyncDeviceRequest&);
  101. void request_finished();
  102. [[nodiscard]] bool in_target_context(UserOrKernelBuffer const& buffer) const
  103. {
  104. if (buffer.is_kernel_buffer())
  105. return true;
  106. return m_process == &Process::current();
  107. }
  108. [[nodiscard]] static bool is_completed_result(RequestResult result)
  109. {
  110. return result > Started;
  111. }
  112. Device& m_device;
  113. AsyncDeviceRequest* m_parent_request { nullptr };
  114. RequestResult m_result { Pending };
  115. IntrusiveListNode<AsyncDeviceRequest, RefPtr<AsyncDeviceRequest>> m_list_node;
  116. using AsyncDeviceSubRequestList = IntrusiveList<&AsyncDeviceRequest::m_list_node>;
  117. AsyncDeviceSubRequestList m_sub_requests_pending;
  118. AsyncDeviceSubRequestList m_sub_requests_complete;
  119. WaitQueue m_queue;
  120. NonnullRefPtr<Process> m_process;
  121. void* m_private { nullptr };
  122. mutable Spinlock m_lock { LockRank::None };
  123. };
  124. }