Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ver 0.25 (not yet released)
- pipewire: add option "reconnect_stream"
* player
- support replay gain parameter in stream URI
- preallocate physical RAM for audio buffer when playback starts
* switch to C++23
* require Meson 1.2

Expand Down
29 changes: 20 additions & 9 deletions src/MusicBuffer.hxx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project

#ifndef MPD_MUSIC_BUFFER_HXX
#define MPD_MUSIC_BUFFER_HXX
#pragma once

#include "MusicChunk.hxx"
#include "MusicChunkPtr.hxx"
Expand All @@ -29,9 +28,10 @@ public:

#ifndef NDEBUG
/**
* Check whether the buffer is empty. This call is not
* protected with the mutex, and may only be used while this
* object is inaccessible to other threads.
* Check whether the buffer is empty.
*
* This call is not protected with the #mutex, and may only be
* used while this object is inaccessible to other threads.
*/
bool IsEmptyUnsafe() const {
return buffer.empty();
Expand All @@ -45,14 +45,27 @@ public:

/**
* Returns the total number of reserved chunks in this buffer. This
* is the same value which was passed to the constructor
* music_buffer_new().
* is the same value which was passed to the constructor.
*/
[[gnu::pure]]
unsigned GetSize() const noexcept {
return buffer.GetCapacity();
}

void PopulateMemory() noexcept {
buffer.PopulateMemory();
}

/**
* Give all memory allocations back to the kernel.
*
* This call is not protected with the #mutex, and may only be
* used while this object is inaccessible to other threads.
*/
void DiscardMemory() noexcept {
buffer.DiscardMemory();
}

/**
* Allocates a chunk from the buffer. When it is not used anymore,
* call Return().
Expand All @@ -68,5 +81,3 @@ public:
*/
void Return(MusicChunk *chunk) noexcept;
};

#endif
7 changes: 2 additions & 5 deletions src/event/Backend.hxx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project

#ifndef EVENT_BACKEND_HXX
#define EVENT_BACKEND_HXX
#pragma once

#include "event/Features.h"
#include "event/config.h"

#ifdef _WIN32

Expand All @@ -22,5 +21,3 @@ using EventPollBackend = EpollBackend;
using EventPollBackend = PollBackend;

#endif

#endif
2 changes: 1 addition & 1 deletion src/event/BackendEvents.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#pragma once

#include "event/Features.h"
#include "event/config.h" // for USE_EPOLL

#ifdef _WIN32

Expand Down
1 change: 0 additions & 1 deletion src/event/FineTimerEvent.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#pragma once

#include "Chrono.hxx"
#include "event/Features.h"
#include "util/BindMethod.hxx"
#include "util/IntrusiveTreeSet.hxx"

Expand Down
2 changes: 1 addition & 1 deletion src/event/Loop.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#include "Chrono.hxx"
#include "TimerWheel.hxx"
#include "Backend.hxx"
#include "event/Features.h"
#include "time/ClockCache.hxx"
#include "util/IntrusiveList.hxx"
#include "event/config.h"

#ifndef NO_FINE_TIMER_EVENT
#include "TimerList.hxx"
Expand Down
7 changes: 2 additions & 5 deletions src/event/MultiSocketMonitor.hxx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project

#ifndef MPD_MULTI_SOCKET_MONITOR_HXX
#define MPD_MULTI_SOCKET_MONITOR_HXX
#pragma once

#include "IdleEvent.hxx"
#include "FineTimerEvent.hxx"
#include "SocketEvent.hxx"
#include "event/Features.h"
#include "event/config.h"

#include <cassert>
#include <forward_list>
Expand Down Expand Up @@ -244,5 +243,3 @@ private:

void OnIdle() noexcept;
};

#endif
2 changes: 1 addition & 1 deletion src/event/SignalMonitor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright The Music Player Daemon Project

#include "SignalMonitor.hxx"
#include "event/Features.h"
#include "event/config.h"

#ifndef _WIN32

Expand Down
1 change: 0 additions & 1 deletion src/event/SocketEvent.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "SocketEvent.hxx"
#include "Loop.hxx"
#include "event/Features.h"

#include <cassert>
#include <utility>
Expand Down
2 changes: 1 addition & 1 deletion src/event/SocketEvent.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#pragma once

#include "BackendEvents.hxx"
#include "event/Features.h" // for USE_EPOLL
#include "event/config.h" // for USE_EPOLL
#include "net/SocketDescriptor.hxx"
#include "util/BindMethod.hxx"
#include "util/IntrusiveList.hxx"
Expand Down
2 changes: 1 addition & 1 deletion src/event/TimerList.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ TimerList::GetDue::operator()(const FineTimerEvent &timer) const noexcept
return timer.GetDue();
}

TimerList::TimerList() = default;
TimerList::TimerList() noexcept = default;

TimerList::~TimerList() noexcept
{
Expand Down
3 changes: 1 addition & 2 deletions src/event/TimerList.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#pragma once

#include "Chrono.hxx"
#include "event/Features.h"
#include "util/IntrusiveTreeSet.hxx"

class FineTimerEvent;
Expand All @@ -22,7 +21,7 @@ class TimerList final {
IntrusiveTreeSetOperators<FineTimerEvent, GetDue>> timers;

public:
TimerList();
TimerList() noexcept;
~TimerList() noexcept;

TimerList(const TimerList &other) = delete;
Expand Down
7 changes: 2 additions & 5 deletions src/event/WakeFD.hxx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project

#ifndef MPD_WAKE_FD_HXX
#define MPD_WAKE_FD_HXX
#pragma once

#include "net/SocketDescriptor.hxx"
#include "event/Features.h"
#include "event/config.h"

#ifdef USE_EVENTFD
#include "system/EventFD.hxx"
Expand Down Expand Up @@ -37,5 +36,3 @@ public:
fd.Write();
}
};

#endif
2 changes: 1 addition & 1 deletion src/event/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ event_features.set('USE_EVENTFD', is_linux and get_option('eventfd'))
event_features.set('USE_SIGNALFD', is_linux and get_option('signalfd'))
event_features.set('USE_EPOLL', is_linux and get_option('epoll'))
event_features.set('HAVE_THREADED_EVENT_LOOP', true)
configure_file(output: 'Features.h', configuration: event_features)
configure_file(output: 'config.h', configuration: event_features)

event_sources = []

Expand Down
7 changes: 7 additions & 0 deletions src/memory/HugeAllocator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ HugeForkCow(std::span<std::byte> p, bool enable) noexcept
EnablePageFork(AlignToPageSize(p), enable);
}

void
HugePopulate(std::span<std::byte> p) noexcept
{
PagesPopulateWrite(p);
CollapseHugePages(p);
}

void
HugeDiscard(std::span<std::byte> p) noexcept
{
Expand Down
18 changes: 18 additions & 0 deletions src/memory/HugeAllocator.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ HugeSetName(std::span<std::byte> p, const char *name) noexcept;
void
HugeForkCow(std::span<std::byte> p, bool enable) noexcept;

/**
* Populate (prefault) page tables writable, faulting in all pages in
* the range just as if manually writing to each each page.
*/
void
HugePopulate(std::span<std::byte> p) noexcept;

/**
* Discard any data stored in the allocation and give the memory back
* to the kernel. After returning, the allocation still exists and
Expand Down Expand Up @@ -75,6 +82,12 @@ HugeForkCow(std::span<std::byte>, bool) noexcept
{
}

static inline void
HugePopulate(std::span<std::byte> p) noexcept
{
VirtualAlloc(p.data(), p.size(), MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS);
}

static inline void
HugeDiscard(std::span<std::byte> p) noexcept
{
Expand Down Expand Up @@ -109,6 +122,11 @@ HugeForkCow(std::span<std::byte>, bool) noexcept
{
}

static inline void
HugePopulate(std::span<std::byte>) noexcept
{
}

static inline void
HugeDiscard(std::span<std::byte>) noexcept
{
Expand Down
8 changes: 8 additions & 0 deletions src/memory/HugeArray.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include "HugeAllocator.hxx"
#include "util/SpanCast.hxx"

#ifdef __linux__
#include "system/PageAllocator.hxx"
#endif

#include <utility>

/**
Expand Down Expand Up @@ -51,6 +55,10 @@ public:
HugeForkCow(std::as_writable_bytes(buffer), enable);
}

void Populate() noexcept {
HugePopulate(std::as_writable_bytes(buffer));
}

void Discard() noexcept {
HugeDiscard(std::as_writable_bytes(buffer));
}
Expand Down
10 changes: 4 additions & 6 deletions src/memory/SliceBuffer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public:
buffer.SetName(name);
}

void PopulateMemory() noexcept {
buffer.Populate();
}

void DiscardMemory() noexcept {
assert(empty());

Expand Down Expand Up @@ -120,11 +124,5 @@ public:
slice->next = available;
available = slice;
--n_allocated;

/* give memory back to the kernel when the last slice
was freed */
if (n_allocated == 0) {
DiscardMemory();
}
}
};
7 changes: 7 additions & 0 deletions src/player/Thread.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,12 @@ try {

{
const ScopeUnlock unlock(mutex);

/* allocate physical RAM for the whole
buffer to reduce page faults
later */
buffer.PopulateMemory();

do_play(*this, dc, buffer);

/* give the main thread a chance to
Expand Down Expand Up @@ -1306,6 +1312,7 @@ try {
CommandFinished();

assert(buffer.IsEmptyUnsafe());
buffer.DiscardMemory();

break;

Expand Down
Loading