public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Russ Lewis <russ@deming-os.org>
To: linux-kernel@vger.kernel.org
Subject: Safely giving up a lock before sleeping
Date: Mon, 23 Jul 2001 14:49:50 -0700	[thread overview]
Message-ID: <3B5C9BFE.5BFB8BC7@deming-os.org> (raw)

I'm writing a module where I need to go to sleep and release a spinlock
as I do so.  I know how to do this, but it's not elegant...I'm wondering
if anyone has a more elegant solution to what I would guess is a common
problem.


The problem:
I have a module that gets called by other modules' bottom half
handlers.  These calls add information to a job queue I manage.  I then
have user processes that perform read operations on device files asking
for work.  If there is no work currently available, I put them to
sleep.  Of course, this user thread must release the spinlock before
going to sleep.  The calls from the bottom half handlers wake up the
wait queue after they put new work on the job queue.

If I implement this by calling spin_unlock_irqrestore() immediately
followed by interruptible_sleep_on(), then I have a race condition where
I could release the lock and immediately have a bottom half handler on
another processor grab it, put data in the queue, and wake the wait
queue.  My original (user-side) process then happily goes to sleep,
unaware that new information is available.

My current solution:
I looked at the source of interruptible_sleep_on and stuck my
spin_unlock_irqsave right into the middle of it.  My code currently is:

current->state = TASK_INTERRUPTIBLE;
add_wait_queue_exclusive(...);
spin_unlock_irqrestore(...);
schedule();

This avoids the wait condition, since the lock is not released until the
process is set to INTERRUPTIBLE and is on the qait queue.  Thus, if the
other process races me and puts work on the queue and wakes up the wait
queue before I complete schedule(), then my state is simply reset to
TASK_RUNNING and the user process just keeps going.

Of course, since I need the lock to do anything, the first thing I do
(after removing myself from the wait queue and checking for signals) is
to relock the lock.

Is this a common problem?  Is there a more elegant solution to this?


             reply	other threads:[~2001-07-23 21:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-07-23 21:49 Russ Lewis [this message]
2001-07-24 12:39 ` Safely giving up a lock before sleeping Richard B. Johnson
  -- strict thread matches above, loose matches on Subject: below --
2001-07-24 15:20 Manfred Spraul

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=3B5C9BFE.5BFB8BC7@deming-os.org \
    --to=russ@deming-os.org \
    --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