A question about the softirq implementation in DDE Linux26

Björn Döbel doebel at os.inf.tu-dresden.de
Mon Mar 1 16:59:42 CET 2010


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

> Can't we simulate the same semantics with a lock? If the same thread already
> holds the lock, local_irq_disable() does nothing. My implementation for now
> works pretty well, at least for the pcnet32 driver. Maybe I miss something
> important. Here is my code:
> int raw_irqs_disabled_flags(unsigned long flags)
> {
> 	return ((int)flags > 0);
> }
> 
> /* If it does lock operation successfully, return > 0. Otherwise, 0. */
> static int nested_lock(ddekit_lock_t lock)
> {
> 	int do_lock = 0;
> 
> 	if (ddekit_lock_try_lock(&lock)) {  /* if we cannot lock */
> 		/* check who hold the lock. */
> 		if (_ddekit_lock_owner(&lock) != (int) ddekit_thread_myself()) {
> 			/* Someone else holds the lock,
> 			 * or by the time I try to lock again,
> 			 * the person has release the lock. */
> 			ddekit_lock_lock(&lock);
> 			do_lock = 1;
> 		}
> 		/* If I hold the lock myself, I don't need to worry
> 		 * the lock will be released somewhere before I do it. */
> 	}
> 	else
> 		do_lock = 2;
> 
> 	return do_lock;
> }
> 
> /* Store the current flags state.
>  *
>  * This is done by returning the current refcnt.
>  *
>  * XXX: Up to now, flags was always 0 at this point and
>  *      I assume that this is always the case. Prove?
>  */
> unsigned long __raw_local_save_flags(void)
> {
> 	unsigned long flags;
> 	int do_lock = 0;
> 
> 	if (cli_lock == NULL)
> 		ddekit_lock_init_unlocked(&cli_lock);
> 	/* It's important to do lock here.
> 	 * Otherwise, a thread might not get correct flags. */
> 	do_lock = nested_lock(cli_lock);
> 	flags = (unsigned long)atomic_read(&_refcnt);
> 	if (do_lock)
> 		ddekit_lock_unlock(&cli_lock);
> 	return flags;
> }
> 
> /* Restore IRQ state. */
> void raw_local_irq_restore(unsigned long flags)
> {
> 	Assert(cli_lock != NULL);
> 	atomic_set(&_refcnt, flags);
> 	if (flags == 0)
> 		ddekit_lock_unlock(&cli_lock);
> }
> 
> /* Disable IRQs by grabbing the IRQ lock. */
> void raw_local_irq_disable(void)
> {
> 	struct ddekit_thread *helder;
> 	int is_print = 0;
> 
> 	if (cli_lock == NULL)
> 		ddekit_lock_init_unlocked(&cli_lock);
> 
> 	nested_lock(cli_lock);
> 	atomic_inc(&_refcnt);
> }
> 
> /* Unlock the IRQ lock until refcnt is 0. */
> void raw_local_irq_enable(void)
> {
> 	Assert(cli_lock != NULL);
> 	atomic_set(&_refcnt, 0);
> 	ddekit_lock_unlock(&cli_lock);
> }

Compiles and runs for me right now. However, this solution does a global
IRQ disable by using a global CLI/STI lock and therefore does not adhere
to the DDE semantics of every thread running on its own virtual CPU. So,
this may not be the final solution we'll end up with, but if it works
for you, feel free to go ahead with it.

>> L4Linux uses a threaded lock implementation for that reason, so we'll
>> discuss reusing this idea.
> What is a threaded lock?

It's a lock implementation that uses a dedicated thread to serialize
lock accesses and implements waiting on a lock by blocking in an IPC to
this thread.

Bjoern
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkuL5G4ACgkQP5ijxgQLUNkrvACdHNZA0ecT1Xsl0/IUvO30eTEt
dbMAn0PMcLb1Xu5EjzYeKVsstUo+tiuA
=ONEv
-----END PGP SIGNATURE-----




More information about the l4-hackers mailing list