Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Nov 2016 20:51:39 +0100
From:      Hans Petter Selasky <hps@selasky.org>
To:        Oleksandr Tymoshenko <gonzo@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r308424 - head/sys/arm/broadcom/bcm2835
Message-ID:  <2b03afc6-9bfa-1124-7b70-2532751bfed9@selasky.org>
In-Reply-To: <c7cd871d-9007-6de4-7063-2680e259713f@selasky.org>
References:  <201611071738.uA7HceYu045944@repo.freebsd.org> <f8169b11-56d8-4566-f9e9-e387dd9b939e@selasky.org> <680D84F2-65BF-48DD-8D11-311B1F65A634@freebsd.org> <c7cd871d-9007-6de4-7063-2680e259713f@selasky.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------470FDF2C15B0D23E906DFD84
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 8bit

On 11/07/16 20:32, Hans Petter Selasky wrote:
> On 11/07/16 20:23, Oleksandr Tymoshenko wrote:
>>
>>> On Nov 7, 2016, at 10:27 AM, Hans Petter Selasky <hps@selasky.org>
>>> wrote:
>>>
>>> On 11/07/16 18:38, Oleksandr Tymoshenko wrote:
>>>> +        bcm2835_audio_unlock(sc);
>>>> +        cv_signal(&sc->worker_cv);
>>>
>>>
>>> Shouldn't cv_signal() be done locked, so that you don't loose any
>>> transactions? CV's only wakeup the treads that are sleeping right
>>> there and then.
>>
>> Hi Hans,
>>
>> In this case it doesn’t matter. bcm2835_audio_xxx lock functions are
>> used to keep channel state consistent. The actual audio hw
>> reprogramming happens in worker thread which only picks up latest
>> state of the virtual channel, there is no need to run every
>> transaction in sequence.
>>
>
> Hi,
>
> It is not about running in sequence, but that if the worker thread is
> not sleeping, but on the way to sleep, it will never get woken up unless
> you use proper locks here!
>
> --HPS

Hi,

Also the teardown sequence for the worker thread looks a bit broken, 
that it doesn't wait for the thread to exit.

I've made a patch, attached which I think is the right way to do it.

Try opening and closing /dev/dsp in a loop with some DSP ioctls and see 
what happens.

--HPS

--------------470FDF2C15B0D23E906DFD84
Content-Type: text/x-patch;
 name="bcm2835_audio.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="bcm2835_audio.diff"

Index: sys/arm/broadcom/bcm2835/bcm2835_audio.c
===================================================================
--- sys/arm/broadcom/bcm2835/bcm2835_audio.c	(revision 308426)
+++ sys/arm/broadcom/bcm2835/bcm2835_audio.c	(working copy)
@@ -149,6 +149,14 @@
 }
 
 static void
+bcm2835_wakeup_worker(struct bcm2835_audio_info *sc)
+{
+	sx_xlock(&sc->worker_lock);
+	cv_signal(&sc->worker_cv);
+	sx_xunlock(&sc->worker_lock);
+}
+
+static void
 bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *msg_handle)
 {
 	struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)param;
@@ -540,6 +548,8 @@
 			}
 		}
 	}
+	sc->unloading = 2;
+	cv_signal(&sc->worker_cv);
 	sx_sunlock(&sc->worker_lock);
 
 	kproc_exit(0);
@@ -586,8 +596,9 @@
 	}
 
 	sc->parameters_update_pending = true;
-	cv_signal(&sc->worker_cv);
 
+	bcm2835_wakeup_worker(sc);
+
 	return ch;
 }
 
@@ -615,7 +626,7 @@
 	sc->parameters_update_pending = true;
 	bcm2835_audio_unlock(sc);
 
-	cv_signal(&sc->worker_cv);
+	bcm2835_wakeup_worker(sc);
 
 	return 0;
 }
@@ -631,7 +642,7 @@
 	sc->parameters_update_pending = true;
 	bcm2835_audio_unlock(sc);
 
-	cv_signal(&sc->worker_cv);
+	bcm2835_wakeup_worker(sc);
 
 	return ch->spd;
 }
@@ -662,8 +673,7 @@
 		bcm2835_audio_unlock(sc);
 		/* kickstart data flow */
 		chn_intr(sc->pch.channel);
-		/* wakeup worker thread */
-		cv_signal(&sc->worker_cv);
+		bcm2835_wakeup_worker(sc);
 		break;
 
 	case PCMTRIG_STOP:
@@ -671,7 +681,7 @@
 		bcm2835_audio_lock(sc);
 		ch->playback_state = PLAYBACK_STOPPING;
 		bcm2835_audio_unlock(sc);
-		cv_signal(&sc->worker_cv);
+		bcm2835_wakeup_worker(sc);
 		break;
 
 	default:
@@ -738,7 +748,8 @@
 		sc->volume = left;
 		sc->controls_update_pending = true;
 		bcm2835_audio_unlock(sc);
-		cv_signal(&sc->worker_cv);
+
+		bcm2835_wakeup_worker(sc);
 		break;
 
 	default:
@@ -776,7 +787,7 @@
 	sc->controls_update_pending = true;
 	bcm2835_audio_unlock(sc);
 
-	cv_signal(&sc->worker_cv);
+	bcm2835_wakeup_worker(sc);
 	device_printf(sc->dev, "destination set to %s\n", dest_description(val));
 
 	return (0);
@@ -898,8 +909,11 @@
 	/* Stop worker thread */
 	sx_xlock(&sc->worker_lock);
 	sc->unloading = 1;
+	cv_signal(&sc->worker_cv);
+	/* Wait for thread to exit */
+	while (sc->unloading != 2)
+		cv_wait_sig(&sc->worker_cv, &sc->worker_lock);
 	sx_xunlock(&sc->worker_lock);
-	cv_signal(&sc->worker_cv);
 
 	r = pcm_unregister(dev);
 	if (r)

--------------470FDF2C15B0D23E906DFD84--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2b03afc6-9bfa-1124-7b70-2532751bfed9>