suppress realloc-poll debug messages in optimized builds
[ardour.git] / libs / pbd / windows_mmcss.cc
1 /*
2  * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include "pbd/windows_mmcss.h"
20
21 #include "pbd/compose.h"
22 #include "pbd/debug.h"
23
24 #define DEBUG_THREADS(msg) DEBUG_TRACE (PBD::DEBUG::Threads, msg);
25
26 typedef HANDLE (WINAPI* AvSetMmThreadCharacteristicsA_t)(LPCSTR TaskName,
27                                                          LPDWORD TaskIndex);
28
29 typedef BOOL (WINAPI* AvRevertMmThreadCharacteristics_t)(HANDLE AvrtHandle);
30
31 typedef BOOL (WINAPI* AvSetMmThreadPriority_t)(
32     HANDLE AvrtHandle, PBD::MMCSS::AVRT_PRIORITY Priority);
33
34 static HMODULE avrt_dll = NULL;
35
36 static AvSetMmThreadCharacteristicsA_t AvSetMmThreadCharacteristicsA = NULL;
37 static AvRevertMmThreadCharacteristics_t AvRevertMmThreadCharacteristics = NULL;
38 static AvSetMmThreadPriority_t AvSetMmThreadPriority = NULL;
39
40 namespace PBD {
41
42 namespace MMCSS {
43
44 bool
45 initialize ()
46 {
47         if (avrt_dll != NULL) return true;
48
49         avrt_dll = LoadLibraryA ("avrt.dll");
50
51         if (avrt_dll == NULL) {
52                 DEBUG_THREADS ("Unable to load avrt.dll\n");
53                 return false;
54         }
55         bool unload_dll = false;
56
57         AvSetMmThreadCharacteristicsA =
58             (AvSetMmThreadCharacteristicsA_t)GetProcAddress (
59                 avrt_dll, "AvSetMmThreadCharacteristicsA");
60
61         if (AvSetMmThreadCharacteristicsA == NULL) {
62                 DEBUG_THREADS ("Unable to resolve AvSetMmThreadCharacteristicsA\n");
63                 unload_dll = true;
64         }
65
66         AvRevertMmThreadCharacteristics =
67             (AvRevertMmThreadCharacteristics_t)GetProcAddress (
68                 avrt_dll, "AvRevertMmThreadCharacteristics");
69
70         if (AvRevertMmThreadCharacteristics == NULL) {
71                 DEBUG_THREADS ("Unable to resolve AvRevertMmThreadCharacteristics\n");
72                 unload_dll = true;
73         }
74
75         AvSetMmThreadPriority = (AvSetMmThreadPriority_t)GetProcAddress (
76             avrt_dll, "AvSetMmThreadPriority");
77
78         if (AvSetMmThreadPriority == NULL) {
79                 DEBUG_THREADS ("Unable to resolve AvSetMmThreadPriority\n");
80                 unload_dll = true;
81         }
82
83         if (unload_dll) {
84                 DEBUG_THREADS (
85                     "MMCSS Unable to resolve necessary symbols, unloading avrt.dll\n");
86                 deinitialize ();
87         }
88
89         return true;
90 }
91
92 bool
93 deinitialize ()
94 {
95         if (avrt_dll == NULL) return true;
96
97         if (FreeLibrary (avrt_dll) == 0) {
98                 DEBUG_THREADS ("Unable to unload avrt.dll\n");
99                 return false;
100         }
101
102         avrt_dll = NULL;
103
104         AvSetMmThreadCharacteristicsA = NULL;
105         AvRevertMmThreadCharacteristics = NULL;
106         AvSetMmThreadPriority = NULL;
107
108         return true;
109 }
110
111 bool
112 set_thread_characteristics (const std::string& task_name, HANDLE* task_handle)
113 {
114         if (AvSetMmThreadCharacteristicsA == NULL) return false;
115
116         DWORD task_index_dummy = 0;
117
118         *task_handle = AvSetMmThreadCharacteristicsA(task_name.c_str(), &task_index_dummy);
119
120         if (*task_handle == 0) {
121                 DEBUG_THREADS (string_compose ("Failed to set Thread Characteristics to %1\n",
122                                                task_name));
123                 DWORD error = GetLastError();
124
125                 switch (error) {
126                 case ERROR_INVALID_TASK_INDEX:
127                         DEBUG_THREADS("MMCSS: Invalid Task Index\n");
128                         break;
129                 case ERROR_INVALID_TASK_NAME:
130                         DEBUG_THREADS("MMCSS: Invalid Task Name\n");
131                         break;
132                 case ERROR_PRIVILEGE_NOT_HELD:
133                         DEBUG_THREADS("MMCSS: Privilege not held\n");
134                         break;
135                 default:
136                         DEBUG_THREADS("MMCSS: Unknown error setting thread characteristics\n");
137                         break;
138                 }
139                 return false;
140         }
141
142         DEBUG_THREADS (
143             string_compose ("Set thread characteristics to %1\n", task_name));
144
145         return true;
146 }
147
148 bool
149 revert_thread_characteristics (HANDLE task_handle)
150 {
151         if (AvRevertMmThreadCharacteristics == NULL) return false;
152
153         if (AvRevertMmThreadCharacteristics (task_handle) == 0) {
154                 DEBUG_THREADS ("Failed to set revert thread characteristics\n");
155                 return false;
156         }
157
158         DEBUG_THREADS ("Reverted thread characteristics\n");
159
160         return true;
161 }
162
163 bool
164 set_thread_priority (HANDLE task_handle, AVRT_PRIORITY priority)
165 {
166         if (AvSetMmThreadPriority == NULL) return false;
167
168         if (AvSetMmThreadPriority (task_handle, priority) == 0) {
169                 DEBUG_THREADS (
170                     string_compose ("Failed to set thread priority %1\n", priority));
171                 return false;
172         }
173
174         DEBUG_THREADS (string_compose ("Set thread priority to %1\n", priority));
175
176         return true;
177 }
178
179 } // namespace MMCSS
180
181 } // namespace PBD