diff options
author | Tim Mayberry <mojofunk@gmail.com> | 2015-09-14 13:26:07 +1000 |
---|---|---|
committer | Tim Mayberry <mojofunk@gmail.com> | 2015-09-16 11:22:16 +1000 |
commit | 091c4ed3a718c22ebcf205abdb3f2e2bad786459 (patch) | |
tree | 228e85ee18f7707e1696980c3b9c29026d556ade /libs/pbd/windows_mmcss.cc | |
parent | 76a0c823caab700725fe8318d1a4c4e33f067847 (diff) |
Move Windows MMCSS related utility functions into libpbd
Diffstat (limited to 'libs/pbd/windows_mmcss.cc')
-rw-r--r-- | libs/pbd/windows_mmcss.cc | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/libs/pbd/windows_mmcss.cc b/libs/pbd/windows_mmcss.cc new file mode 100644 index 0000000000..92fdea2fdc --- /dev/null +++ b/libs/pbd/windows_mmcss.cc @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com> + * + * 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 "pbd/windows_mmcss.h" + +#include "pbd/compose.h" +#include "pbd/debug.h" + +#define DEBUG_THREADS(msg) DEBUG_TRACE (PBD::DEBUG::Threads, msg); + +typedef HANDLE (WINAPI* AvSetMmThreadCharacteristicsA_t)(LPCSTR TaskName, + LPDWORD TaskIndex); + +typedef BOOL (WINAPI* AvRevertMmThreadCharacteristics_t)(HANDLE AvrtHandle); + +typedef BOOL (WINAPI* AvSetMmThreadPriority_t)( + HANDLE AvrtHandle, PBD::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 PBD { + +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)); + DWORD error = GetLastError(); + + switch (error) { + case ERROR_INVALID_TASK_INDEX: + DEBUG_THREADS("MMCSS: Invalid Task Index\n"); + break; + case ERROR_INVALID_TASK_NAME: + DEBUG_THREADS("MMCSS: Invalid Task Name\n"); + break; + case ERROR_PRIVILEGE_NOT_HELD: + DEBUG_THREADS("MMCSS: Privilege not held\n"); + break; + default: + DEBUG_THREADS("MMCSS: Unknown error setting thread characteristics\n"); + break; + } + 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 + +} // namespace PBD |