Device.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Singleton.h>
  7. #include <Kernel/Devices/Device.h>
  8. #include <Kernel/FileSystem/InodeMetadata.h>
  9. #include <Kernel/Locking/MutexProtected.h>
  10. #include <Kernel/Sections.h>
  11. namespace Kernel {
  12. static Singleton<MutexProtected<HashMap<u32, Device*>>> s_all_devices;
  13. MutexProtected<HashMap<u32, Device*>>& Device::all_devices()
  14. {
  15. return *s_all_devices;
  16. }
  17. void Device::for_each(Function<void(Device&)> callback)
  18. {
  19. all_devices().with_exclusive([&](auto& map) -> void {
  20. for (auto& entry : map)
  21. callback(*entry.value);
  22. });
  23. }
  24. Device* Device::get_device(unsigned major, unsigned minor)
  25. {
  26. return all_devices().with_exclusive([&](auto& map) -> Device* {
  27. auto it = map.find(encoded_device(major, minor));
  28. if (it == map.end())
  29. return nullptr;
  30. return it->value;
  31. });
  32. }
  33. Device::Device(unsigned major, unsigned minor)
  34. : m_major(major)
  35. , m_minor(minor)
  36. {
  37. u32 device_id = encoded_device(major, minor);
  38. all_devices().with_exclusive([&](auto& map) -> void {
  39. auto it = map.find(device_id);
  40. if (it != map.end()) {
  41. dbgln("Already registered {},{}: {}", major, minor, it->value->class_name());
  42. }
  43. VERIFY(!map.contains(device_id));
  44. map.set(device_id, this);
  45. });
  46. }
  47. Device::~Device()
  48. {
  49. u32 device_id = encoded_device(m_major, m_minor);
  50. all_devices().with_exclusive([&](auto& map) -> void {
  51. VERIFY(map.contains(device_id));
  52. map.remove(encoded_device(m_major, m_minor));
  53. });
  54. }
  55. String Device::absolute_path() const
  56. {
  57. // FIXME: I assume we can't really provide a well known path in the kernel
  58. // because this is a violation of abstraction layers between userland and the
  59. // kernel, but maybe the whole name of "absolute_path" is just wrong as this
  60. // is really not an "absolute_path".
  61. return String::formatted("device:{},{}", major(), minor());
  62. }
  63. String Device::absolute_path(const OpenFileDescription&) const
  64. {
  65. return absolute_path();
  66. }
  67. void Device::process_next_queued_request(Badge<AsyncDeviceRequest>, const AsyncDeviceRequest& completed_request)
  68. {
  69. SpinlockLocker lock(m_requests_lock);
  70. VERIFY(!m_requests.is_empty());
  71. VERIFY(m_requests.first().ptr() == &completed_request);
  72. m_requests.remove(m_requests.begin());
  73. if (!m_requests.is_empty()) {
  74. auto* next_request = m_requests.first().ptr();
  75. next_request->do_start(move(lock));
  76. }
  77. evaluate_block_conditions();
  78. }
  79. }