public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Martin Wirth <martin.wirth@epost.de>
To: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] 2.5: push BKL out of llseek
Date: Wed, 30 Jan 2002 22:14:21 +0100	[thread overview]
Message-ID: <3C58622D.6B0265ED@epost.de> (raw)

Hi,

This is just a general idea I had a few month ago and might be of some
value
for the replacement of BKL or longheld spinlocks in the future 2.5
developement.

While writing some device driver for a real-time data acquisition I had
a 
similar problem. I had to protect some driver data structure that is 
heavily accessed from multiple processes for merely reading a few
variables
consistently. But from time to time there are bigger tasks to be done,
where
holding a spinlock is not appropriate. 

So I used a combination of a spinlock and a semaphore. You can lock this
combilock for short-term issues in a spin-lock mode:

       combi_spin_lock(struct combilock *x)
       combi_spin_unlock(struct combilock *x)

and for longer lasting tasks in a semaphore mode by:

       combi_mutex_lock(struct combilock *x)
       combi_mutex_unlock(struct combilock *x)

If a spin-lock request is blocked by a mutex-lock, the spin-lock
attempt also sleeps i.e. behaves like a semaphore.

This approach is less automatic than a first_spin_then_sleep mutex,
but normally the programmer knows better if he is going to do quick
things, or
maybe maybe unbounded stuff.

Note: For a preemtible kernel this approach could lead to much less
scheduling ping-pong also for UP if a spinlock is replaced by a
combilock 
instead of a semaphore.  


The code is quite simple and borrowed a bit from the completion handler
stuff
in sched.c. (Of course the owner could be a simple flag, but I had some
later 
extension to a priority inheritance scheme in mind).

struct combilock {
       wait_queue_head_t wait;
       task_t            *owner;
};


void combi_spin_lock(struct combilock *x)
{
       spin_lock(&x->wait.lock);
       if (x->owner) {
              DECLARE_WAITQUEUE(wait, current);
              wait.flags |= WQ_FLAG_EXCLUSIVE;
	      __add_wait_queue_tail(&x->wait, &wait);
	      do {
	             __set_current_state(TASK_UNINTERRUPTIBLE);
		     spin_unlock(&x->wait.lock);
		     schedule();
		     spin_lock(&x->wait.lock);
	      } while (x->owner);
	      __remove_wait_queue(&x->wait, &wait);
       }
}


void combi_spin_unlock(struct combilock *x)
{
       spin_unlock(&x->wait.lock);  
}


void combi_mutex_lock(struct combilock *x)
{
       spin_lock(&x->wait.lock);
       if (x->owner) {
              DECLARE_WAITQUEUE(wait, current);
              wait.flags |= WQ_FLAG_EXCLUSIVE;
	      __add_wait_queue_tail(&x->wait, &wait);
	      do {
		     __set_current_state(TASK_UNINTERRUPTIBLE);
		     spin_unlock(&x->wait.lock);
		     schedule();
		     spin_lock(&x->wait.lock);
	      } while (x->owner);
	      __remove_wait_queue(&x->wait, &wait);
       } else 
              x->owner=current;  
       spin_unlock(&x->wait.lock);
}


void combi_mutex_unlock(struct combilock *x)
{
	spin_lock(&x->wait.lock);
	x->owner=NULL;
	__wake_up_common(&x->wait, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE,
1, 0);
	spin_unlock(&x->wait.lock);
}


Martin Wirth

             reply	other threads:[~2002-01-30 21:15 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-01-30 21:14 Martin Wirth [this message]
  -- strict thread matches above, loose matches on Subject: below --
2002-02-01 19:29 [PATCH] 2.5: push BKL out of llseek John Hawkes
2002-01-31 15:39 Martin Wirth
2002-01-31 21:06 ` Nigel Gamble
2002-01-30  0:00 Robert Love
2002-01-30  0:09 ` Linus Torvalds
2002-01-30  0:41   ` Robert Love
2002-01-30  0:52     ` Linus Torvalds
2002-01-30  2:24       ` Robert Love
2002-01-30  1:26     ` Andrew Morton
2002-01-30  2:16       ` Linus Torvalds
2002-01-30  2:20       ` Robert Love
2002-01-30  2:20         ` Andrew Morton
2002-01-30  2:21         ` Dave Jones
2002-01-30  2:37           ` Robert Love
2002-01-30  2:50         ` Nigel Gamble
2002-01-30  3:19           ` Andrew Morton
2002-01-30  9:34             ` Nigel Gamble
2002-01-30 10:36         ` Russell King
2002-01-30  4:54   ` Alexander Viro
2002-01-30  8:00     ` Trond Myklebust
2002-01-30 13:39       ` Robert Love
2002-01-30  4:50 ` Anton Blanchard
2002-01-30  5:03 ` Robert Love

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=3C58622D.6B0265ED@epost.de \
    --to=martin.wirth@epost.de \
    --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