Skip to content

Commit 4b4f064

Browse files
committed
improve thread safety using signals/mutexes
1 parent 1aabbc8 commit 4b4f064

20 files changed

+677
-76
lines changed

audio/AudDrv_ALSA.c

+32-9
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414

1515
#include "AudioStream.h"
1616
#include "../utils/OSThread.h"
17+
#include "../utils/OSSignal.h"
18+
#include "../utils/OSMutex.h"
1719

1820

19-
#pragma pack(1)
2021
typedef struct
2122
{
2223
UINT16 wFormatTag;
@@ -26,7 +27,6 @@ typedef struct
2627
UINT16 nBlockAlign;
2728
UINT16 wBitsPerSample;
2829
} WAVEFORMAT; // from MSDN Help
29-
#pragma pack()
3030

3131
#define WAVE_FORMAT_PCM 0x0001
3232

@@ -35,7 +35,6 @@ typedef struct _alsa_driver
3535
{
3636
void* audDrvPtr;
3737
volatile UINT8 devState; // 0 - not running, 1 - running, 2 - terminating
38-
UINT16 dummy; // [for alignment purposes]
3938

4039
WAVEFORMAT waveFmt;
4140
UINT32 bufSmpls;
@@ -44,6 +43,8 @@ typedef struct _alsa_driver
4443
UINT8* bufSpace;
4544

4645
OS_THREAD* hThread;
46+
OS_SIGNAL* hSignal;
47+
OS_MUTEX* hMutex;
4748
snd_pcm_t* hPCM;
4849
volatile UINT8 pauseThread;
4950
UINT8 canPause;
@@ -165,15 +166,26 @@ AUDIO_OPTS* ALSA_GetDefaultOpts(void)
165166
UINT8 ALSA_Create(void** retDrvObj)
166167
{
167168
DRV_ALSA* drv;
169+
UINT8 retVal8;
168170

169171
drv = (DRV_ALSA*)malloc(sizeof(DRV_ALSA));
170172
drv->devState = 0;
171173
drv->hPCM = NULL;
172174
drv->hThread = NULL;
175+
drv->hSignal = NULL;
176+
drv->hMutex = NULL;
173177
drv->userParam = NULL;
174178
drv->FillBuffer = NULL;
175179

176180
activeDrivers ++;
181+
retVal8 = OSSignal_Init(&drv->hSignal, 0);
182+
retVal8 |= OSMutex_Init(&drv->hMutex, 0);
183+
if (retVal8)
184+
{
185+
ALSA_Destroy(drv);
186+
*retDrvObj = NULL;
187+
return AERR_API_ERR;
188+
}
177189
*retDrvObj = drv;
178190

179191
return AERR_OK;
@@ -190,6 +202,10 @@ UINT8 ALSA_Destroy(void* drvObj)
190202
OSThread_Cancel(drv->hThread);
191203
OSThread_Deinit(drv->hThread);
192204
}
205+
if (drv->hSignal != NULL)
206+
OSSignal_Deinit(drv->hSignal);
207+
if (drv->hMutex != NULL)
208+
OSMutex_Deinit(drv->hMutex);
193209

194210
free(drv);
195211
activeDrivers --;
@@ -281,7 +297,7 @@ UINT8 ALSA_Start(void* drvObj, UINT32 deviceID, AUDIO_OPTS* options, void* audDr
281297
return 0xCF;
282298
}
283299

284-
drv->pauseThread = 1;
300+
OSSignal_Reset(drv->hSignal);
285301
retVal8 = OSThread_Init(&drv->hThread, &AlsaThread, drv);
286302
if (retVal8)
287303
{
@@ -294,6 +310,7 @@ UINT8 ALSA_Start(void* drvObj, UINT32 deviceID, AUDIO_OPTS* options, void* audDr
294310

295311
drv->devState = 1;
296312
drv->pauseThread = 0;
313+
OSSignal_Signal(drv->hSignal);
297314

298315
return AERR_OK;
299316
}
@@ -368,8 +385,10 @@ UINT8 ALSA_SetCallback(void* drvObj, AUDFUNC_FILLBUF FillBufCallback, void* user
368385
{
369386
DRV_ALSA* drv = (DRV_ALSA*)drvObj;
370387

388+
OSMutex_Lock(drv->hMutex);
371389
drv->userParam = userParam;
372390
drv->FillBuffer = FillBufCallback;
391+
OSMutex_Unlock(drv->hMutex);
373392

374393
return AERR_OK;
375394
}
@@ -396,12 +415,15 @@ UINT8 ALSA_IsBusy(void* drvObj)
396415
UINT8 ALSA_WriteData(void* drvObj, UINT32 dataSize, void* data)
397416
{
398417
DRV_ALSA* drv = (DRV_ALSA*)drvObj;
399-
int retVal;
418+
UINT8 retVal;
400419

401420
if (dataSize > drv->bufSize)
402421
return AERR_TOO_MUCH_DATA;
403422

404-
return WriteBuffer(drv, dataSize, data);
423+
OSMutex_Lock(drv->hMutex);
424+
retVal = WriteBuffer(drv, dataSize, data);
425+
OSMutex_Unlock(drv->hMutex);
426+
return retVal;
405427
}
406428

407429

@@ -420,16 +442,16 @@ UINT32 ALSA_GetLatency(void* drvObj)
420442
static void AlsaThread(void* Arg)
421443
{
422444
DRV_ALSA* drv = (DRV_ALSA*)Arg;
423-
UINT32 curBuf;
424445
UINT32 didBuffers; // number of processed buffers
425446
UINT32 bufBytes;
426447
int retVal;
427448

428-
while(drv->pauseThread)
429-
Sleep(1);
449+
OSSignal_Wait(drv->hSignal); // wait until the initialization is done
450+
430451
while(drv->devState == 1)
431452
{
432453
didBuffers = 0;
454+
OSMutex_Lock(drv->hMutex);
433455
if (! drv->pauseThread && drv->FillBuffer != NULL)
434456
{
435457
retVal = snd_pcm_wait(drv->hPCM, 5);
@@ -441,6 +463,7 @@ static void AlsaThread(void* Arg)
441463
}
442464
didBuffers ++; // not 100% correct, but has the desired effect
443465
}
466+
OSMutex_Unlock(drv->hMutex);
444467
if (! didBuffers)
445468
Sleep(1);
446469

audio/AudDrv_DSound.cpp

+27-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "AudioStream.h"
1717
#include "../utils/OSThread.h"
18+
#include "../utils/OSSignal.h"
19+
#include "../utils/OSMutex.h"
1820

1921
#define EXT_C extern "C"
2022

@@ -33,7 +35,7 @@ typedef struct _dsound_device
3335
typedef struct _directsound_driver
3436
{
3537
void* audDrvPtr;
36-
UINT8 devState; // 0 - not running, 1 - running, 2 - terminating
38+
volatile UINT8 devState; // 0 - not running, 1 - running, 2 - terminating
3739
UINT16 dummy; // [for alignment purposes]
3840

3941
WAVEFORMATEX waveFmt;
@@ -47,6 +49,8 @@ typedef struct _directsound_driver
4749
LPDIRECTSOUND dSndIntf;
4850
LPDIRECTSOUNDBUFFER dSndBuf;
4951
OS_THREAD* hThread;
52+
OS_SIGNAL* hSignal;
53+
OS_MUTEX* hMutex;
5054
void* userParam;
5155
AUDFUNC_FILLBUF FillBuffer;
5256

@@ -221,17 +225,28 @@ AUDIO_OPTS* DSound_GetDefaultOpts(void)
221225
UINT8 DSound_Create(void** retDrvObj)
222226
{
223227
DRV_DSND* drv;
228+
UINT8 retVal8;
224229

225230
drv = (DRV_DSND*)malloc(sizeof(DRV_DSND));
226231
drv->devState = 0;
227232
drv->hWnd = NULL;
228233
drv->dSndIntf = NULL;
229234
drv->dSndBuf = NULL;
230235
drv->hThread = NULL;
236+
drv->hSignal = NULL;
237+
drv->hMutex = NULL;
231238
drv->userParam = NULL;
232239
drv->FillBuffer = NULL;
233240

234241
activeDrivers ++;
242+
retVal8 = OSSignal_Init(&drv->hSignal, 0);
243+
retVal8 |= OSMutex_Init(&drv->hMutex, 0);
244+
if (retVal8)
245+
{
246+
DSound_Destroy(drv);
247+
*retDrvObj = NULL;
248+
return AERR_API_ERR;
249+
}
235250
*retDrvObj = drv;
236251

237252
return AERR_OK;
@@ -248,6 +263,10 @@ UINT8 DSound_Destroy(void* drvObj)
248263
OSThread_Cancel(drv->hThread);
249264
OSThread_Deinit(drv->hThread);
250265
}
266+
if (drv->hSignal != NULL)
267+
OSSignal_Deinit(drv->hSignal);
268+
if (drv->hMutex != NULL)
269+
OSMutex_Deinit(drv->hMutex);
251270

252271
free(drv);
253272
activeDrivers --;
@@ -329,6 +348,7 @@ UINT8 DSound_Start(void* drvObj, UINT32 deviceID, AUDIO_OPTS* options, void* aud
329348
if (retVal != DS_OK)
330349
return AERR_API_ERR;
331350

351+
OSSignal_Reset(drv->hSignal);
332352
retVal8 = OSThread_Init(&drv->hThread, &DirectSoundThread, drv);
333353
if (retVal8)
334354
return 0xC8; // CreateThread failed
@@ -350,6 +370,7 @@ UINT8 DSound_Start(void* drvObj, UINT32 deviceID, AUDIO_OPTS* options, void* aud
350370
retVal = drv->dSndBuf->Play(0, 0, DSBPLAY_LOOPING);
351371

352372
drv->devState = 1;
373+
OSSignal_Signal(drv->hSignal);
353374

354375
return AERR_OK;
355376
}
@@ -414,8 +435,10 @@ UINT8 DSound_SetCallback(void* drvObj, AUDFUNC_FILLBUF FillBufCallback, void* us
414435
{
415436
DRV_DSND* drv = (DRV_DSND*)drvObj;
416437

438+
OSMutex_Lock(drv->hMutex);
417439
drv->userParam = userParam;
418440
drv->FillBuffer = FillBufCallback;
441+
OSMutex_Unlock(drv->hMutex);
419442

420443
return AERR_OK;
421444
}
@@ -499,19 +522,20 @@ static void DirectSoundThread(void* Arg)
499522
UINT32 wrtBytes;
500523
UINT32 didBuffers; // number of processed buffers
501524

502-
while(drv->devState == 0)
503-
Sleep(1); // TODO: replace with mutex/signal
525+
OSSignal_Wait(drv->hSignal); // wait until the initialization is done
504526

505527
while(drv->devState == 1)
506528
{
507529
didBuffers = 0;
508530

531+
OSMutex_Lock(drv->hMutex);
509532
while(GetFreeBytes(drv) >= drv->bufSegSize && drv->FillBuffer != NULL)
510533
{
511534
wrtBytes = drv->FillBuffer(drv->audDrvPtr, drv->userParam, drv->bufSegSize, drv->bufSpace);
512535
WriteBuffer(drv, wrtBytes, drv->bufSpace);
513536
didBuffers ++;
514537
}
538+
OSMutex_Unlock(drv->hMutex);
515539
if (! didBuffers)
516540
Sleep(1);
517541

audio/AudDrv_OSS.c

+27-6
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919

2020
#include "AudioStream.h"
2121
#include "../utils/OSThread.h"
22+
#include "../utils/OSSignal.h"
23+
#include "../utils/OSMutex.h"
2224

2325

24-
#pragma pack(1)
2526
typedef struct
2627
{
2728
UINT16 wFormatTag;
@@ -31,7 +32,6 @@ typedef struct
3132
UINT16 nBlockAlign;
3233
UINT16 wBitsPerSample;
3334
} WAVEFORMAT; // from MSDN Help
34-
#pragma pack()
3535

3636
#define WAVE_FORMAT_PCM 0x0001
3737

@@ -47,7 +47,6 @@ typedef struct _oss_driver
4747
{
4848
void* audDrvPtr;
4949
volatile UINT8 devState; // 0 - not running, 1 - running, 2 - terminating
50-
UINT16 dummy; // [for alignment purposes]
5150

5251
WAVEFORMAT waveFmt;
5352
UINT32 bufSmpls;
@@ -59,6 +58,8 @@ typedef struct _oss_driver
5958
#ifdef ENABLE_OSS_THREAD
6059
OS_THREAD* hThread;
6160
#endif
61+
OS_SIGNAL* hSignal;
62+
OS_MUTEX* hMutex;
6263
int hFileDSP;
6364
volatile UINT8 pauseThread;
6465

@@ -179,17 +180,28 @@ AUDIO_OPTS* OSS_GetDefaultOpts(void)
179180
UINT8 OSS_Create(void** retDrvObj)
180181
{
181182
DRV_OSS* drv;
183+
UINT8 retVal8;
182184

183185
drv = (DRV_OSS*)malloc(sizeof(DRV_OSS));
184186
drv->devState = 0;
185187
drv->hFileDSP = 0;
186188
#ifdef ENABLE_OSS_THREAD
187189
drv->hThread = NULL;
188190
#endif
191+
drv->hSignal = NULL;
192+
drv->hMutex = NULL;
189193
drv->userParam = NULL;
190194
drv->FillBuffer = NULL;
191195

192196
activeDrivers ++;
197+
retVal8 = OSSignal_Init(&drv->hSignal, 0);
198+
retVal8 |= OSMutex_Init(&drv->hMutex, 0);
199+
if (retVal8)
200+
{
201+
OSS_Destroy(drv);
202+
*retDrvObj = NULL;
203+
return AERR_API_ERR;
204+
}
193205
*retDrvObj = drv;
194206

195207
return AERR_OK;
@@ -208,6 +220,10 @@ UINT8 OSS_Destroy(void* drvObj)
208220
OSThread_Deinit(drv->hThread);
209221
}
210222
#endif
223+
if (drv->hSignal != NULL)
224+
OSSignal_Deinit(drv->hSignal);
225+
if (drv->hMutex != NULL)
226+
OSMutex_Deinit(drv->hMutex);
211227

212228
free(drv);
213229
activeDrivers --;
@@ -308,7 +324,7 @@ UINT8 OSS_Start(void* drvObj, UINT32 deviceID, AUDIO_OPTS* options, void* audDrv
308324
if (retVal)
309325
printf("Error setting Sample Rate!\n");
310326

311-
drv->pauseThread = 1;
327+
OSSignal_Reset(drv->hSignal);
312328
#ifdef ENABLE_OSS_THREAD
313329
retVal8 = OSThread_Init(&drv->hThread, &OssThread, drv);
314330
if (retVal8)
@@ -323,6 +339,7 @@ UINT8 OSS_Start(void* drvObj, UINT32 deviceID, AUDIO_OPTS* options, void* audDrv
323339

324340
drv->devState = 1;
325341
drv->pauseThread = 0;
342+
OSSignal_Signal(drv->hSignal);
326343

327344
return AERR_OK;
328345
}
@@ -381,8 +398,10 @@ UINT8 OSS_SetCallback(void* drvObj, AUDFUNC_FILLBUF FillBufCallback, void* userP
381398
DRV_OSS* drv = (DRV_OSS*)drvObj;
382399

383400
#ifdef ENABLE_OSS_THREAD
401+
OSMutex_Lock(drv->hMutex);
384402
drv->userParam = userParam;
385403
drv->FillBuffer = FillBufCallback;
404+
OSMutex_Unlock(drv->hMutex);
386405

387406
return AERR_OK;
388407
#else
@@ -443,17 +462,19 @@ static void OssThread(void* Arg)
443462
UINT32 bufBytes;
444463
ssize_t wrtBytes;
445464

446-
while(drv->pauseThread)
447-
Sleep(1);
465+
OSSignal_Wait(drv->hSignal); // wait until the initialization is done
466+
448467
while(drv->devState == 1)
449468
{
450469
didBuffers = 0;
470+
OSMutex_Lock(drv->hMutex);
451471
if (! drv->pauseThread && drv->FillBuffer != NULL)
452472
{
453473
bufBytes = drv->FillBuffer(drv->audDrvPtr, drv->userParam, drv->bufSize, drv->bufSpace);
454474
wrtBytes = write(drv->hFileDSP, drv->bufSpace, bufBytes);
455475
didBuffers ++;
456476
}
477+
OSMutex_Unlock(drv->hMutex);
457478
if (! didBuffers)
458479
Sleep(1);
459480

0 commit comments

Comments
 (0)