Cocoa Port:

- Reverse locking mechanics for the core emulation loop's producer/consumer threads. (Instead of the producer telling consumers to lock, now consumers check if the producer is locked.)
- Add additional error check for the execution state within the core emulation loop.
- Reduce spin lock time when setting the GPU state flags.
- Improve thread safety when changing the execution state.
This commit is contained in:
rogerman 2012-03-10 20:42:49 +00:00
parent 0fdb9308c1
commit 7ae952f366
3 changed files with 55 additions and 46 deletions

View File

@ -465,6 +465,8 @@ static BOOL isCoreStarted = NO;
- (void) setCoreState:(NSInteger)coreState
{
pthread_mutex_lock(&threadParam.mutexThreadExecute);
if (threadParam.state == CORESTATE_PAUSE)
{
prevCoreState = CORESTATE_PAUSE;
@ -474,7 +476,6 @@ static BOOL isCoreStarted = NO;
prevCoreState = CORESTATE_EXECUTE;
}
pthread_mutex_lock(&threadParam.mutexThreadExecute);
threadParam.state = coreState;
pthread_cond_signal(&threadParam.condThreadExecute);
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
@ -618,6 +619,7 @@ static BOOL isCoreStarted = NO;
- (void) addOutput:(CocoaDSOutput *)theOutput
{
theOutput.mutexProducer = self.mutexCoreExecute;
[self.cdsOutputList addObject:theOutput];
}
@ -673,16 +675,20 @@ void* RunCoreThread(void *arg)
// We'll just jump directly to ending the input processing.
NDS_endProcessingInput();
for(CocoaDSOutput *cdsOutput in cdsOutputList)
{
pthread_mutex_lock(cdsOutput.mutexOutputFrame);
}
// Execute the frame and increment the frame counter.
pthread_mutex_lock(param->mutexCoreExecute);
NDS_exec<false>();
pthread_mutex_unlock(param->mutexCoreExecute);
// Check if an internal execution error occurred that halted the emulation.
if (!execute)
{
pthread_mutex_unlock(&param->mutexThreadExecute);
// TODO: Message the core that emulation halted.
NSLog(@"The emulator halted during execution. Was it an internal error that caused this?");
continue;
}
if (param->framesToSkip == 0)
{
param->frameCount++;
@ -692,12 +698,10 @@ void* RunCoreThread(void *arg)
{
if (param->framesToSkip > 0 && [cdsOutput isMemberOfClass:[CocoaDSDisplay class]])
{
pthread_mutex_unlock(cdsOutput.mutexOutputFrame);
continue;
}
[cdsOutput doCoreEmuFrame];
pthread_mutex_unlock(cdsOutput.mutexOutputFrame);
}
// Determine the number of frames to skip based on how much time "debt"

View File

@ -30,14 +30,16 @@
NSData *frameData;
NSMutableDictionary *property;
pthread_mutex_t *mutexOutputFrame;
pthread_mutex_t *mutexProducer;
pthread_mutex_t *mutexConsume;
}
@property (assign) BOOL isStateChanged;
@property (assign) NSUInteger frameCount;
@property (retain) NSData *frameData;
@property (readonly) NSMutableDictionary *property;
@property (readonly) pthread_mutex_t *mutexOutputFrame;
@property (assign) pthread_mutex_t *mutexProducer;
@property (readonly) pthread_mutex_t *mutexConsume;
- (void) doCoreEmuFrame;
- (void) handleEmuFrameProcessed:(NSData *)theData;

View File

@ -45,7 +45,8 @@ GPU3DInterface *core3DList[] = {
@synthesize frameCount;
@synthesize frameData;
@synthesize property;
@synthesize mutexOutputFrame;
@synthesize mutexProducer;
@synthesize mutexConsume;
- (id)init
{
@ -62,8 +63,8 @@ GPU3DInterface *core3DList[] = {
property = [[NSMutableDictionary alloc] init];
[property setValue:[NSDate date] forKey:@"outputTime"];
mutexOutputFrame = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexOutputFrame, NULL);
mutexConsume = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexConsume, NULL);
return self;
}
@ -85,9 +86,9 @@ GPU3DInterface *core3DList[] = {
self.frameData = nil;
[property release];
pthread_mutex_destroy(mutexOutputFrame);
free(mutexOutputFrame);
mutexOutputFrame = nil;
pthread_mutex_destroy(mutexConsume);
free(mutexConsume);
mutexConsume = NULL;
[super dealloc];
}
@ -199,7 +200,7 @@ GPU3DInterface *core3DList[] = {
[property setValue:[NSNumber numberWithInteger:methodID] forKey:@"audioOutputEngine"];
OSSpinLockUnlock(&spinlockAudioOutputEngine);
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
NSInteger result = -1;
@ -213,7 +214,7 @@ GPU3DInterface *core3DList[] = {
SPU_ChangeSoundCore(SNDCORE_DUMMY, 0);
}
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
// Force the volume back to it's original setting.
[self setVolume:[self volume]];
@ -234,9 +235,9 @@ GPU3DInterface *core3DList[] = {
[property setValue:[NSNumber numberWithBool:state] forKey:@"spuAdvancedLogic"];
OSSpinLockUnlock(&spinlockSpuAdvancedLogic);
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.spu_advanced = state;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (BOOL) spuAdvancedLogic
@ -254,9 +255,9 @@ GPU3DInterface *core3DList[] = {
[property setValue:[NSNumber numberWithInteger:modeID] forKey:@"spuInterpolationMode"];
OSSpinLockUnlock(&spinlockSpuInterpolationMode);
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.spuInterpolationMode = (SPUInterpolationMode)modeID;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (NSInteger) spuInterpolationMode
@ -276,9 +277,9 @@ GPU3DInterface *core3DList[] = {
NSInteger methodID = [self spuSyncMethod];
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
SPU_SetSynchMode(modeID, methodID);
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (NSInteger) spuSyncMode
@ -298,9 +299,9 @@ GPU3DInterface *core3DList[] = {
NSInteger modeID = [self spuSyncMode];
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
SPU_SetSynchMode(modeID, methodID);
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (NSInteger) spuSyncMethod
@ -554,8 +555,10 @@ GPU3DInterface *core3DList[] = {
- (void) setGpuStateFlags:(UInt32)flags
{
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = flags;
OSSpinLockUnlock(&spinlockGpuState);
pthread_mutex_lock(self.mutexProducer);
if (flags & GPUSTATE_MAIN_GPU_MASK)
{
@ -689,7 +692,7 @@ GPU3DInterface *core3DList[] = {
[property setValue:[NSNumber numberWithBool:NO] forKey:@"gpuStateSubOBJ"];
}
OSSpinLockUnlock(&spinlockGpuState);
pthread_mutex_unlock(self.mutexProducer);
}
- (UInt32) gpuStateFlags
@ -771,9 +774,9 @@ GPU3DInterface *core3DList[] = {
[property setValue:[NSNumber numberWithInteger:methodID] forKey:@"render3DRenderingEngine"];
OSSpinLockUnlock(&spinlockRender3DRenderingEngine);
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
NDS_3D_ChangeCore(methodID);
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (NSInteger) render3DRenderingEngine
@ -797,9 +800,9 @@ GPU3DInterface *core3DList[] = {
cState = true;
}
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.GFX3D_HighResolutionInterpolateColor = cState;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (BOOL) render3DHighPrecisionColorInterpolation
@ -823,9 +826,9 @@ GPU3DInterface *core3DList[] = {
cState = true;
}
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.GFX3D_EdgeMark = cState;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (BOOL) render3DEdgeMarking
@ -849,9 +852,9 @@ GPU3DInterface *core3DList[] = {
cState = true;
}
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.GFX3D_Fog = cState;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (BOOL) render3DFog
@ -875,9 +878,9 @@ GPU3DInterface *core3DList[] = {
cState = true;
}
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.GFX3D_Texture = cState;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (BOOL) render3DTextures
@ -895,9 +898,9 @@ GPU3DInterface *core3DList[] = {
[property setValue:[NSNumber numberWithInteger:threshold] forKey:@"render3DDepthComparisonThreshold"];
OSSpinLockUnlock(&spinlockRender3DDepthComparisonThreshold);
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = threshold;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (NSUInteger) render3DDepthComparisonThreshold
@ -936,15 +939,15 @@ GPU3DInterface *core3DList[] = {
numberCores = numberThreads;
}
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.num_cores = numberCores;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
if ([self render3DRenderingEngine] == CORE3DLIST_SWRASTERIZE)
{
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
NDS_3D_ChangeCore(CORE3DLIST_SWRASTERIZE);
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
}
@ -969,9 +972,9 @@ GPU3DInterface *core3DList[] = {
cState = true;
}
pthread_mutex_lock(self.mutexOutputFrame);
pthread_mutex_lock(self.mutexProducer);
CommonSettings.GFX3D_LineHack = cState;
pthread_mutex_unlock(self.mutexOutputFrame);
pthread_mutex_unlock(self.mutexProducer);
}
- (BOOL) render3DLineHack