Re: Is this the right list?

Andi Kleen (ak@muc.de)
Mon, 7 Dec 1998 21:30:37 +0100


In muc.lists.linux-kernel, you wrote:
>I apologize in advance in case this is not the right forum for my
>questions. I am a candidate for a Master's degree in Computer Science,
>and my project deals in adding functionality to the TCP/IP stack in
>linux. I am running into some problems, and I am curious about some
>synchronization mechanisms I am using. When is it safe and not safe to
>use the start_bh_atomic() and end_bh_atomic() calls to try to guarantee
>single access to critical sections of code? I am working on the 2.0.36
>kernel until I get this working, then I will port it to 2.1.x or 2.2.x (if
>it's released before I finish). If start/end_bh_atomic() is not supposed
>to be used for a general synch. mechanism, is there one to use, or should
>I roll my own? Also, when I look at the defs for the
>start/end_bh_atomic() calls, they reference a function called barrier()
>that is #defined as:

start_bh_atomic()/end_bh_atomic() can be used from process context to
ensure that no bottom half is run in the critical region (to lock against
bhs).

Bottom halves are guranteed to be atomic compared to each other.

If you want to lock against interrupts use

unsigned long flags;
save_flags(flags);
cli();

...

restore_flags(flags);

instead (this implies no bottom halves too). Blocking interrupts should
be avoided if possible, because they're costly on SMP and are bad for
interrupt latency (and when done the critical region should be kept small)

To lock against other threads simply don't sleep (inside the linux
kernel cooperative multitasking is used) or use semaphores. Linux 2.0
uses a giant lock against the complete kernel for SMP locking, so there
are no additional SMP races to worry about (this changed in Linux 2.1,
although most of the kernel still runs inside the giant lock)

For some small critical regions that only e.g. increment a counter or
replace a value the functions in asm/atomic.h are fast alternatives (these
functions are safe against bottom halves and interrupts)

>
>#define barrier() __asm__("": : :"memory")

That tells gcc to not move any instructions over this - it is used to
prevent overoptimization. For more information on gcc's inline assembly
mechanism see the gcc documentation ("info gcc", m C extensions)

I hope this helps,

-Andi

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/