diff --git a/NEWS b/NEWS index dd08e4b24..7db9cd4da 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,7 @@ ver 0.19 (not yet released) * threads: - the update thread runs at "idle" priority - the output thread runs at "real-time" priority + - increase kernel timer slack on Linux - name each thread (for debugging) * new resampler option using libsoxr diff --git a/configure.ac b/configure.ac index 0da4eb645..80e50191e 100644 --- a/configure.ac +++ b/configure.ac @@ -184,6 +184,8 @@ AC_SEARCH_LIBS([exp], [m],, AC_CHECK_HEADERS(locale.h) AC_CHECK_HEADERS(valgrind/memcheck.h) +AC_CHECK_HEADERS([sys/prctl.h], AC_CHECK_FUNCS([prctl])) + AC_CHECK_LIB([pthread], [pthread_setname_np], [have_pthread_setname_np=yes], [have_pthread_setname_np=no]) diff --git a/src/Main.cxx b/src/Main.cxx index f8f7a6545..ab70c875c 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -60,6 +60,7 @@ #include "util/Error.hxx" #include "util/Domain.hxx" #include "thread/Id.hxx" +#include "thread/Slack.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigData.hxx" #include "config/ConfigDefaults.hxx" @@ -523,6 +524,10 @@ int mpd_main(int argc, char *argv[]) win32_app_started(); #endif + /* the MPD frontend does not care about timer slack; set it to + a huge value to allow the kernel to reduce CPU wakeups */ + SetThreadTimerSlackMS(100); + /* run the main loop */ main_loop->Run(); diff --git a/src/output/OutputThread.cxx b/src/output/OutputThread.cxx index 05d9468b4..a7fb2b87f 100644 --- a/src/output/OutputThread.cxx +++ b/src/output/OutputThread.cxx @@ -30,6 +30,7 @@ #include "MusicPipe.hxx" #include "MusicChunk.hxx" #include "thread/Util.hxx" +#include "thread/Slack.hxx" #include "thread/Name.hxx" #include "system/FatalError.hxx" #include "util/Error.hxx" @@ -561,6 +562,7 @@ AudioOutput::Task() FormatThreadName("output:%s", name); SetThreadRealtime(); + SetThreadTimerSlackUS(100); mutex.lock(); diff --git a/src/thread/Slack.hxx b/src/thread/Slack.hxx new file mode 100644 index 000000000..66b2254a4 --- /dev/null +++ b/src/thread/Slack.hxx @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_THREAD_SLACK_HXX +#define MPD_THREAD_SLACK_HXX + +#ifdef HAVE_PRCTL +#include +#endif + +/** + * Set the current thread's timer slack to the specified number of + * nanoseconds (requires Linux 2.6.28). This allows the kernel to + * merge multiple wakeups, which is a trick to save energy. + */ +static inline void +SetThreadTimerSlackNS(unsigned long slack_ns) +{ +#if defined(HAVE_PRCTL) && defined(PR_SET_TIMERSLACK) + prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0); +#else + (void)slack_ns; +#endif +} + +static inline void +SetThreadTimerSlackUS(unsigned long slack_us) +{ + SetThreadTimerSlackNS(slack_us * 1000ul); +} + +static inline void +SetThreadTimerSlackMS(unsigned long slack_ms) +{ + SetThreadTimerSlackNS(slack_ms * 1000000ul); +} + +#endif