ReactOS  0.4.13-dev-73-gcfe54aa
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 
16 {
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 
103 MMRESULT
107 {
109 
110  SND_TRACE(L"Sound thread terminator routine called\n");
111  SND_ASSERT( Thread );
112 
113  Thread->Running = FALSE;
114 
115  return MMSYSERR_NOERROR;
116 }
117 
118 MMRESULT
121 {
122  DWORD WaitResult;
123 
124  SND_ASSERT( Thread );
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 
150 MMRESULT
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 
189 MMRESULT
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 
208 MMRESULT
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 
271 MMRESULT
274 {
276  SND_ASSERT( Thread->Handle != INVALID_HANDLE_VALUE );
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? */
286  Thread->Handle = INVALID_HANDLE_VALUE;
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 */
293  ZeroMemory(Thread, sizeof(SOUND_THREAD));
295 
296  SND_TRACE(L"Finished thread cleanup\n");
297 
298  return MMSYSERR_NOERROR;
299 }
300 
#define CreateEvent
Definition: winbase.h:3562
MMRESULT CreateSoundThread(OUT PSOUND_THREAD *Thread)
Definition: thread.c:209
DWORD WINAPI WaitForSingleObjectEx(IN HANDLE hHandle, IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:94
#define IN
Definition: typedefs.h:38
static VOID FreeMemory(PCREATE_DATA Data)
Definition: create.c:134
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
MMRESULT(* SOUND_THREAD_REQUEST_HANDLER)(IN struct _SOUND_DEVICE_INSTANCE *SoundDeviceInstance, IN PVOID Parameter)
Definition: mmebuddy.h:231
struct _SOUND_THREAD::@3305 Events
MMRESULT Win32ErrorToMmResult(IN UINT ErrorCode)
Definition: utility.c:87
MMRESULT CallSoundThread(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN SOUND_THREAD_REQUEST_HANDLER RequestHandler, IN PVOID Parameter OPTIONAL)
Definition: thread.c:71
#define MMSUCCESS(result)
Definition: mmebuddy.h:80
MMRESULT TranslateInternalMmResult(IN MMRESULT Result)
Definition: utility.c:132
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
UINT MMRESULT
Definition: mmsystem.h:962
static PVOID
Definition: thread.c:83
_In_ PVOID Parameter
Definition: ldrtypes.h:240
#define VALIDATE_MMSYS_PARAMETER(parameter_condition)
Definition: mmebuddy.h:71
MMRESULT DestroySoundThread(IN PSOUND_THREAD Thread)
Definition: thread.c:272
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
#define CREATE_SUSPENDED
Definition: winbase.h:178
MMRESULT SoundThreadTerminator(IN PSOUND_DEVICE_INSTANCE Instance, IN PVOID Parameter)
Definition: thread.c:104
DWORD WINAPI SoundThreadMain(IN LPVOID lpParameter OPTIONAL)
Definition: thread.c:14
unsigned int BOOL
Definition: ntddk_ex.h:94
MMRESULT DestroySoundThreadEvents(IN HANDLE ReadyEvent, IN HANDLE RequestEvent, IN HANDLE DoneEvent)
Definition: thread.c:190
#define ok(value,...)
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:112
smooth NULL
Definition: ftsmooth.c:416
#define SND_ASSERT(condition)
_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:426
#define WAIT_IO_COMPLETION
Definition: winbase.h:392
BOOLEAN IsValidSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
struct _SOUND_THREAD * PSOUND_THREAD
#define WAIT_OBJECT_0
Definition: winbase.h:387
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MMSYSERR_ERROR
Definition: mmsystem.h:97
#define AllocateStruct(thing)
Definition: mmebuddy.h:27
#define SND_ERR(...)
MMRESULT TerminateSoundThread(IN PSOUND_THREAD Thread)
Definition: thread.c:119
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
static const WCHAR L[]
Definition: oid.c:1250
LPVOID lpParameter
Definition: kernel32.h:234
HANDLE Handle
Definition: mmebuddy.h:237
MMRESULT CreateSoundThreadEvents(OUT HANDLE *ReadyEvent, OUT HANDLE *RequestEvent, OUT HANDLE *DoneEvent)
Definition: thread.c:151
IN PVOID Instance
Definition: pci.h:359
#define OUT
Definition: typedefs.h:39
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:529
#define INFINITE
Definition: serial.h:102
#define SND_TRACE(...)
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68