On Wed, Mar 26, 2008 at 01:29:58PM -0700, Luck, Tony wrote:I did brifly consider creating a spinaphore data type, but it's significantly less code to create down_spin(). Thanks for testing and putting this together in patch form. I've fixed it up to address Jens' astute comment and added it to my semaphore patchset. http://git.kernel.org/?p=linux/kernel/git/willy/misc.git;a=shortlog;h=semaphore-200803... Stephen, I've updated the 'semaphore' tag to point ot the same place as semaphore-20080327, so please change your linux-next tree from pulling semaphore-20080314 to just pulling plain 'semaphore'. I'll use this method of tagging from now on. Here's the edited patch. commit 517df6fedc88af3f871cf827a62ef1a1a2073645 Author: Matthew Wilcox <matthew@wil.cx> Date: Thu Mar 27 09:49:26 2008 -0400 Add down_spin() ia64 would like to use a semaphore in flush_tlb_all() as it can have multiple tokens. Unfortunately, it's currently nested inside a spinlock, so they can't sleep. down_spin() is the cheapest solution to implement. Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Matthew Wilcox <willy@linux.intel.com> diff --git a/include/linux/semaphore.h b/include/linux/semaphore.h index a7125da..13b5f32 100644 --- a/include/linux/semaphore.h +++ b/include/linux/semaphore.h @@ -78,6 +78,14 @@ extern int __must_check down_trylock(struct semaphore *sem); extern int __must_check down_timeout(struct semaphore *sem, long jiffies); /* + * As down(), except this function will spin waiting for the semaphore + * instead of sleeping. It is safe to use while holding a spinlock or + * with interrupts disabled. It should not be called from interrupt + * context as this may lead to deadlocks. + */ +extern void down_spin(struct semaphore *sem); + +/* * Release the semaphore. Unlike mutexes, up() may be called from any * context and even by tasks which have never called down(). */ diff --git a/kernel/semaphore.c b/kernel/semaphore.c index bef977b..a242d87 100644 --- a/kernel/semaphore.c +++ b/kernel/semaphore.c @@ -26,6 +26,7 @@ static noinline void __down(struct semaphore *sem); static noinline int __down_interruptible(struct semaphore *sem); static noinline int __down_killable(struct semaphore *sem); static noinline int __down_timeout(struct semaphore *sem, long jiffies); +static noinline void __down_spin(struct semaphore *sem, unsigned long flags); static noinline void __up(struct semaphore *sem); void down(struct semaphore *sem) @@ -117,6 +118,20 @@ int down_timeout(struct semaphore *sem, long jiffies) } EXPORT_SYMBOL(down_timeout); +void down_spin(struct semaphore *sem) +{ + unsigned long flags; + + spin_lock_irqsave(&sem->lock, flags); + if (likely(sem->count > 0)) { + sem->count--; + spin_unlock_irqrestore(&sem->lock, flags); + } else { + __down_spin(sem, flags); + } +} +EXPORT_SYMBOL(down_spin); + void up(struct semaphore *sem) { unsigned long flags; @@ -197,6 +212,20 @@ static noinline int __sched __down_timeout(struct semaphore return __down_common(sem, TASK_UNINTERRUPTIBLE, jiffies); } +static noinline void __sched __down_spin(struct semaphore *sem, + unsigned long flags) +{ + struct semaphore_waiter waiter; + + list_add_tail(&waiter.list, &sem->wait_list); + waiter.task = current; + waiter.up = 0; + + spin_unlock_irqrestore(&sem->lock, flags); + while (!waiter.up) + cpu_relax(); +} + static noinline void __sched __up(struct semaphore *sem) { struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list, -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." --
| David Miller | Slow DOWN, please!!! |
| KAMEZAWA Hiroyuki | Re: 2.6.22-rc1-mm1 |
| Steven Rostedt | [RFC PATCH 1/3] Unified trace buffer |
| Steven Rostedt | [RFC PATCH 0/6] Convert all tasklets to workqueues |
git: | |
| Peter Klavins | Re: CRLF problems with Git on Win32 |
| J. Bruce Fields | Re: Git User's Survey 2007 unfinished summary continued |
| Linus Torvalds | Re: VCS comparison table |
| Junichi Uekawa | Re: [ANNOUNCE] GIT 1.5.4 |
| Arjan van de Ven | Re: [GIT]: Networking |
| Rémi | [PATCH 0/6] [RFC] Phonet pipes protocol (v2) |
| Jarek Poplawski | Re: [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Jozsef Kadlecsik | Re: TCP connection stalls under 2.6.24.7 |
| Richard Stallman | Real men don't attack straw men |
| Rogier Krieger | Re: bcw(4) is gone |
| Leon Dippenaar | New tcp stack attack |
| Brandon Lee | DELL PERC 5iR slow performance |
| high memory | 5 hours ago | Linux kernel |
| semaphore access speed | 8 hours ago | Applications and Utilities |
| the kernel how to power off the machine | 9 hours ago | Linux kernel |
| Easter Eggs in windows XP | 12 hours ago | Windows |
| Shared swap partition | 13 hours ago | Linux general |
| Root password | 13 hours ago | Linux general |
| Where/when DNOTIFY is used? | 15 hours ago | Linux kernel |
| How to convert Linux Kernel built-in module into a loadable module | 17 hours ago | Linux kernel |
| Linux 2.6.24 and I/O schedulers | 18 hours ago | Linux kernel |
| USB Driver -- Interrupt Polling -- A Little Help Please | 23 hours ago | Linux general |
