From 5bf4a6d52b8cce9264ef88c6fe4d44fd3da7f593 Mon Sep 17 00:00:00 2001 From: Bart Trzynadlowski Date: Wed, 14 Sep 2011 07:38:56 +0000 Subject: [PATCH] - Added mutex for MIDI FIFO access to SCSP.cpp. --- Src/Model3/SoundBoard.cpp | 5 +- Src/Model3/SoundBoard.h | 1 + Src/OSD/SDL/Thread.cpp | 33 ++++++++++- Src/OSD/Thread.h | 37 ++++++++++-- Src/Sound/SCSP.cpp | 119 +++++++++++++++++++++++++++++++++++--- Src/Sound/SCSP.h | 17 +++++- 6 files changed, 194 insertions(+), 18 deletions(-) diff --git a/Src/Model3/SoundBoard.cpp b/Src/Model3/SoundBoard.cpp index 1490e4a..a674cb1 100644 --- a/Src/Model3/SoundBoard.cpp +++ b/Src/Model3/SoundBoard.cpp @@ -1,7 +1,7 @@ /** ** Supermodel ** A Sega Model 3 Arcade Emulator. - ** Copyright 2011 Bart Trzynadlowski + ** Copyright 2011 Bart Trzynadlowski, Nik Henson ** ** This file is part of Supermodel. ** @@ -500,7 +500,8 @@ bool CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr) // Initialize SCSPs SCSP_SetBuffers(audioL, audioR, 44100/60); SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback); - SCSP_Init(2); + if (OKAY != SCSP_Init(2)) + return FAIL; SCSP_SetRAM(0, ram1); SCSP_SetRAM(1, ram2); diff --git a/Src/Model3/SoundBoard.h b/Src/Model3/SoundBoard.h index 88bea14..9b9df55 100644 --- a/Src/Model3/SoundBoard.h +++ b/Src/Model3/SoundBoard.h @@ -31,6 +31,7 @@ #include "Types.h" #include "CPU/Bus.h" #include "Model3/DSB.h" +#include "OSD/Thread.h" /* * CSoundBoardConfig: diff --git a/Src/OSD/SDL/Thread.cpp b/Src/OSD/SDL/Thread.cpp index fa3e776..7a43e01 100755 --- a/Src/OSD/SDL/Thread.cpp +++ b/Src/OSD/SDL/Thread.cpp @@ -1,10 +1,37 @@ +/** + ** Supermodel + ** A Sega Model 3 Arcade Emulator. + ** Copyright 2011 Bart Trzynadlowski, Nik Henson + ** + ** This file is part of Supermodel. + ** + ** Supermodel 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 3 of the License, or (at your option) + ** any later version. + ** + ** Supermodel 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 Supermodel. If not, see . + **/ + +/* + * Thread.cpp + * + * SDL-based implementation of threading primitives. + */ + #include "Supermodel.h" - + #ifdef SUPERMODEL_OSX -#include +#include #include #else -#include +#include #include #endif diff --git a/Src/OSD/Thread.h b/Src/OSD/Thread.h index 0821043..a8900d4 100755 --- a/Src/OSD/Thread.h +++ b/Src/OSD/Thread.h @@ -1,3 +1,30 @@ +/** + ** Supermodel + ** A Sega Model 3 Arcade Emulator. + ** Copyright 2011 Bart Trzynadlowski, Nik Henson + ** + ** This file is part of Supermodel. + ** + ** Supermodel 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 3 of the License, or (at your option) + ** any later version. + ** + ** Supermodel 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 Supermodel. If not, see . + **/ + +/* + * Thread.h + * + * Header file for threading primitives. + */ + #ifndef INCLUDED_THREADS_H #define INCLUDED_THREADS_H @@ -7,10 +34,10 @@ class CCondVar; typedef int (*ThreadStart)(void *startParam); -/* - * CThread - * - * Class that represents an O/S thread. +/* + * CThread + * + * Class that represents an O/S thread. */ class CThread { @@ -122,7 +149,7 @@ public: }; /* - * CSemaphore + * CCondVar * * Class that represents a condition variable. */ diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp index 58a67b6..01cb3ca 100644 --- a/Src/Sound/SCSP.cpp +++ b/Src/Sound/SCSP.cpp @@ -1,7 +1,7 @@ /** ** Supermodel ** A Sega Model 3 Arcade Emulator. - ** Copyright 2011 Bart Trzynadlowski + ** Copyright 2011 Bart Trzynadlowski, Nik Henson ** ** This file is part of Supermodel. ** @@ -116,6 +116,7 @@ unsigned int RevR,RevW; #define DWORD UINT32 #endif +static CMutex *MIDILock; // for safe access to the MIDI FIFOs static int (*Run68kCB)(int cycles); static void (*Int68kCB)(int irq); static void (*RetIntCB)(); @@ -332,14 +333,31 @@ void CheckPendingIRQ() return; } */ + + /* + * MIDI FIFO critical section + * + * NOTE: I don't think a mutex is really needed here, so I've disabled + * this critical section. + */ + //if (g_Config.multiThreaded) + // MIDILock->Lock(); + if(MidiW!=MidiR) { + //if (g_Config.multiThreaded) + // MIDILock->Unlock(); + //SCSP.data[0x20/2]|=0x8; //Hold midi line while there are commands pending Int68kCB(IrqMidi); //printf("68K: MIDI IRQ\n"); //ErrorLogMessage("Midi"); return; } + + //if (g_Config.multiThreaded) + // MIDILock->Unlock(); + if(!pend) return; if(pend&0x40) @@ -535,7 +553,7 @@ void SCSP_StopSlot(_SLOT *slot,int keyoff) #define log2(n) (log((float) n)/log((float) 2)) -void SCSP_Init(int n) +bool SCSP_Init(int n) { if(n==2) { @@ -712,10 +730,30 @@ void SCSP_Init(int n) #endif LFO_Init(); + buffertmpl = NULL; + buffertmpr = NULL; buffertmpl=(signed int*) malloc(44100*sizeof(signed int)); + if (NULL == buffertmpl) + return ErrorLog("Insufficient memory for internal SCSP buffers."); buffertmpr=(signed int*) malloc(44100*sizeof(signed int)); + if (NULL == buffertmpl) + { + free(buffertmpl); + return ErrorLog("Insufficient memory for internal SCSP buffers."); + } memset(buffertmpl,0,44100*sizeof(signed int)); memset(buffertmpr,0,44100*sizeof(signed int)); + + // MIDI FIFO mutex + MIDILock = CThread::CreateMutex(); + if (NULL == MIDILock) + { + free(buffertmpl); + free(buffertmpr); + return ErrorLog("Unable to create MIDI mutex!"); + } + + return OKAY; } void SCSP_SetRAM(int n,unsigned char *r) @@ -887,6 +925,13 @@ void SCSP_UpdateRegR(int reg) { unsigned short v=SCSP->data[0x5/2]; v&=0xff00; + + /* + * MIDI FIFO critical section! + */ + if (g_Config.multiThreaded) + MIDILock->Lock(); + v|=MidiStack[MidiR]; //printf("read MIDI\n"); if(MidiR!=MidiW) @@ -894,11 +939,13 @@ void SCSP_UpdateRegR(int reg) ++MidiR; MidiR&=MIDI_STACK_SIZE_MASK; //Int68kCB(IrqMidi); - } MidiInFill--; SCSP->data[0x5/2]=v; + + if (g_Config.multiThreaded) + MIDILock->Unlock(); } break; case 8: @@ -1870,46 +1917,100 @@ void SCSP_SetCB(int (*Run68k)(int cycles),void (*Int68k)(int irq)) void SCSP_MidiIn(BYTE val) { + /* + * MIDI FIFO critical section + */ + if (g_Config.multiThreaded) + MIDILock->Lock(); + //DebugLog("Midi Buffer push %02X",val); - MidiStack[MidiW++]=val; MidiW&=MIDI_STACK_SIZE_MASK; MidiInFill++; //Int68kCB(IrqMidi); // SCSP.data[0x20/2]|=0x8; + + if (g_Config.multiThreaded) + MIDILock->Unlock(); } void SCSP_MidiOutW(BYTE val) { + /* + * MIDI FIFO critical section + */ + if (g_Config.multiThreaded) + MIDILock->Lock(); + //printf("68K: MIDI out\n"); //DebugLog("Midi Out Buffer push %02X",val); MidiStack[MidiOutW++]=val; MidiOutW&=7; ++MidiOutFill; + + if (g_Config.multiThreaded) + MIDILock->Unlock(); } unsigned char SCSP_MidiOutR() { unsigned char val; - if(MidiOutR==MidiOutW) + + if(MidiOutR==MidiOutW) // I don't think this needs to be a critical section... return 0xff; + + /* + * MIDI FIFO critical section + */ + if (g_Config.multiThreaded) + MIDILock->Lock(); val=MidiStack[MidiOutR++]; //DebugLog("Midi Out Buffer pop %02X",val); MidiOutR&=7; --MidiOutFill; + + if (g_Config.multiThreaded) + MIDILock->Unlock(); + return val; } unsigned char SCSP_MidiOutFill() { - return MidiOutFill; + unsigned char v; + + /* + * MIDI FIFO critical section + */ + if (g_Config.multiThreaded) + MIDILock->Lock(); + + v = MidiOutFill; + + if (g_Config.multiThreaded) + MIDILock->Unlock(); + + return v; } unsigned char SCSP_MidiInFill() { - return MidiInFill; + unsigned char v; + + /* + * MIDI FIFO critical section + */ + if (g_Config.multiThreaded) + MIDILock->Lock(); + + v = MidiInFill; + + if (g_Config.multiThreaded) + MIDILock->Unlock(); + + return v; } void SCSP_RTECheck() @@ -2218,4 +2319,8 @@ void SCSP_Deinit(void) #endif free(buffertmpl); free(buffertmpr); + delete MIDILock; + buffertmpl = NULL; + buffertmpr = NULL; + MIDILock = NULL; } diff --git a/Src/Sound/SCSP.h b/Src/Sound/SCSP.h index 15c5185..8c68cdc 100644 --- a/Src/Sound/SCSP.h +++ b/Src/Sound/SCSP.h @@ -44,7 +44,22 @@ UINT8 SCSP_MidiOutFill(); UINT8 SCSP_MidiInFill(); void SCSP_CpuRunScanline(); UINT8 SCSP_MidiOutR(); -void SCSP_Init(int n); + +/* + * SCSP_Init(n): + * + * Initializes the SCSPs, allocates internal memory, and creates a mutex for + * MIDI FIFO access. Call SCSP_SetCB() and SCSP_SetBuffers() before calling + * this. + * + * Parameters: + * n Number of SCSPs to create. Always use 2! + * + * Returns: + * FAIL if an error occured (prints own error messages), OKAY otherwise. + */ +bool SCSP_Init(int n); + void SCSP_SetRAM(int n,UINT8 *r); void SCSP_RTECheck(); int SCSP_IRQCB(int);