[Kos-dev] Implémentation des sémaphores dans Fr eeBSD

Thomas Petazzoni kos-dev@enix.org
Mon, 26 May 2003 17:18:52 +0200


This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enigF4A053C8B14EDBB9822C8B07
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit

Hello,

Dans FreeBSD, ils utilisent non pas un entier par sémaphore, mais 2 : la
valeur (l'entier classique d'une sémaphore) et un entier donnant le
nombre de threads en attente sur la sémaphore. Ceci dit, ils passent
quand même un pointeur sur la mutex à cv_wait(), certainement pour qu'il
le relache. J'ai mis le code de cv_wait() en dessous.

Voila les deux bouts de code intéressants
http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/kern/kern_sema.c?rev=1.3&content-type=text/x-cvsweb-markup
:

void
_sema_post(struct sema *sema, const char *file, int line)
{

	mtx_lock(&sema->sema_mtx);
	sema->sema_value++;
	if (sema->sema_waiters && sema->sema_value > 0)
		cv_signal(&sema->sema_cv);

	CTR6(KTR_LOCK, "%s(%p) \"%s\" v = %d at %s:%d", __func__, sema,
	    cv_wmesg(&sema->sema_cv), sema->sema_value, file, line);

	mtx_unlock(&sema->sema_mtx);
}

void
_sema_wait(struct sema *sema, const char *file, int line)
{

	mtx_lock(&sema->sema_mtx);
	while (sema->sema_value == 0) {
		sema->sema_waiters++;
		cv_wait(&sema->sema_cv, &sema->sema_mtx);
		sema->sema_waiters--;
	}
	sema->sema_value--;

	CTR6(KTR_LOCK, "%s(%p) \"%s\" v = %d at %s:%d", __func__, sema,
	    cv_wmesg(&sema->sema_cv), sema->sema_value, file, line);

	mtx_unlock(&sema->sema_mtx);
}

****** Code de cv_wait()
http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/kern/kern_condvar.c?rev=1.41&content-type=text/x-cvsweb-markup
******

/*
 * Wait on a condition variable.  The current thread is placed on the
condition
 * variable's wait queue and suspended.  A cv_signal or cv_broadcast on
the same
 * condition variable will resume the thread.  The mutex is released before
 * sleeping and will be held on return.  It is recommended that the mutex be
 * held when cv_signal or cv_broadcast are called.
 */
void
cv_wait(struct cv *cvp, struct mtx *mp)
{
	struct thread *td;
	WITNESS_SAVE_DECL(mp);

	td = curthread;
#ifdef KTRACE
	if (KTRPOINT(td, KTR_CSW))
		ktrcsw(1, 0);
#endif
	CV_ASSERT(cvp, mp, td);
	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object,
	    "Waiting on \"%s\"", cvp->cv_description);
	WITNESS_SAVE(&mp->mtx_object, mp);

	if (cold ) {
		/*
		 * During autoconfiguration, just give interrupts
		 * a chance, then just return.  Don't run any other
		 * thread or panic below, in case this is the idle
		 * process and already asleep.
		 */
		return;
	}

	mtx_lock_spin(&sched_lock);

	CV_WAIT_VALIDATE(cvp, mp);

	DROP_GIANT();
	mtx_unlock(mp);

	cv_waitq_add(cvp, td);
	cv_switch(td);

	mtx_unlock_spin(&sched_lock);
#ifdef KTRACE
	if (KTRPOINT(td, KTR_CSW))
		ktrcsw(0, 0);
#endif
	PICKUP_GIANT();
	mtx_lock(mp);
	WITNESS_RESTORE(&mp->mtx_object, mp);
}

-- 
PETAZZONI Thomas - thomas DOT petazzoni AT enix DOT org - UIN : 34937744
Web: http://www.enix.org/~thomas/
KOS: http://kos.enix.org/ - Lolut: http://lolut.utbm.info
Fingerprint : 0BE1 4CF3 CEA4 AC9D CC6E  1624 F653 CB30 98D3 F7A7

--------------enigF4A053C8B14EDBB9822C8B07
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE+0jBd9lPLMJjT96cRAoUOAJ9EV/f6Iq4KeIg7hHL7vYCTMt1lIgCdGv+X
FlG64IrnRMEllYhWghwqKzY=
=MA6o
-----END PGP SIGNATURE-----

--------------enigF4A053C8B14EDBB9822C8B07--