summaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel
diff options
context:
space:
mode:
authorAl Viro <viro@ZenIV.linux.org.uk>2012-10-20 15:52:23 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-24 05:16:45 +0300
commit3185bd26188223195dc2e659a3d00219cad71a0f (patch)
tree1363b0619f9e416b308aee3c804fab13e6efa72c /arch/alpha/kernel
parent3d0ceac129f3ea0b125289055a3aa7519d38df77 (diff)
alpha: separate thread-synchronous flags
... and fix the race in updating unaligned control ones Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/alpha/kernel')
-rw-r--r--arch/alpha/kernel/osf_sys.c25
-rw-r--r--arch/alpha/kernel/process.c2
-rw-r--r--arch/alpha/kernel/traps.c6
3 files changed, 14 insertions, 19 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 9eb090582cf..1e6956a9060 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -793,8 +793,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
case GSI_UACPROC:
if (nbytes < sizeof(unsigned int))
return -EINVAL;
- w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) &
- UAC_BITMASK;
+ w = current_thread_info()->status & UAC_BITMASK;
if (put_user(w, (unsigned int __user *)buffer))
return -EFAULT;
return 1;
@@ -904,24 +903,20 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
break;
case SSI_NVPAIRS: {
- unsigned long v, w, i;
- unsigned int old, new;
+ unsigned __user *p = buffer;
+ unsigned i;
- for (i = 0; i < nbytes; ++i) {
+ for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
+ unsigned v, w, status;
- if (get_user(v, 2*i + (unsigned int __user *)buffer))
- return -EFAULT;
- if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer))
+ if (get_user(v, p) || get_user(w, p + 1))
return -EFAULT;
switch (v) {
case SSIN_UACPROC:
- again:
- old = current_thread_info()->flags;
- new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT);
- new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT;
- if (cmpxchg(&current_thread_info()->flags,
- old, new) != old)
- goto again;
+ w &= UAC_BITMASK;
+ status = current_thread_info()->status;
+ status = (status & ~UAC_BITMASK) | w;
+ current_thread_info()->status = status;
break;
default:
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 4054e0ffe2b..51987dcf79b 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(pm_power_off);
void
cpu_idle(void)
{
- set_thread_flag(TIF_POLLING_NRFLAG);
+ current_thread_info()->status |= TS_POLLING;
while (1) {
/* FIXME -- EV6 and LCA45 know how to power down
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 80d987c0e9a..272666d006d 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -780,17 +780,17 @@ do_entUnaUser(void __user * va, unsigned long opcode,
/* Check the UAC bits to decide what the user wants us to do
with the unaliged access. */
- if (!test_thread_flag (TIF_UAC_NOPRINT)) {
+ if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
if (__ratelimit(&ratelimit)) {
printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
current->comm, task_pid_nr(current),
regs->pc - 4, va, opcode, reg);
}
}
- if (test_thread_flag (TIF_UAC_SIGBUS))
+ if ((current_thread_info()->status & TS_UAC_SIGBUS))
goto give_sigbus;
/* Not sure why you'd want to use this, but... */
- if (test_thread_flag (TIF_UAC_NOFIX))
+ if ((current_thread_info()->status & TS_UAC_NOFIX))
return;
/* Don't bother reading ds in the access check since we already