From: Tim Mayberry Date: Wed, 29 Jul 2015 22:40:41 +0000 (+1000) Subject: Add MMCSS related code for raising thread priority on Windows X-Git-Tag: 4.2~153 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=e9d00f5cfbc774004d121dc7eae69ff22419cb49;p=ardour.git Add MMCSS related code for raising thread priority on Windows --- diff --git a/libs/backends/portaudio/mmcss.cc b/libs/backends/portaudio/mmcss.cc new file mode 100644 index 0000000000..49551af339 --- /dev/null +++ b/libs/backends/portaudio/mmcss.cc @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2015 Tim Mayberry + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "mmcss.h" + +#include "pbd/compose.h" + +#include "debug.h" + +typedef HANDLE (WINAPI* AvSetMmThreadCharacteristicsA_t)(LPCSTR TaskName, + LPDWORD TaskIndex); + +typedef WINBOOL (WINAPI* AvRevertMmThreadCharacteristics_t)(HANDLE AvrtHandle); + +typedef WINBOOL (WINAPI* AvSetMmThreadPriority_t)( + HANDLE AvrtHandle, mmcss::AVRT_PRIORITY Priority); + +static HMODULE avrt_dll = NULL; + +static AvSetMmThreadCharacteristicsA_t AvSetMmThreadCharacteristicsA = NULL; +static AvRevertMmThreadCharacteristics_t AvRevertMmThreadCharacteristics = NULL; +static AvSetMmThreadPriority_t AvSetMmThreadPriority = NULL; + + +namespace mmcss { + +bool +initialize () +{ + if (avrt_dll != NULL) return true; + + avrt_dll = LoadLibraryA ("avrt.dll"); + + if (avrt_dll == NULL) { + DEBUG_THREADS ("Unable to load avrt.dll\n"); + return false; + } + bool unload_dll = false; + + AvSetMmThreadCharacteristicsA = + (AvSetMmThreadCharacteristicsA_t)GetProcAddress ( + avrt_dll, "AvSetMmThreadCharacteristicsA"); + + if (AvSetMmThreadCharacteristicsA == NULL) { + DEBUG_THREADS ("Unable to resolve AvSetMmThreadCharacteristicsA\n"); + unload_dll = true; + } + + AvRevertMmThreadCharacteristics = + (AvRevertMmThreadCharacteristics_t)GetProcAddress ( + avrt_dll, "AvRevertMmThreadCharacteristics"); + + if (AvRevertMmThreadCharacteristics == NULL) { + DEBUG_THREADS ("Unable to resolve AvRevertMmThreadCharacteristics\n"); + unload_dll = true; + } + + AvSetMmThreadPriority = (AvSetMmThreadPriority_t)GetProcAddress ( + avrt_dll, "AvSetMmThreadPriority"); + + if (AvSetMmThreadPriority == NULL) { + DEBUG_THREADS ("Unable to resolve AvSetMmThreadPriority\n"); + unload_dll = true; + } + + if (unload_dll) { + DEBUG_THREADS ( + "MMCSS Unable to resolve necessary symbols, unloading avrt.dll\n"); + deinitialize (); + } + + return true; +} + +bool +deinitialize () +{ + if (avrt_dll == NULL) return true; + + if (FreeLibrary (avrt_dll) == 0) { + DEBUG_THREADS ("Unable to unload avrt.dll\n"); + return false; + } + + avrt_dll = NULL; + + AvSetMmThreadCharacteristicsA = NULL; + AvRevertMmThreadCharacteristics = NULL; + AvSetMmThreadPriority = NULL; + + return true; +} + +bool +set_thread_characteristics (const std::string& task_name, HANDLE* task_handle) +{ + if (AvSetMmThreadCharacteristicsA == NULL) return false; + + DWORD task_index_dummy = 0; + + *task_handle = AvSetMmThreadCharacteristicsA(task_name.c_str(), &task_index_dummy); + + if (*task_handle == 0) { + DEBUG_THREADS (string_compose ("Failed to set Thread Characteristics to %1\n", + task_name)); + return false; + } + + DEBUG_THREADS ( + string_compose ("Set thread characteristics to %1\n", task_name)); + + return true; +} + +bool +revert_thread_characteristics (HANDLE task_handle) +{ + if (AvRevertMmThreadCharacteristics == NULL) return false; + + if (AvRevertMmThreadCharacteristics (task_handle) == 0) { + DEBUG_THREADS ("Failed to set revert thread characteristics\n"); + return false; + } + + DEBUG_THREADS ("Reverted thread characteristics\n"); + + return true; +} + +bool +set_thread_priority (HANDLE task_handle, AVRT_PRIORITY priority) +{ + if (AvSetMmThreadPriority == NULL) return false; + + if (AvSetMmThreadPriority (task_handle, priority) == 0) { + DEBUG_THREADS ( + string_compose ("Failed to set thread priority %1\n", priority)); + return false; + } + + DEBUG_THREADS (string_compose ("Set thread priority to %1\n", priority)); + + return true; +} + +} // namespace mmcss diff --git a/libs/backends/portaudio/mmcss.h b/libs/backends/portaudio/mmcss.h new file mode 100644 index 0000000000..deb9a417d3 --- /dev/null +++ b/libs/backends/portaudio/mmcss.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Tim Mayberry + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef MMCSS_H +#define MMCSS_H + +#include + +#include + +namespace mmcss { + +enum AVRT_PRIORITY { + AVRT_PRIORITY_VERYLOW = -2, + AVRT_PRIORITY_LOW, + AVRT_PRIORITY_NORMAL, + AVRT_PRIORITY_HIGH, + AVRT_PRIORITY_CRITICAL +}; + +bool initialize (); + +bool deinitialize (); + +bool set_thread_characteristics (const std::string& task_name, HANDLE *task_handle); + +bool revert_thread_characteristics (HANDLE task_handle); + +bool set_thread_priority (HANDLE, AVRT_PRIORITY); + + +} // namespace mmcss + +#endif // MMCSS_H diff --git a/libs/backends/portaudio/wscript b/libs/backends/portaudio/wscript index 8bcfa5fa46..fcc0041a99 100644 --- a/libs/backends/portaudio/wscript +++ b/libs/backends/portaudio/wscript @@ -26,7 +26,8 @@ def build(bld): 'winmmemidi_input_device.cc', 'winmmemidi_output_device.cc', 'win_utils.cc', - 'midi_util.cc' + 'midi_util.cc', + 'mmcss.cc' ] obj.includes = ['.'] obj.name = 'portaudio_backend'