lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <a781481a0706241112g5d50a0c7necdebb1c8d3bca09@mail.gmail.com>
Date:	Sun, 24 Jun 2007 23:42:47 +0530
From:	"Satyam Sharma" <satyam.sharma@...il.com>
To:	"Robert P. J. Day" <rpjday@...dspring.com>
Cc:	"Arnd Bergmann" <arnd@...db.de>, "Florin Iucha" <florin@...ha.net>,
	"Linux Kernel Mailing List" <linux-kernel@...r.kernel.org>
Subject: Re: "upping" a semaphore from interrupt context?

Hi,

On 6/24/07, Robert P. J. Day <rpjday@...dspring.com> wrote:
> On Sun, 24 Jun 2007, Satyam Sharma wrote:
>
> > Whoa, hold on. But I've been explicitly mentioning *binary*
> > semaphores all along!
> >
> > Of course users who want / allow multiple tasks (but only upto a
> > specific maximum number, which is what counted semaphores are all
> > about) to be present in a given critical section simultaneously
> > would still want to use the _counted_ semaphores, which is why you
> > won't see the old "struct semaphores" dying anytime soon.
>
> ah, ok, i've been misreading all this, sorry.  i'm wondering, then,
> if, given both mutexes and completions, whether the general semantics
> of semaphores can be tightened up at all.  just curious.

[ Ok, I'll elaborate, just in case someone else interested regarding
this is watching or reading the archives ... but this may be waaaaay
too basic for you and others here, so those can safely ignore it. ]

First: By a semaphore being binary, I mean that the value of that
semaphore (counter) variable can only be 0 or 1. Say we follow the
rule that 1 == available (unlocked) and 0 == unavailable (locked).
So down == lock == test-and-decrement, up == unlock == increment.

Also, note that there is nothing (I'm _not_ talking of implementation
details here) that the "struct mutex" can do something that a *binary*
"struct semaphore" can't, if usage ensures that its value is always
in {0, 1}. So semantically speaking they are equivalent.

1. (Binary) semaphores used for locking:
========================================

Binary semaphores may be used to synchronize access to critical sections
that can (must) only be executed by _only_ *one* task at any given time.
That is, _no_ concurrent execution of that piece of code can be tolerated.
This is often the most common case / usage to implement lock-protection
of any shared data.

Now obviously, because only _one_ task can be in such critical sections
at any given time, who (and only who) can be allowed to unlock the
semaphore (i.e. increment the counter variable back to 1)?

The task that took this (binary) semaphore in the first place, isn't it?
So this precisely one of those extra sanity checks that the "struct
mutex" introduces. [ There are other sanity checks listed at the top of
include/linux/mutex.h, but this is one of the important ones, IMHO. ]

Why is this check _not_ applicable to *counting* semaphores? Because
_multiple_ tasks can be in that given critical section _concurrently_
so the task that _last_ down()'ed the semaphore *need not be* forced
to be same as the task that _next_ wants to up() it!

2. Semaphores used to indicate completion:
==========================================

Ok, this one's again purely an implementation thing -- in fact if you
look at the way "struct semaphore"s are currently implemented in the
kernel they _do_ use waitqueues, which is precisely what
"struct completion"s use as well. The difference is even less pronounced
because all down()'s do become (in the slowpath i.e. when the test failed
so we decide to schedule() ourselves out) _add_wait_queue_tail with
callers marking themselves as exclusive waiters), and all up()'s also do
call __wake_up_common with NR_EXCLUSIVE == 1 to ensure that at
least one exclusively-waiting task _is_ woken up when the lock is
released (i.e. counter incremented).

So this basically means that one _can_ use semaphores as completion
notification primitives, and also (to again give the technically
accurate answer to Florin's original question on this thread) "upping"
is not illegal per-se from interrupt/atomic contexts.

But wait_for_completion() and complete() are to be still preferred in
new code (although they have a very similar implementation) because they
are specifically for this purpose, plus they avoid all the extra
fastpath/lock-acquiring stuff that the semaphore implementation involves
(and one less member in the struct if nothing else). [ I have never
benchmarked, of course, but I'd expect use of the completion primitives
to be microscopically faster than using semaphores in this manner too. ]

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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ