[patch] down_norecurse(), down_interruptible_norecurse(), up_norecurse()

Andrea Arcangeli (andrea@e-mind.com)
Sat, 30 Jan 1999 16:33:32 +0100 (CET)


These new functions allow a kernel hacker to use semaphores without
recursion, so you'll be allowed to use again something like this:

data_ready()
{
up_norecurse(&sem)
}

engine()
{
sem = MUTEX_LOCKED_NORECURSE;

while (need_data)
{
down_interruptible_norecurse(&sem);
do_something()
}
}

NOTE: The norecursive functions are _not_ thought to be used mixed with
the recursive ones and I am not going to think at what can happen doing
that ;).

Here the patch against 2.2.1:

Index: semaphore.h
===================================================================
RCS file: /var/cvs/linux/include/asm-i386/semaphore.h,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 semaphore.h
--- semaphore.h 1999/01/25 20:40:02 1.1.2.4
+++ semaphore.h 1999/01/30 14:58:39
@@ -66,6 +66,8 @@

#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, 0, 0, NULL })
#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, 1, 0, NULL })
+#define MUTEX_NORECURSE ((struct semaphore) { ATOMIC_INIT(1), 0, 0, 0, NULL })
+#define MUTEX_LOCKED_NORECURSE ((struct semaphore) { ATOMIC_INIT(0), 0, 0, 0, NULL })

asmlinkage void __down_failed(void /* special register calling convention */);
asmlinkage int __down_failed_interruptible(void /* params in registers */);
@@ -209,6 +211,69 @@
__asm__ __volatile__(
"# atomic up operation\n\t"
"decl 8(%0)\n\t"
+#ifdef __SMP__
+ "lock ; "
+#endif
+ "incl 0(%0)\n\t"
+ "jle 2f\n"
+ "1:\n"
+ ".section .text.lock,\"ax\"\n"
+ "2:\tpushl $1b\n\t"
+ "jmp __up_wakeup\n"
+ ".previous"
+ :/* no outputs */
+ :"c" (sem)
+ :"memory");
+}
+
+extern inline void down_norecurse(struct semaphore * sem)
+{
+ __asm__ __volatile__(
+ "# atomic down operation\n\t"
+#ifdef __SMP__
+ "lock ; "
+#endif
+ "decl 0(%0)\n\t"
+ "js 2f\n\t"
+ "1:\n"
+ ".section .text.lock,\"ax\"\n"
+ "2:\tpushl $1b\n\t"
+ "jmp __down_failed\n"
+ ".previous"
+ :/* no outputs */
+ :"c" (sem)
+ :"memory");
+}
+
+extern inline int down_interruptible_norecurse(struct semaphore * sem)
+{
+ int result;
+
+ __asm__ __volatile__(
+ "# atomic interruptible down operation\n\t"
+#ifdef __SMP__
+ "lock ; "
+#endif
+ "decl 0(%1)\n\t"
+ "js 2f\n\t"
+ "xorl %0,%0\n"
+ "1:\n"
+ ".section .text.lock,\"ax\"\n"
+ "2:\tpushl $1b\n\t"
+ "jmp __down_failed_interruptible\n"
+ ".previous"
+ :"=a" (result)
+ :"c" (sem)
+ :"memory");
+ return result;
+}
+
+extern inline void up_norecurse(struct semaphore * sem)
+{
+ __asm__ __volatile__(
+ "movl $0,4(%0)\n\t"
+ "movl $-1,8(%0)\n\t"
+ "# atomic up operation\n\t"
#ifdef __SMP__
"lock ; "
#endif

Note we could also avoid some asm instruction in norecursive semaphores,
but I don't think it's worth since the recursive semaphores are likely to
be so used that I think it's very probabile that your CPU get the function
__down (see kernel/sched.c) just from the cache. And left
waking_non_zero() untouched made more fun to implement no-recusive
semaphores ;)).

NOTE: the patch is completly untested, but make sense to me (even if
really I had not a lot of time to think about its correcness.. ;)

BTW, MUTEX_LOCKED used with recursive semaphores (2.2.1) is not likely to
make a lot of sense (to me at least) and the code that is using it should
be probably reviewed (e.g. ide_do_drive_cmd(), ide_end_drive_cmd()). Code
that is using MUTEX_LOCKED is likely to want to be converted to
norecursive semaphores. Personally I would remove MUTEX_LOCKED and I would
left only MUTEX, MUTEX_NORECURSE and MUTEX_LOCKED_NORECURSE... I'll do
that here soon but I am not going to post my future changes on the list
even if I am worried by such _potential_ bogus semaphores usages.

NOTE: In many cases we may want to convert a not-recursive semaphore to a
add_wait_queue() loop because is more efficient then a down_norecursive()
and is the right structure to not miss irq handler and at the same time
not cli() the CPU (see Ingo's email for more details), but I see at least
a clean usage of no-recursive semaphores, that could be to take care of
_how_many_ interrupts happened in the meantime. You can handle the same
with a separate volatile counter of course, but a norecursive semaphore
would produce simpler code for sure.

I hope that the patch will work fine ;). If somebody will play with it
please feedback. Thanks.

Andrea Arcangeli

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