summaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/osf_sys.c
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/osf_sys.c
parent3d0ceac129f3ea0b125289055a3aa7519d38df77 (diff)
downloadtalos-op-linux-3185bd26188223195dc2e659a3d00219cad71a0f.tar.gz
talos-op-linux-3185bd26188223195dc2e659a3d00219cad71a0f.zip
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/osf_sys.c')
-rw-r--r--arch/alpha/kernel/osf_sys.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 9eb090582cf1..1e6956a90608 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:
OpenPOWER on IntegriCloud