event/Loop: explicit io_uring initialization

Log the io_uring initialization error at MPD startup.
This commit is contained in:
Max Kellermann 2025-02-01 17:38:28 +01:00
parent 63cc07b8a7
commit 00a352ffcd
4 changed files with 79 additions and 34 deletions

@ -13,8 +13,6 @@
#ifdef HAVE_URING
#include "uring/Manager.hxx"
#include "util/PrintException.hxx"
#include <stdio.h>
#endif
EventLoop::EventLoop(
@ -53,26 +51,46 @@ EventLoop::~EventLoop() noexcept
assert(ready_sockets.empty());
}
void
EventLoop::SetVolatile() noexcept
{
#ifdef HAVE_URING
if (uring)
uring->SetVolatile();
#endif
}
#ifdef HAVE_URING
void
EventLoop::EnableUring(unsigned entries, unsigned flags)
{
assert(!uring);
uring = std::make_unique<Uring::Manager>(*this, entries, flags);
}
void
EventLoop::EnableUring(unsigned entries, struct io_uring_params &params)
{
assert(!uring);
uring = std::make_unique<Uring::Manager>(*this, entries, params);
}
void
EventLoop::DisableUring() noexcept
{
uring.reset();
}
Uring::Queue *
EventLoop::GetUring() noexcept
{
if (!uring_initialized) {
uring_initialized = true;
try {
uring = std::make_unique<Uring::Manager>(*this, 1024,
IORING_SETUP_SINGLE_ISSUER);
} catch (...) {
fprintf(stderr, "Failed to initialize io_uring: ");
PrintException(std::current_exception());
}
}
return uring.get();
}
#endif
#endif // HAVE_URING
bool
EventLoop::AddFD(int fd, unsigned events, SocketEvent &event) noexcept
@ -280,17 +298,6 @@ EventLoop::Run() noexcept
wake_event.Schedule(SocketEvent::READ);
#endif
#ifdef HAVE_URING
AtScopeExit(this) {
/* make sure that the Uring::Manager gets destructed
from within the EventThread, or else its
destruction in another thread will cause assertion
failures */
uring.reset();
uring_initialized = false;
};
#endif
#ifdef HAVE_THREADED_EVENT_LOOP
AtScopeExit(this) {
wake_event.Cancel();

@ -27,6 +27,7 @@
#include "io/uring/Features.h"
#ifdef HAVE_URING
#include <memory>
struct io_uring_params;
namespace Uring { class Queue; class Manager; }
#endif
@ -133,10 +134,6 @@ class EventLoop final
bool busy = true;
#endif
#ifdef HAVE_URING
bool uring_initialized = false;
#endif
ClockCache<std::chrono::steady_clock> steady_clock_cache;
public:
@ -185,8 +182,27 @@ public:
steady_clock_cache.flush();
}
void SetVolatile() noexcept;
#ifdef HAVE_URING
[[gnu::pure]]
/**
* Try to enable io_uring support. If this method succeeds,
* GetUring() can be used to obtain a pointer to the queue
* instance.
*
* Throws on error.
*/
void EnableUring(unsigned entries, unsigned flags);
void EnableUring(unsigned entries, struct io_uring_params &params);
void DisableUring() noexcept;
/**
* Returns a pointer to the io_uring queue instance or nullptr
* if io_uring support is not available (or was not enabled
* using EnableUring()).
*/
[[nodiscard]] [[gnu::const]]
Uring::Queue *GetUring() noexcept;
#endif

@ -9,6 +9,11 @@
#include "util/Domain.hxx"
#include "Log.hxx"
#ifdef HAVE_URING
#include "util/ScopeExit.hxx"
#include <liburing.h>
#endif
static constexpr Domain event_domain("event");
void
@ -51,7 +56,27 @@ EventThread::Run() noexcept
"RTIOThread could not get realtime scheduling, continuing anyway: {}",
std::current_exception());
}
} else {
#ifdef HAVE_URING
try {
event_loop.EnableUring(1024, IORING_SETUP_SINGLE_ISSUER);
} catch (...) {
FmtInfo(event_domain,
"Failed to initialize io_uring: {}",
std::current_exception());
}
#endif
}
#ifdef HAVE_URING
AtScopeExit(this) {
/* make sure that the Uring::Manager gets destructed
from within the EventThread, or else its
destruction in another thread will cause assertion
failures */
event_loop.DisableUring();
};
#endif
event_loop.Run();
}

@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#ifndef MPD_EVENT_THREAD_HXX
#define MPD_EVENT_THREAD_HXX
#pragma once
#include "Loop.hxx"
#include "thread/Thread.hxx"
@ -36,5 +35,3 @@ public:
private:
void Run() noexcept;
};
#endif /* MAIN_NOTIFY_H */