[Scummvm-cvs-logs] CVS: scummvm/sound mpu401.cpp,1.11,1.12 mpu401.h,1.9,1.10

Jamieson Christian jamieson630 at users.sourceforge.net
Tue Jun 10 22:55:08 CEST 2003


Update of /cvsroot/scummvm/scummvm/sound
In directory sc8-pr-cvs1:/tmp/cvs-serv5106/scummvm/sound

Modified Files:
	mpu401.cpp mpu401.h 
Log Message:
Fixed race condition in MPU401 shutdown

Index: mpu401.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/mpu401.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- mpu401.cpp	1 Jun 2003 04:05:13 -0000	1.11
+++ mpu401.cpp	11 Jun 2003 05:54:45 -0000	1.12
@@ -76,18 +76,29 @@
 	return midi_errors[error_code];
 }
 
-MidiDriver_MPU401::MidiDriver_MPU401() : MidiDriver() {
-	uint i;
-	
-	_started_thread = false;	// palmos
-	_timer_proc = NULL;			// palmos
-	_timer_param = NULL;		// palmos
+MidiDriver_MPU401::MidiDriver_MPU401() :
+	MidiDriver(),
+	_started_thread (false),
+	_timer_proc (0),
+	_timer_param (0),
+	_mutex (0)
+{
 	
+	uint i;
 	for (i = 0; i < ARRAYSIZE(_midi_channels); ++i) {
 		_midi_channels [i].init (this, i);
 	}
 }
 
+void MidiDriver_MPU401::close() {
+	if (_mutex) {
+		_started_thread = false;
+		g_system->lock_mutex (_mutex); // Wait for the timer thread to shutdown.
+		g_system->unlock_mutex (_mutex);
+		g_system->delete_mutex (_mutex);
+	}
+}
+
 MidiChannel *MidiDriver_MPU401::allocateChannel() {
 	MidiChannel_MPU401 *chan;
 	uint i;
@@ -106,40 +117,45 @@
 
 void MidiDriver_MPU401::setTimerCallback (void *timer_param, void (*timer_proc) (void *)) {
 	if (!_timer_proc || !timer_proc) {
-		_timer_proc = (TimerCallback *) timer_proc;
+		_timer_proc = timer_proc;
 		_timer_param = timer_param;
 		if (!_started_thread && timer_proc) {
 			// TODO: This is the only place in ScummVM where create_thread is
 			// being used. And it's used for a timer like thread. So if we
 			// could convert it to use the timer API instead, we could get
 			// rid of create_thread completely.
+			_mutex = g_system->create_mutex();
+			_started_thread = true;
 			g_system->create_thread(midi_driver_thread, this);
 		}
-		_started_thread = true;
 	}
 }
 
 #if !defined(__MORPHOS__) && !defined(__PALM_OS__)
+typedef void (*TimerCallback) (void*);
+
 int MidiDriver_MPU401::midi_driver_thread(void *param) {
-	volatile MidiDriver_MPU401 *mid = (MidiDriver_MPU401 *)param;
+	MidiDriver_MPU401 *mid = (MidiDriver_MPU401 *)param;
 	int old_time, cur_time;
 
-	old_time = g_system->get_msecs();
+	// Grab the MidiDriver's mutex. When the MidiDriver
+	// shuts down, it will wait on that mutex until we've
+	// detected the shutdown and quit looping.
+	g_system->lock_mutex (mid->_mutex);
 
-	for (;;) {
+	old_time = g_system->get_msecs();
+	while (mid->_started_thread) {
 		g_system->delay_msecs(10);
 
 		cur_time = g_system->get_msecs();
 		while (old_time < cur_time) {
 			old_time += 10;
-			// Don't use mid->_se_on_timer()
-			// We must come in through IMuseMonitor to protect
-			// against conflicts with script access to IMuse.
 			if (mid->_timer_proc)
-				(*(mid->_timer_proc)) (mid->_timer_param);
+				(*(TimerCallback)(mid->_timer_proc)) (mid->_timer_param);
 		}
 	}
 
+	g_system->unlock_mutex (mid->_mutex);
 	return 0;
 }
 #endif

Index: mpu401.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/mpu401.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- mpu401.h	1 Jun 2003 04:05:13 -0000	1.9
+++ mpu401.h	11 Jun 2003 05:54:45 -0000	1.10
@@ -30,8 +30,6 @@
 //
 ////////////////////////////////////////
 
-typedef void TimerCallback (void *);
-
 class MidiDriver_MPU401;
 
 class MidiChannel_MPU401 : public MidiChannel {
@@ -78,8 +76,9 @@
 class MidiDriver_MPU401 : public MidiDriver {
 private:
 	MidiChannel_MPU401 _midi_channels [16];
-	bool _started_thread;
-	TimerCallback *_timer_proc;
+	volatile bool _started_thread;
+	void *_mutex; // Concurrent shutdown barrier
+	volatile void *_timer_proc;
 	void *_timer_param;
 
 	static int midi_driver_thread (void *param);
@@ -87,8 +86,9 @@
 public:
 	MidiDriver_MPU401();
 
+	virtual void close();
 	void setTimerCallback(void *timer_param, void (*timer_proc) (void *));
-	uint32 getBaseTempo(void) { return 10000; } // 0x4A0000; } // Now referenced in microseconds between callbacks
+	uint32 getBaseTempo(void) { return 10000; }
 
 	MidiChannel *allocateChannel();
 	MidiChannel *getPercussionChannel() { return &_midi_channels [9]; }





More information about the Scummvm-git-logs mailing list