diff --git a/[refs] b/[refs] index 012c8e2b9d56..0df7c990d3ba 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 710675d3609b1123a40db1eb28bf34041b1d37f2 +refs/heads/master: 69a331470ff02561cf1898eeb152ccca9f22bf53 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 4ce895a4b5ba..bef79776b388 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -4022,11 +4022,11 @@ S: Supported XFS FILESYSTEM P: Silicon Graphics Inc -P: Tim Shimmin +P: Tim Shimmin, David Chatterton M: xfs-masters@oss.sgi.com L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs -T: git git://oss.sgi.com:8090/xfs/xfs-2.6.git +T: git git://oss.sgi.com:8090/xfs/xfs-2.6 S: Supported XILINX UARTLITE SERIAL DRIVER diff --git a/trunk/arch/s390/appldata/appldata_base.c b/trunk/arch/s390/appldata/appldata_base.c index 6ffbab77ae4d..81a2b92ab0c2 100644 --- a/trunk/arch/s390/appldata/appldata_base.c +++ b/trunk/arch/s390/appldata/appldata_base.c @@ -535,7 +535,8 @@ void appldata_unregister_ops(struct appldata_ops *ops) /******************************* init / exit *********************************/ -static void __cpuinit appldata_online_cpu(int cpu) +static void +appldata_online_cpu(int cpu) { init_virt_timer(&per_cpu(appldata_timer, cpu)); per_cpu(appldata_timer, cpu).function = appldata_timer_function; @@ -579,7 +580,7 @@ appldata_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata appldata_nb = { +static struct notifier_block appldata_nb = { .notifier_call = appldata_cpu_notify, }; diff --git a/trunk/arch/s390/kernel/entry.S b/trunk/arch/s390/kernel/entry.S index 6234c6978a1f..c8a2212014e0 100644 --- a/trunk/arch/s390/kernel/entry.S +++ b/trunk/arch/s390/kernel/entry.S @@ -769,13 +769,10 @@ mcck_return: RESTORE_ALL __LC_RETURN_MCCK_PSW,0 +#ifdef CONFIG_SMP /* * Restart interruption handler, kick starter for additional CPUs */ -#ifdef CONFIG_SMP -#ifndef CONFIG_HOTPLUG_CPU - .section .init.text,"ax" -#endif .globl restart_int_handler restart_int_handler: l %r15,__LC_SAVE_AREA+60 # load ksp @@ -788,9 +785,6 @@ restart_int_handler: br %r14 # branch to start_secondary restart_addr: .long start_secondary -#ifndef CONFIG_HOTPLUG_CPU - .previous -#endif #else /* * If we do not run with SMP enabled, let the new CPU crash ... diff --git a/trunk/arch/s390/kernel/entry64.S b/trunk/arch/s390/kernel/entry64.S index 685f11faa4bc..93745fd8f555 100644 --- a/trunk/arch/s390/kernel/entry64.S +++ b/trunk/arch/s390/kernel/entry64.S @@ -745,13 +745,10 @@ mcck_return: #endif lpswe __LC_RETURN_MCCK_PSW # back to caller +#ifdef CONFIG_SMP /* * Restart interruption handler, kick starter for additional CPUs */ -#ifdef CONFIG_SMP -#ifndef CONFIG_HOTPLUG_CPU - .section .init.text,"ax" -#endif .globl restart_int_handler restart_int_handler: lg %r15,__LC_SAVE_AREA+120 # load ksp @@ -762,9 +759,6 @@ restart_int_handler: lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on jg start_secondary -#ifndef CONFIG_HOTPLUG_CPU - .previous -#endif #else /* * If we do not run with SMP enabled, let the new CPU crash ... diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index 7e1bfb984064..51d6309e7f3b 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -300,7 +300,6 @@ static void __init setup_zfcpdump(unsigned int console_devno) else sprintf(str, "cio_ignore=all,!0.0.%04x", ipl_info.data.fcp.dev_id.devno); - strcat(COMMAND_LINE, " "); strcat(COMMAND_LINE, str); console_loglevel = 2; } diff --git a/trunk/arch/s390/kernel/traps.c b/trunk/arch/s390/kernel/traps.c index ee9186f8fb08..cbfe73034c30 100644 --- a/trunk/arch/s390/kernel/traps.c +++ b/trunk/arch/s390/kernel/traps.c @@ -253,22 +253,19 @@ void die(const char * str, struct pt_regs * regs, long err) { static int die_counter; - oops_enter(); debug_stop_all(); console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); - print_modules(); - show_regs(regs); + show_regs(regs); bust_spinlocks(0); - spin_unlock_irq(&die_lock); + spin_unlock_irq(&die_lock); if (in_interrupt()) panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception: panic_on_oops"); - oops_exit(); - do_exit(SIGSEGV); + do_exit(SIGSEGV); } static void inline diff --git a/trunk/arch/sh/kernel/signal.c b/trunk/arch/sh/kernel/signal.c index b32c35a7c0a3..fdca038e4b91 100644 --- a/trunk/arch/sh/kernel/signal.c +++ b/trunk/arch/sh/kernel/signal.c @@ -481,7 +481,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0) { int ret; @@ -500,6 +500,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, } /* fallthrough */ case -ERESTARTNOINTR: + regs->regs[0] = save_r0; regs->pc -= instruction_size( ctrl_inw(regs->pc - 4)); break; @@ -583,7 +584,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + if (handle_signal(signr, &ka, &info, oldset, regs, save_r0) + == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply diff --git a/trunk/drivers/message/fusion/mptspi.c b/trunk/drivers/message/fusion/mptspi.c index 37bf65348372..d75f7ffbb02e 100644 --- a/trunk/drivers/message/fusion/mptspi.c +++ b/trunk/drivers/message/fusion/mptspi.c @@ -727,15 +727,13 @@ static int mptspi_slave_configure(struct scsi_device *sdev) struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)sdev->host->hostdata; VirtTarget *vtarget = scsi_target(sdev)->hostdata; - int ret; - - mptspi_initTarget(hd, vtarget, sdev); - - ret = mptscsih_slave_configure(sdev); + int ret = mptscsih_slave_configure(sdev); if (ret) return ret; + mptspi_initTarget(hd, vtarget, sdev); + ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x" " max_offset=0x%02x max_width=%d\n", hd->ioc->name, sdev->id, spi_min_period(scsi_target(sdev)), diff --git a/trunk/drivers/s390/char/zcore.c b/trunk/drivers/s390/char/zcore.c index 4e711a985d59..66eb0688d523 100644 --- a/trunk/drivers/s390/char/zcore.c +++ b/trunk/drivers/s390/char/zcore.c @@ -267,9 +267,7 @@ struct zcore_header { u64 tod; cpuid_t cpu_id; u32 arch_id; - u32 volnr; u32 build_arch; - u64 rmem_size; char pad2[4016]; } __attribute__((packed,__aligned__(16))); @@ -561,7 +559,6 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr) else hdr->arch_id = DUMP_ARCH_S390; hdr->mem_size = sys_info.mem_size; - hdr->rmem_size = sys_info.mem_size; hdr->mem_end = sys_info.mem_size; hdr->num_pages = sys_info.mem_size / PAGE_SIZE; hdr->tod = get_clock(); diff --git a/trunk/drivers/scsi/esp_scsi.c b/trunk/drivers/scsi/esp_scsi.c index 71caf2ded6ba..ec71061aef61 100644 --- a/trunk/drivers/scsi/esp_scsi.c +++ b/trunk/drivers/scsi/esp_scsi.c @@ -2033,7 +2033,6 @@ static void esp_reset_cleanup(struct esp *esp) starget_for_each_device(tp->starget, NULL, esp_clear_hold); } - esp->flags &= ~ESP_FLAG_RESETTING; } /* Runs under host->lock */ diff --git a/trunk/fs/xfs/linux-2.6/xfs_lrw.c b/trunk/fs/xfs/linux-2.6/xfs_lrw.c index ed90403f0ee7..86fb671a8bcc 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_lrw.c +++ b/trunk/fs/xfs/linux-2.6/xfs_lrw.c @@ -159,7 +159,7 @@ xfs_iozero( if (status) goto unlock; - zero_user_page(page, offset, bytes, KM_USER0); + memclear_highpage_flush(page, offset, bytes); status = mapping->a_ops->commit_write(NULL, page, offset, offset + bytes); diff --git a/trunk/include/asm-s390/processor.h b/trunk/include/asm-s390/processor.h index 5cb480af65d5..e0fcea8c64c3 100644 --- a/trunk/include/asm-s390/processor.h +++ b/trunk/include/asm-s390/processor.h @@ -216,11 +216,6 @@ static inline void cpu_relax(void) barrier(); } -static inline void psw_set_key(unsigned int key) -{ - asm volatile("spka 0(%0)" : : "d" (key)); -} - /* * Set PSW to specified value. */ diff --git a/trunk/include/asm-s390/ptrace.h b/trunk/include/asm-s390/ptrace.h index 332ee73688fc..fa6ca87080e8 100644 --- a/trunk/include/asm-s390/ptrace.h +++ b/trunk/include/asm-s390/ptrace.h @@ -470,7 +470,14 @@ struct user_regs_struct #define regs_return_value(regs)((regs)->gprs[2]) #define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs * regs); -#endif /* __KERNEL__ */ +#endif + +static inline void +psw_set_key(unsigned int key) +{ + asm volatile("spka 0(%0)" : : "d" (key)); +} + #endif /* __ASSEMBLY__ */ #endif /* _S390_PTRACE_H */ diff --git a/trunk/include/linux/futex.h b/trunk/include/linux/futex.h index 99650353adfa..899fc7f20edd 100644 --- a/trunk/include/linux/futex.h +++ b/trunk/include/linux/futex.h @@ -17,6 +17,7 @@ union ktime; #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_CMP_REQUEUE_PI 9 #define FUTEX_PRIVATE_FLAG 128 #define FUTEX_CMD_MASK ~FUTEX_PRIVATE_FLAG @@ -96,10 +97,15 @@ struct robust_list_head { */ #define FUTEX_OWNER_DIED 0x40000000 +/* + * Some processes have been requeued on this PI-futex + */ +#define FUTEX_WAITER_REQUEUED 0x20000000 + /* * The rest of the robust-futex field is for the TID: */ -#define FUTEX_TID_MASK 0x3fffffff +#define FUTEX_TID_MASK 0x0fffffff /* * This limit protects against a deliberately circular list. @@ -133,6 +139,7 @@ handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi); #define FUT_OFF_MMSHARED 2 /* We set bit 1 if key has a reference on mm */ union futex_key { + u32 __user *uaddr; struct { unsigned long pgoff; struct inode *inode; diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index df248f5e0836..3b7f7713d9a4 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -56,6 +56,12 @@ #include "rtmutex_common.h" +#ifdef CONFIG_DEBUG_RT_MUTEXES +# include "rtmutex-debug.h" +#else +# include "rtmutex.h" +#endif + #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) /* @@ -105,6 +111,12 @@ struct futex_q { /* Optional priority inheritance state: */ struct futex_pi_state *pi_state; struct task_struct *task; + + /* + * This waiter is used in case of requeue from a + * normal futex to a PI-futex + */ + struct rt_mutex_waiter waiter; }; /* @@ -204,6 +216,9 @@ int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared, if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ)) return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES; + /* Save the user address in the ley */ + key->uaddr = uaddr; + /* * Private mappings are handled in a simple way. * @@ -621,6 +636,8 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) int ret = 0; newval = FUTEX_WAITERS | new_owner->pid; + /* Keep the FUTEX_WAITER_REQUEUED flag if it was set */ + newval |= (uval & FUTEX_WAITER_REQUEUED); pagefault_disable(); curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); @@ -732,6 +749,259 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, return ret; } +/* + * Called from futex_requeue_pi. + * Set FUTEX_WAITERS and FUTEX_WAITER_REQUEUED flags on the + * PI-futex value; search its associated pi_state if an owner exist + * or create a new one without owner. + */ +static inline int +lookup_pi_state_for_requeue(u32 __user *uaddr, struct futex_hash_bucket *hb, + union futex_key *key, + struct futex_pi_state **pi_state) +{ + u32 curval, uval, newval; + +retry: + /* + * We can't handle a fault cleanly because we can't + * release the locks here. Simply return the fault. + */ + if (get_futex_value_locked(&curval, uaddr)) + return -EFAULT; + + /* set the flags FUTEX_WAITERS and FUTEX_WAITER_REQUEUED */ + if ((curval & (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED)) + != (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED)) { + /* + * No waiters yet, we prepare the futex to have some waiters. + */ + + uval = curval; + newval = uval | FUTEX_WAITERS | FUTEX_WAITER_REQUEUED; + + pagefault_disable(); + curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); + pagefault_enable(); + + if (unlikely(curval == -EFAULT)) + return -EFAULT; + if (unlikely(curval != uval)) + goto retry; + } + + if (!(curval & FUTEX_TID_MASK) + || lookup_pi_state(curval, hb, key, pi_state)) { + /* the futex has no owner (yet) or the lookup failed: + allocate one pi_state without owner */ + + *pi_state = alloc_pi_state(); + + /* Already stores the key: */ + (*pi_state)->key = *key; + + /* init the mutex without owner */ + __rt_mutex_init(&(*pi_state)->pi_mutex, NULL); + } + + return 0; +} + +/* + * Keep the first nr_wake waiter from futex1, wake up one, + * and requeue the next nr_requeue waiters following hashed on + * one physical page to another physical page (PI-futex uaddr2) + */ +static int futex_requeue_pi(u32 __user *uaddr1, + struct rw_semaphore *fshared, + u32 __user *uaddr2, + int nr_wake, int nr_requeue, u32 *cmpval) +{ + union futex_key key1, key2; + struct futex_hash_bucket *hb1, *hb2; + struct plist_head *head1; + struct futex_q *this, *next; + struct futex_pi_state *pi_state2 = NULL; + struct rt_mutex_waiter *waiter, *top_waiter = NULL; + struct rt_mutex *lock2 = NULL; + int ret, drop_count = 0; + + if (refill_pi_state_cache()) + return -ENOMEM; + +retry: + /* + * First take all the futex related locks: + */ + if (fshared) + down_read(fshared); + + ret = get_futex_key(uaddr1, fshared, &key1); + if (unlikely(ret != 0)) + goto out; + ret = get_futex_key(uaddr2, fshared, &key2); + if (unlikely(ret != 0)) + goto out; + + hb1 = hash_futex(&key1); + hb2 = hash_futex(&key2); + + double_lock_hb(hb1, hb2); + + if (likely(cmpval != NULL)) { + u32 curval; + + ret = get_futex_value_locked(&curval, uaddr1); + + if (unlikely(ret)) { + spin_unlock(&hb1->lock); + if (hb1 != hb2) + spin_unlock(&hb2->lock); + + /* + * If we would have faulted, release mmap_sem, fault + * it in and start all over again. + */ + if (fshared) + up_read(fshared); + + ret = get_user(curval, uaddr1); + + if (!ret) + goto retry; + + return ret; + } + if (curval != *cmpval) { + ret = -EAGAIN; + goto out_unlock; + } + } + + head1 = &hb1->chain; + plist_for_each_entry_safe(this, next, head1, list) { + if (!match_futex (&this->key, &key1)) + continue; + if (++ret <= nr_wake) { + wake_futex(this); + } else { + /* + * FIRST: get and set the pi_state + */ + if (!pi_state2) { + int s; + /* do this only the first time we requeue someone */ + s = lookup_pi_state_for_requeue(uaddr2, hb2, + &key2, &pi_state2); + if (s) { + ret = s; + goto out_unlock; + } + + lock2 = &pi_state2->pi_mutex; + spin_lock(&lock2->wait_lock); + + /* Save the top waiter of the wait_list */ + if (rt_mutex_has_waiters(lock2)) + top_waiter = rt_mutex_top_waiter(lock2); + } else + atomic_inc(&pi_state2->refcount); + + + this->pi_state = pi_state2; + + /* + * SECOND: requeue futex_q to the correct hashbucket + */ + + /* + * If key1 and key2 hash to the same bucket, no need to + * requeue. + */ + if (likely(head1 != &hb2->chain)) { + plist_del(&this->list, &hb1->chain); + plist_add(&this->list, &hb2->chain); + this->lock_ptr = &hb2->lock; +#ifdef CONFIG_DEBUG_PI_LIST + this->list.plist.lock = &hb2->lock; +#endif + } + this->key = key2; + get_futex_key_refs(&key2); + drop_count++; + + + /* + * THIRD: queue it to lock2 + */ + spin_lock_irq(&this->task->pi_lock); + waiter = &this->waiter; + waiter->task = this->task; + waiter->lock = lock2; + plist_node_init(&waiter->list_entry, this->task->prio); + plist_node_init(&waiter->pi_list_entry, this->task->prio); + plist_add(&waiter->list_entry, &lock2->wait_list); + this->task->pi_blocked_on = waiter; + spin_unlock_irq(&this->task->pi_lock); + + if (ret - nr_wake >= nr_requeue) + break; + } + } + + /* If we've requeued some tasks and the top_waiter of the rt_mutex + has changed, we must adjust the priority of the owner, if any */ + if (drop_count) { + struct task_struct *owner = rt_mutex_owner(lock2); + if (owner && + (top_waiter != (waiter = rt_mutex_top_waiter(lock2)))) { + int chain_walk = 0; + + spin_lock_irq(&owner->pi_lock); + if (top_waiter) + plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); + else + /* + * There was no waiters before the requeue, + * the flag must be updated + */ + mark_rt_mutex_waiters(lock2); + + plist_add(&waiter->pi_list_entry, &owner->pi_waiters); + __rt_mutex_adjust_prio(owner); + if (owner->pi_blocked_on) { + chain_walk = 1; + get_task_struct(owner); + } + + spin_unlock_irq(&owner->pi_lock); + spin_unlock(&lock2->wait_lock); + + if (chain_walk) + rt_mutex_adjust_prio_chain(owner, 0, lock2, NULL, + current); + } else { + /* No owner or the top_waiter does not change */ + mark_rt_mutex_waiters(lock2); + spin_unlock(&lock2->wait_lock); + } + } + +out_unlock: + spin_unlock(&hb1->lock); + if (hb1 != hb2) + spin_unlock(&hb2->lock); + + /* drop_futex_key_refs() must be called outside the spinlocks. */ + while (--drop_count >= 0) + drop_futex_key_refs(&key1); + +out: + if (fshared) + up_read(fshared); + return ret; +} + /* * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: @@ -1114,6 +1384,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, while (!ret) { newval = (uval & FUTEX_OWNER_DIED) | newtid; + newval |= (uval & FUTEX_WAITER_REQUEUED); pagefault_disable(); curval = futex_atomic_cmpxchg_inatomic(uaddr, @@ -1145,7 +1416,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, struct futex_q q; u32 uval; int ret; - struct hrtimer_sleeper t; + struct hrtimer_sleeper t, *to = NULL; int rem = 0; q.pi_state = NULL; @@ -1201,6 +1472,14 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, if (uval != val) goto out_unlock_release_sem; + /* + * This rt_mutex_waiter structure is prepared here and will + * be used only if this task is requeued from a normal futex to + * a PI-futex with futex_requeue_pi. + */ + debug_rt_mutex_init_waiter(&q.waiter); + q.waiter.task = NULL; + /* Only actually queue if *uaddr contained val. */ __queue_me(&q, hb); @@ -1231,6 +1510,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, if (!abs_time) schedule(); else { + to = &t; hrtimer_init(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); hrtimer_init_sleeper(&t, current); t.timer.expires = *abs_time; @@ -1258,6 +1538,67 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, * we are the only user of it. */ + if (q.pi_state) { + /* + * We were woken but have been requeued on a PI-futex. + * We have to complete the lock acquisition by taking + * the rtmutex. + */ + + struct rt_mutex *lock = &q.pi_state->pi_mutex; + + spin_lock(&lock->wait_lock); + if (unlikely(q.waiter.task)) { + remove_waiter(lock, &q.waiter); + } + spin_unlock(&lock->wait_lock); + + if (rem) + ret = -ETIMEDOUT; + else + ret = rt_mutex_timed_lock(lock, to, 1); + + if (fshared) + down_read(fshared); + spin_lock(q.lock_ptr); + + /* + * Got the lock. We might not be the anticipated owner if we + * did a lock-steal - fix up the PI-state in that case. + */ + if (!ret && q.pi_state->owner != curr) { + /* + * We MUST play with the futex we were requeued on, + * NOT the current futex. + * We can retrieve it from the key of the pi_state + */ + uaddr = q.pi_state->key.uaddr; + + ret = fixup_pi_state_owner(uaddr, &q, curr); + } else { + /* + * Catch the rare case, where the lock was released + * when we were on the way back before we locked + * the hash bucket. + */ + if (ret && q.pi_state->owner == curr) { + if (rt_mutex_trylock(&q.pi_state->pi_mutex)) + ret = 0; + } + } + + /* Unqueue and drop the lock */ + unqueue_me_pi(&q); + if (fshared) + up_read(fshared); + + debug_rt_mutex_free_waiter(&q.waiter); + + return ret; + } + + debug_rt_mutex_free_waiter(&q.waiter); + /* If we were woken (and unqueued), we succeeded, whatever. */ if (!unqueue_me(&q)) return 0; @@ -1307,6 +1648,51 @@ static long futex_wait_restart(struct restart_block *restart) } +static void set_pi_futex_owner(struct futex_hash_bucket *hb, + union futex_key *key, struct task_struct *p) +{ + struct plist_head *head; + struct futex_q *this, *next; + struct futex_pi_state *pi_state = NULL; + struct rt_mutex *lock; + + /* Search a waiter that should already exists */ + + head = &hb->chain; + + plist_for_each_entry_safe(this, next, head, list) { + if (match_futex (&this->key, key)) { + pi_state = this->pi_state; + break; + } + } + + BUG_ON(!pi_state); + + /* set p as pi_state's owner */ + lock = &pi_state->pi_mutex; + + spin_lock(&lock->wait_lock); + spin_lock_irq(&p->pi_lock); + + list_add(&pi_state->list, &p->pi_state_list); + pi_state->owner = p; + + + /* set p as pi_mutex's owner */ + debug_rt_mutex_proxy_lock(lock, p); + WARN_ON(rt_mutex_owner(lock)); + rt_mutex_set_owner(lock, p, 0); + rt_mutex_deadlock_account_lock(lock, p); + + plist_add(&rt_mutex_top_waiter(lock)->pi_list_entry, + &p->pi_waiters); + __rt_mutex_adjust_prio(p); + + spin_unlock_irq(&p->pi_lock); + spin_unlock(&lock->wait_lock); +} + /* * Userspace tried a 0 -> TID atomic transition of the futex value * and failed. The kernel side here does the whole locking operation: @@ -1367,7 +1753,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, * situation and we return success to user space. */ if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) { - ret = -EDEADLK; + if (!(curval & FUTEX_WAITER_REQUEUED)) + ret = -EDEADLK; goto out_unlock_release_sem; } @@ -1387,14 +1774,14 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, /* * There are two cases, where a futex might have no owner (the - * owner TID is 0): OWNER_DIED. We take over the futex in this - * case. We also do an unconditional take over, when the owner - * of the futex died. + * owner TID is 0): OWNER_DIED or REQUEUE. We take over the + * futex in this case. We also do an unconditional take over, + * when the owner of the futex died. * * This is safe as we are protected by the hash bucket lock ! */ if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { - /* Keep the OWNER_DIED bit */ + /* Keep the OWNER_DIED and REQUEUE bits */ newval = (curval & ~FUTEX_TID_MASK) | current->pid; ownerdied = 0; lock_taken = 1; @@ -1410,10 +1797,14 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, goto retry_locked; /* - * We took the lock due to owner died take over. + * We took the lock due to requeue or owner died take over. */ - if (unlikely(lock_taken)) + if (unlikely(lock_taken)) { + /* For requeue we need to fixup the pi_futex */ + if (curval & FUTEX_WAITER_REQUEUED) + set_pi_futex_owner(hb, &q.key, curr); goto out_unlock_release_sem; + } /* * We dont have the lock. Look up the PI state (or create it if @@ -1898,6 +2289,8 @@ int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi) * userspace. */ mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; + /* Also keep the FUTEX_WAITER_REQUEUED flag if set */ + mval |= (uval & FUTEX_WAITER_REQUEUED); nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval); if (nval == -EFAULT) @@ -2034,6 +2427,9 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, case FUTEX_TRYLOCK_PI: ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1); break; + case FUTEX_CMP_REQUEUE_PI: + ret = futex_requeue_pi(uaddr, fshared, uaddr2, val, val2, &val3); + break; default: ret = -ENOSYS; } @@ -2064,7 +2460,8 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, /* * requeue parameter in 'utime' if cmd == FUTEX_REQUEUE. */ - if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE) + if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE + || cmd == FUTEX_CMP_REQUEUE_PI) val2 = (u32) (unsigned long) utime; return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); diff --git a/trunk/kernel/futex_compat.c b/trunk/kernel/futex_compat.c index f7921360efad..27478948b318 100644 --- a/trunk/kernel/futex_compat.c +++ b/trunk/kernel/futex_compat.c @@ -157,7 +157,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, t = ktime_add(ktime_get(), t); tp = &t; } - if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE) + if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE + || cmd == FUTEX_CMP_REQUEUE_PI) val2 = (int) (unsigned long) utime; return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); diff --git a/trunk/kernel/rtmutex.c b/trunk/kernel/rtmutex.c index 17d28ce20300..a6fbb4130521 100644 --- a/trunk/kernel/rtmutex.c +++ b/trunk/kernel/rtmutex.c @@ -56,7 +56,7 @@ * state. */ -static void +void rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner, unsigned long mask) { @@ -80,29 +80,6 @@ static void fixup_rt_mutex_waiters(struct rt_mutex *lock) clear_rt_mutex_waiters(lock); } -/* - * We can speed up the acquire/release, if the architecture - * supports cmpxchg and if there's no debugging state to be set up - */ -#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES) -# define rt_mutex_cmpxchg(l,c,n) (cmpxchg(&l->owner, c, n) == c) -static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) -{ - unsigned long owner, *p = (unsigned long *) &lock->owner; - - do { - owner = *p; - } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner); -} -#else -# define rt_mutex_cmpxchg(l,c,n) (0) -static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) -{ - lock->owner = (struct task_struct *) - ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS); -} -#endif - /* * Calculate task priority from the waiter list priority * @@ -123,7 +100,7 @@ int rt_mutex_getprio(struct task_struct *task) * * This can be both boosting and unboosting. task->pi_lock must be held. */ -static void __rt_mutex_adjust_prio(struct task_struct *task) +void __rt_mutex_adjust_prio(struct task_struct *task) { int prio = rt_mutex_getprio(task); @@ -159,11 +136,11 @@ int max_lock_depth = 1024; * Decreases task's usage by one - may thus free the task. * Returns 0 or -EDEADLK. */ -static int rt_mutex_adjust_prio_chain(struct task_struct *task, - int deadlock_detect, - struct rt_mutex *orig_lock, - struct rt_mutex_waiter *orig_waiter, - struct task_struct *top_task) +int rt_mutex_adjust_prio_chain(struct task_struct *task, + int deadlock_detect, + struct rt_mutex *orig_lock, + struct rt_mutex_waiter *orig_waiter, + struct task_struct *top_task) { struct rt_mutex *lock; struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter; @@ -537,8 +514,8 @@ static void wakeup_next_waiter(struct rt_mutex *lock) * * Must be called with lock->wait_lock held */ -static void remove_waiter(struct rt_mutex *lock, - struct rt_mutex_waiter *waiter) +void remove_waiter(struct rt_mutex *lock, + struct rt_mutex_waiter *waiter) { int first = (waiter == rt_mutex_top_waiter(lock)); struct task_struct *owner = rt_mutex_owner(lock); diff --git a/trunk/kernel/rtmutex_common.h b/trunk/kernel/rtmutex_common.h index 9c75856e791e..242ec7ee740b 100644 --- a/trunk/kernel/rtmutex_common.h +++ b/trunk/kernel/rtmutex_common.h @@ -112,6 +112,29 @@ static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock) return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING; } +/* + * We can speed up the acquire/release, if the architecture + * supports cmpxchg and if there's no debugging state to be set up + */ +#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES) +# define rt_mutex_cmpxchg(l,c,n) (cmpxchg(&l->owner, c, n) == c) +static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) +{ + unsigned long owner, *p = (unsigned long *) &lock->owner; + + do { + owner = *p; + } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner); +} +#else +# define rt_mutex_cmpxchg(l,c,n) (0) +static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) +{ + lock->owner = (struct task_struct *) + ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS); +} +#endif + /* * PI-futex support (proxy locking functions, etc.): */ @@ -120,4 +143,15 @@ extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock, struct task_struct *proxy_owner); extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, struct task_struct *proxy_owner); + +extern void rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner, + unsigned long mask); +extern void __rt_mutex_adjust_prio(struct task_struct *task); +extern int rt_mutex_adjust_prio_chain(struct task_struct *task, + int deadlock_detect, + struct rt_mutex *orig_lock, + struct rt_mutex_waiter *orig_waiter, + struct task_struct *top_task); +extern void remove_waiter(struct rt_mutex *lock, + struct rt_mutex_waiter *waiter); #endif diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index a7475913b009..13cdab3b4c48 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -1159,72 +1159,21 @@ void wait_task_inactive(struct task_struct *p) { unsigned long flags; struct rq *rq; - struct prio_array *array; - int running; + int preempted; repeat: - /* - * We do the initial early heuristics without holding - * any task-queue locks at all. We'll only try to get - * the runqueue lock when things look like they will - * work out! - */ - rq = task_rq(p); - - /* - * If the task is actively running on another CPU - * still, just relax and busy-wait without holding - * any locks. - * - * NOTE! Since we don't hold any locks, it's not - * even sure that "rq" stays as the right runqueue! - * But we don't care, since "task_running()" will - * return false if the runqueue has changed and p - * is actually now running somewhere else! - */ - while (task_running(rq, p)) - cpu_relax(); - - /* - * Ok, time to look more closely! We need the rq - * lock now, to be *sure*. If we're wrong, we'll - * just go back and repeat. - */ rq = task_rq_lock(p, &flags); - running = task_running(rq, p); - array = p->array; - task_rq_unlock(rq, &flags); - - /* - * Was it really running after all now that we - * checked with the proper locks actually held? - * - * Oops. Go back and try again.. - */ - if (unlikely(running)) { + /* Must be off runqueue entirely, not preempted. */ + if (unlikely(p->array || task_running(rq, p))) { + /* If it's preempted, we yield. It could be a while. */ + preempted = !task_running(rq, p); + task_rq_unlock(rq, &flags); cpu_relax(); + if (preempted) + yield(); goto repeat; } - - /* - * It's not enough that it's not actively running, - * it must be off the runqueue _entirely_, and not - * preempted! - * - * So if it wa still runnable (but just not actively - * running right now), it's preempted, and we should - * yield - it could be a while. - */ - if (unlikely(array)) { - yield(); - goto repeat; - } - - /* - * Ahh, all good. It wasn't running, and it wasn't - * runnable, which means that it will never become - * running in the future either. We're all done! - */ + task_rq_unlock(rq, &flags); } /*** @@ -7122,13 +7071,12 @@ EXPORT_SYMBOL(__might_sleep); void normalize_rt_tasks(void) { struct prio_array *array; - struct task_struct *g, *p; + struct task_struct *p; unsigned long flags; struct rq *rq; read_lock_irq(&tasklist_lock); - - do_each_thread(g, p) { + for_each_process(p) { if (!rt_task(p)) continue; @@ -7146,8 +7094,7 @@ void normalize_rt_tasks(void) __task_rq_unlock(rq); spin_unlock_irqrestore(&p->pi_lock, flags); - } while_each_thread(g, p); - + } read_unlock_irq(&tasklist_lock); } diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index f9405609774e..fe590e00db8d 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -363,13 +363,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, */ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) { - int signr = 0; - - /* We only dequeue private signals from ourselves, we don't let - * signalfd steal them - */ - if (tsk == current) - signr = __dequeue_signal(&tsk->pending, mask, info); + int signr = __dequeue_signal(&tsk->pending, mask, info); if (!signr) { signr = __dequeue_signal(&tsk->signal->shared_pending, mask, info); diff --git a/trunk/sound/ppc/pmac.c b/trunk/sound/ppc/pmac.c index 7a22f0f3784a..5a2bef44a2f5 100644 --- a/trunk/sound/ppc/pmac.c +++ b/trunk/sound/ppc/pmac.c @@ -775,8 +775,7 @@ static int snd_pmac_free(struct snd_pmac *chip) out_le32(&chip->awacs->control, in_le32(&chip->awacs->control) & 0xfff); } - if (chip->node) - snd_pmac_sound_feature(chip, 0); + snd_pmac_sound_feature(chip, 0); /* clean up mixer if any */ if (chip->mixer_free) @@ -926,7 +925,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) } if (! sound) { of_node_put(chip->node); - chip->node = NULL; return -ENODEV; } prop = of_get_property(sound, "sub-frame", NULL); @@ -939,9 +937,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) printk(KERN_INFO "snd-powermac no longer handles any " "machines with a layout-id property " "in the device-tree, use snd-aoa.\n"); - of_node_put(sound); of_node_put(chip->node); - chip->node = NULL; return -ENODEV; } /* This should be verified on older screamers */ @@ -1301,6 +1297,8 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) return 0; __error: + if (chip->pdev) + pci_dev_put(chip->pdev); snd_pmac_free(chip); return err; }