From: Kyle Moffett <mrmacman_g4@mac.com>
To: David Nicol <davidnicol@gmail.com>
Cc: john cooper <john.cooper@timesys.com>, linux-kernel@vger.kernel.org
Subject: Re: spinaphore conceptual draft (was discussion of RT patch)
Date: Fri, 27 May 2005 21:04:37 -0400 [thread overview]
Message-ID: <A53A981B-98F9-42EC-8939-60A528FEC34E@mac.com> (raw)
In-Reply-To: <934f64a205052715315c21d722@mail.gmail.com>
On May 27, 2005, at 18:31:38, David Nicol wrote:
> On 5/26/05, john cooper <john.cooper@timesys.com> wrote:
>
>> given design. Clearly we aren't buying anything to trade off
>> a spinlock protecting the update of a single pointer with a
>> blocking lock and associated context switching.
>
> On contention, and only on contention, we are faced with the
> question of what
> to do. Do we wait, or do we go away and come back later? What
> information is
> available to us to base the decision on? We can't gather any more
> information,
> because that would take longer than spin-waiting. If the
> "spinaphore" told us,
> on acquisition failure, how many other threads were asking for it, we
> could implement
> a tunable lock, that surrenders context when there are more than N
> threads waiting for
> the resource, and that otherwise waits its turn, or its chance, as
> a compromise
> and synthesis.
Here is an example naive implementation which could perhaps be
optimized further
for architectures based on memory and synchronization requirements.
A quick summary:
Each time the lock is taken and released, a "hold_time" is updated
which indicates
the average time that the lock is held. During contention, each CPU
checks the
current average hold time and the number of CPUs waiting against a
predefined
"context switch + useful work" time, and goes to sleep if it thinks
it has enough
time to spare.
Problems:
You can't nest these. You also can't take a normal semaphore inside
one. The
only useable locking order for these is:
..., semaphore, semaphore, spinaphore, spinlock, spinlock, ...
Possible Solution:
If you had a reliable way of determining when it is safe to sleep,
you could call
a "cond_resched_if_nonatomic()" function instead of cond_resched()
and allow
nesting of spinaphores within each other and within spinlocks. I
_do_ implement a
spinaphore_lock_atomic which is guaranteed not to sleep and could be
used within
other locks instead.
struct spinaphore {
atomic_t queued;
atomic_t hold_time;
spinlock_t spinlock;
unsigned long acquire_time;
};
void spinaphore_lock (struct spinaphore *sph) {
unsigned long start_time = fast_monotonic_count();
int queue_me = 1;
until (likely(spin_trylock(&sph->spinlock))) {
/* Get the queue count (And ensure we're queued in the
process) */
unsigned int queued = queue_me ?
atomic_inc_return(&sph->queued) :
queued = atomic_get(&sph->queued);
queue_me = 0;
/* Figure out if we should switch away */
if (unlikely(CONFIG_SPINAPHORE_CONTEXT_SWITCH <
( queued*atomic_get(&sph->hold_time) -
fast_monotonic_count() - start_time
))) {
/* Remove ourselves from the wait pool (remember to re-
add later) */
atomic_dec(&sph->queued);
queue_me = 1;
/* Go to sleep */
cond_resched();
}
}
/* Dequeue ourselves and update the acquire time */
atomic_dec(&sph->queued);
sph->acquire_time = fast_monotonic_count();
}
void spinaphore_lock_atomic (struct spinaphore *sph) {
/* Let the other processes know what we're doing */
atomic_inc(&sph->queued);
/* Just get the lock the old fashioned way */
spin_lock(&sph->spinlock);
/* Dequeue ourselves and update the acquire time */
atomic_dec(&sph->queued);
sph->acquire_time = fast_monotonic_count();
}
int spinaphore_trylock (struct spinaphore *sph) {
/* Try to get the lock, and if so, update the acquire time */
if (spin_trylock(&sph->spinlock)) {
sph->acquire_time = fast_monotonic_count();
}
void spinaphore_unlock (struct spinaphore *sph) {
/* Update the running average hold time */
atomic_set(&sph->hold_time, (4*atomic_get(&sph->hold_time) +
(fast_monotonic_count() - sph->acquire_time))/5);
/* Actually unlock the spinlock */
spin_unlock(&sph->spinlock);
}
Cheers,
Kyle Moffett
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCM/CS/IT/U d- s++: a18 C++++>$ UB/L/X/*++++(+)>$ P+++(++++)>$
L++++(+++) E W++(+) N+++(++) o? K? w--- O? M++ V? PS+() PE+(-) Y+
PGP+++ t+(+++) 5 X R? tv-(--) b++++(++) DI+ D+ G e->++++$ h!*()>++$
r !y?(-)
------END GEEK CODE BLOCK------
next prev parent reply other threads:[~2005-05-28 1:04 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-05-27 22:31 David Nicol
2005-05-28 1:04 ` Kyle Moffett [this message]
2005-05-29 5:25 ` David Nicol
2005-05-29 13:41 ` Kyle Moffett
2005-05-29 8:42 ` Nikita Danilov
2005-05-29 13:45 ` Kyle Moffett
2005-05-29 13:29 ` Joe Seigh
2005-05-29 15:32 ` Kyle Moffett
2005-05-30 11:06 ` spinaphore conceptual draft Andi Kleen
2005-05-30 14:52 ` Chris Friesen
2005-05-30 16:40 ` Andi Kleen
2005-05-30 17:11 ` Chris Friesen
2005-05-30 17:46 ` Andi Kleen
2005-05-30 18:04 ` Kyle Moffett
2005-05-30 18:40 ` Vojtech Pavlik
2005-05-30 18:54 ` Kyle Moffett
2005-05-30 19:24 ` Andi Kleen
2005-05-30 19:28 ` Andi Kleen
2005-05-30 19:39 ` Kyle Moffett
2005-05-31 22:25 ` Paul E. McKenney
2005-05-28 1:05 ` spinaphore conceptual draft (was discussion of RT patch) john cooper
2005-05-28 2:02 ` Steven Rostedt
2005-05-28 13:59 ` Alan Cox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=A53A981B-98F9-42EC-8939-60A528FEC34E@mac.com \
--to=mrmacman_g4@mac.com \
--cc=davidnicol@gmail.com \
--cc=john.cooper@timesys.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®