AsyncDeviceRequest.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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/ProcessPagingScope.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. Cancelled
  28. };
  29. class RequestWaitResult {
  30. friend class AsyncDeviceRequest;
  31. public:
  32. RequestResult request_result() const { return m_request_result; }
  33. Thread::BlockResult wait_result() const { return m_wait_result; }
  34. private:
  35. RequestWaitResult(RequestResult request_result, Thread::BlockResult wait_result)
  36. : m_request_result(request_result)
  37. , m_wait_result(wait_result)
  38. {
  39. }
  40. RequestResult m_request_result;
  41. Thread::BlockResult m_wait_result;
  42. };
  43. virtual ~AsyncDeviceRequest();
  44. virtual StringView name() const = 0;
  45. virtual void start() = 0;
  46. void add_sub_request(NonnullRefPtr<AsyncDeviceRequest>);
  47. [[nodiscard]] RequestWaitResult wait(Time* = nullptr);
  48. void do_start(SpinlockLocker<Spinlock<u8>>&& requests_lock)
  49. {
  50. if (is_completed_result(m_result))
  51. return;
  52. m_result = Started;
  53. requests_lock.unlock();
  54. start();
  55. }
  56. void complete(RequestResult result);
  57. void set_private(void* priv)
  58. {
  59. VERIFY(!m_private || !priv);
  60. m_private = priv;
  61. }
  62. void* get_private() const { return m_private; }
  63. template<typename... Args>
  64. [[nodiscard]] bool write_to_buffer(UserOrKernelBuffer& buffer, Args... args)
  65. {
  66. if (in_target_context(buffer))
  67. return buffer.write(forward<Args>(args)...);
  68. ProcessPagingScope paging_scope(m_process);
  69. return buffer.write(forward<Args>(args)...);
  70. }
  71. template<size_t BUFFER_BYTES, typename... Args>
  72. [[nodiscard]] KResultOr<size_t> write_to_buffer_buffered(UserOrKernelBuffer& buffer, Args... args)
  73. {
  74. if (in_target_context(buffer))
  75. return buffer.write_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  76. ProcessPagingScope paging_scope(m_process);
  77. return buffer.write_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  78. }
  79. template<typename... Args>
  80. [[nodiscard]] bool read_from_buffer(const UserOrKernelBuffer& buffer, Args... args)
  81. {
  82. if (in_target_context(buffer))
  83. return buffer.read(forward<Args>(args)...);
  84. ProcessPagingScope paging_scope(m_process);
  85. return buffer.read(forward<Args>(args)...);
  86. }
  87. template<size_t BUFFER_BYTES, typename... Args>
  88. [[nodiscard]] KResultOr<size_t> read_from_buffer_buffered(const UserOrKernelBuffer& buffer, Args... args)
  89. {
  90. if (in_target_context(buffer))
  91. return buffer.read_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  92. ProcessPagingScope paging_scope(m_process);
  93. return buffer.read_buffered<BUFFER_BYTES>(forward<Args>(args)...);
  94. }
  95. protected:
  96. AsyncDeviceRequest(Device&);
  97. RequestResult get_request_result() const;
  98. private:
  99. void sub_request_finished(AsyncDeviceRequest&);
  100. void request_finished();
  101. [[nodiscard]] bool in_target_context(const UserOrKernelBuffer& buffer) const
  102. {
  103. if (buffer.is_kernel_buffer())
  104. return true;
  105. return m_process == &Process::current();
  106. }
  107. [[nodiscard]] static bool is_completed_result(RequestResult result)
  108. {
  109. return result > Started;
  110. }
  111. Device& m_device;
  112. AsyncDeviceRequest* m_parent_request { nullptr };
  113. RequestResult m_result { Pending };
  114. IntrusiveListNode<AsyncDeviceRequest, RefPtr<AsyncDeviceRequest>> m_list_node;
  115. using AsyncDeviceSubRequestList = IntrusiveList<AsyncDeviceRequest, RefPtr<AsyncDeviceRequest>, &AsyncDeviceRequest::m_list_node>;
  116. AsyncDeviceSubRequestList m_sub_requests_pending;
  117. AsyncDeviceSubRequestList m_sub_requests_complete;
  118. WaitQueue m_queue;
  119. NonnullRefPtr<Process> m_process;
  120. void* m_private { nullptr };
  121. mutable Spinlock<u8> m_lock;
  122. };
  123. }