[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--