ReactOS 0.4.16-dev-311-g9382aa2
thread.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mmebuddy/thread.c
5 *
6 * PURPOSE: Multimedia thread management
7 *
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9*/
10
11#include "precomp.h"
12
15 IN LPVOID lpParameter OPTIONAL)
16{
17 PSOUND_THREAD Thread = (PSOUND_THREAD) lpParameter;
18
19 SND_TRACE(L"SoundThread running :)\n");
20
21 /* Callers will wait for us to be ready */
22 Thread->Running = TRUE;
23 SetEvent(Thread->Events.Ready);
24
25 while ( Thread->Running )
26 {
27 DWORD WaitResult;
28
29 /* Wait for a request, or an I/O completion */
30 WaitResult = WaitForSingleObjectEx(Thread->Events.Request, INFINITE, TRUE);
31 SND_TRACE(L"SoundThread - Came out of waiting\n");
32
33 if ( WaitResult == WAIT_OBJECT_0 )
34 {
35 SND_TRACE(L"SoundThread - Processing request\n");
36
37 if ( Thread->Request.Handler )
38 {
39 Thread->Request.Result = Thread->Request.Handler(Thread->Request.SoundDeviceInstance,
40 Thread->Request.Parameter);
41 }
42 else
43 {
44 Thread->Request.Result = MMSYSERR_ERROR;
45 }
46
47 /* Announce completion of the request */
48 SetEvent(Thread->Events.Done);
49 /* Accept new requests */
50 SetEvent(Thread->Events.Ready);
51 }
52 else if ( WaitResult == WAIT_IO_COMPLETION )
53 {
54 SND_TRACE(L"SoundThread - Processing IO completion\n");
55 /* TODO? What do we do here? Stream stuff? */
56 }
57 else
58 {
59 /* This should not happen! */
61 }
62
63 }
64
65 SND_TRACE(L"Sound thread terminated\n");
66
67 return 0;
68}
69
72 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
75{
77
80
81 Thread = SoundDeviceInstance->Thread;
82
83 SND_TRACE(L"Waiting for READY event\n");
84 WaitForSingleObject(Thread->Events.Ready, INFINITE);
85
86 Thread->Request.Result = MMSYSERR_NOTSUPPORTED;
87 Thread->Request.Handler = RequestHandler;
88 Thread->Request.SoundDeviceInstance = SoundDeviceInstance;
89 Thread->Request.Parameter = Parameter;
90
91 /* Notify the thread it has work to do */
92 SND_TRACE(L"Setting REQUEST event\n");
93 SetEvent(Thread->Events.Request);
94
95 /* Wait for the work to be done */
96 SND_TRACE(L"Waiting for DONE event\n");
97 WaitForSingleObject(Thread->Events.Done, INFINITE);
98
99 return Thread->Request.Result;
100}
101
102
107{
109
110 SND_TRACE(L"Sound thread terminator routine called\n");
112
113 Thread->Running = FALSE;
114
115 return MMSYSERR_NOERROR;
116}
117
121{
122 DWORD WaitResult;
123
125
126 SND_TRACE(L"Waiting for READY event\n");
127 WaitForSingleObject(Thread->Events.Ready, INFINITE);
128
129 Thread->Request.Result = MMSYSERR_NOTSUPPORTED;
130 Thread->Request.Handler = SoundThreadTerminator;
131 Thread->Request.SoundDeviceInstance = NULL;
132 Thread->Request.Parameter = (PVOID) Thread;
133
134 /* Notify the thread it has work to do */
135 SND_TRACE(L"Setting REQUEST event\n");
136 SetEvent(Thread->Events.Request);
137
138 /* Wait for the work to be done */
139 SND_TRACE(L"Waiting for DONE event\n");
140 WaitForSingleObject(Thread->Events.Done, INFINITE);
141
142 /* Wait for the thread to actually end */
143 WaitResult = WaitForSingleObject(Thread->Handle, INFINITE);
144 SND_ASSERT( WaitResult == WAIT_OBJECT_0 );
145
146 return MMSYSERR_NOERROR;
147}
148
149
152 OUT HANDLE* ReadyEvent,
153 OUT HANDLE* RequestEvent,
154 OUT HANDLE* DoneEvent)
155{
156 BOOL ok;
157
158 VALIDATE_MMSYS_PARAMETER( ReadyEvent );
159 VALIDATE_MMSYS_PARAMETER( RequestEvent );
160 VALIDATE_MMSYS_PARAMETER( DoneEvent );
161
162 SND_TRACE(L"Creating thread events\n");
163
164 /* Initialise these so we can identify them upon failure */
165 *ReadyEvent = *RequestEvent = *DoneEvent = INVALID_HANDLE_VALUE;
166
167 ok = (*ReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE;
168 ok &= (*RequestEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE;
169 ok &= (*DoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE;
170
171 /* If something went wrong, clean up */
172 if ( ! ok )
173 {
174 if ( *ReadyEvent != INVALID_HANDLE_VALUE )
175 CloseHandle(*ReadyEvent);
176
177 if ( *RequestEvent != INVALID_HANDLE_VALUE )
178 CloseHandle(*RequestEvent);
179
180 if ( *DoneEvent != INVALID_HANDLE_VALUE )
181 CloseHandle(*DoneEvent);
182
183 return MMSYSERR_NOMEM;
184 }
185
186 return MMSYSERR_NOERROR;
187}
188
191 IN HANDLE ReadyEvent,
192 IN HANDLE RequestEvent,
193 IN HANDLE DoneEvent)
194{
198
199 SND_TRACE(L"Destroying thread events\n");
200
201 CloseHandle(ReadyEvent);
202 CloseHandle(RequestEvent);
203 CloseHandle(DoneEvent);
204
205 return MMSYSERR_NOERROR;
206}
207
211{
213 PSOUND_THREAD NewThread;
214
216
217 NewThread = AllocateStruct(SOUND_THREAD);
218 if ( ! NewThread )
219 return MMSYSERR_NOMEM;
220
221 /* Prepare the events we'll be using to sync. everything */
222 Result = CreateSoundThreadEvents(&NewThread->Events.Ready,
223 &NewThread->Events.Request,
224 &NewThread->Events.Done);
225
226 if ( ! MMSUCCESS(Result) )
227 {
228 FreeMemory(NewThread);
230 }
231
232 SND_TRACE(L"Creating a sound thread\n");
233 NewThread->Handle = CreateThread(NULL,
234 0,
236 (LPVOID) NewThread,
238 NULL);
239
240 /* Something went wrong, bail out! */
241 if ( NewThread->Handle == INVALID_HANDLE_VALUE )
242 {
243 SND_ERR(L"Sound thread creation failed!\n");
244 DestroySoundThreadEvents(NewThread->Events.Ready,
245 NewThread->Events.Request,
246 NewThread->Events.Done);
247
248 FreeMemory(NewThread);
249
251 }
252
253 /* Wake the thread up */
254 if ( ResumeThread(NewThread->Handle) == -1 )
255 {
256 SND_ERR(L"Failed to resume thread!\n");
257 CloseHandle(NewThread->Handle);
258 DestroySoundThreadEvents(NewThread->Events.Ready,
259 NewThread->Events.Request,
260 NewThread->Events.Done);
261
262 FreeMemory(NewThread);
264 }
265
266 /* If all is well we can now give the thread to the caller */
267 *Thread = NewThread;
268 return MMSYSERR_NOERROR;
269}
270
274{
277
278 SND_TRACE(L"Terminating sound thread\n");
279
280 /* Tell the thread to terminate itself */
282
283 SND_TRACE(L"Sound thread terminated, performing cleanup of thread resources\n");
284
285 CloseHandle(Thread->Handle); /* Is this needed? */
287
288 DestroySoundThreadEvents(Thread->Events.Ready,
289 Thread->Events.Request,
290 Thread->Events.Done);
291
292 /* Wipe and free the memory used for the thread */
295
296 SND_TRACE(L"Finished thread cleanup\n");
297
298 return MMSYSERR_NOERROR;
299}
300
#define ok(value,...)
Definition: atltest.h:57
static VOID FreeMemory(PCREATE_DATA Data)
Definition: create.c:134
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define VALIDATE_MMSYS_PARAMETER(parameter_condition)
Definition: mmebuddy.h:71
#define AllocateStruct(thing)
Definition: mmebuddy.h:27
struct _SOUND_THREAD * PSOUND_THREAD
MMRESULT TranslateInternalMmResult(IN MMRESULT Result)
Definition: utility.c:132
MMRESULT(* SOUND_THREAD_REQUEST_HANDLER)(IN struct _SOUND_DEVICE_INSTANCE *SoundDeviceInstance, IN PVOID Parameter)
Definition: mmebuddy.h:243
#define MMSUCCESS(result)
Definition: mmebuddy.h:80
BOOLEAN IsValidSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
MMRESULT Win32ErrorToMmResult(IN UINT ErrorCode)
Definition: utility.c:87
#define SND_TRACE(...)
#define SND_ERR(...)
#define SND_ASSERT(condition)
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
UINT MMRESULT
Definition: mmsystem.h:962
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MMSYSERR_ERROR
Definition: mmsystem.h:97
static PVOID
Definition: thread.c:78
#define L(x)
Definition: ntvdm.h:50
DWORD WINAPI SoundThreadMain(IN LPVOID lpParameter OPTIONAL)
Definition: thread.c:14
MMRESULT DestroySoundThreadEvents(IN HANDLE ReadyEvent, IN HANDLE RequestEvent, IN HANDLE DoneEvent)
Definition: thread.c:190
MMRESULT CreateSoundThread(OUT PSOUND_THREAD *Thread)
Definition: thread.c:209
MMRESULT CreateSoundThreadEvents(OUT HANDLE *ReadyEvent, OUT HANDLE *RequestEvent, OUT HANDLE *DoneEvent)
Definition: thread.c:151
MMRESULT SoundThreadTerminator(IN PSOUND_DEVICE_INSTANCE Instance, IN PVOID Parameter)
Definition: thread.c:104
MMRESULT CallSoundThread(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN SOUND_THREAD_REQUEST_HANDLER RequestHandler, IN PVOID Parameter OPTIONAL)
Definition: thread.c:71
MMRESULT DestroySoundThread(IN PSOUND_THREAD Thread)
Definition: thread.c:272
MMRESULT TerminateSoundThread(IN PSOUND_THREAD Thread)
Definition: thread.c:119
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
struct _SOUND_THREAD::@3472 Events
HANDLE Handle
Definition: mmebuddy.h:249
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
DWORD WINAPI WaitForSingleObjectEx(IN HANDLE hHandle, IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:94
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_INSTANCE_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_opt_ WDFWMIINSTANCE * Instance
Definition: wdfwmi.h:481
#define ZeroMemory
Definition: winbase.h:1737
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_IO_COMPLETION
Definition: winbase.h:437
#define CreateEvent
Definition: winbase.h:3773
#define CREATE_SUSPENDED
Definition: winbase.h:181
#define WAIT_OBJECT_0
Definition: winbase.h:432
#define WINAPI
Definition: msvc.h:6
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336