diff options
Diffstat (limited to 'arch/arc/kernel/process.c')
-rw-r--r-- | arch/arc/kernel/process.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index be1972bd2729..59aa43cb146e 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c | |||
@@ -41,6 +41,39 @@ SYSCALL_DEFINE0(arc_gettls) | |||
41 | return task_thread_info(current)->thr_ptr; | 41 | return task_thread_info(current)->thr_ptr; |
42 | } | 42 | } |
43 | 43 | ||
44 | SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) | ||
45 | { | ||
46 | int uval; | ||
47 | int ret; | ||
48 | |||
49 | /* | ||
50 | * This is only for old cores lacking LLOCK/SCOND, which by defintion | ||
51 | * can't possibly be SMP. Thus doesn't need to be SMP safe. | ||
52 | * And this also helps reduce the overhead for serializing in | ||
53 | * the UP case | ||
54 | */ | ||
55 | WARN_ON_ONCE(IS_ENABLED(CONFIG_SMP)); | ||
56 | |||
57 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
58 | return -EFAULT; | ||
59 | |||
60 | preempt_disable(); | ||
61 | |||
62 | ret = __get_user(uval, uaddr); | ||
63 | if (ret) | ||
64 | goto done; | ||
65 | |||
66 | if (uval != expected) | ||
67 | ret = -EAGAIN; | ||
68 | else | ||
69 | ret = __put_user(new, uaddr); | ||
70 | |||
71 | done: | ||
72 | preempt_enable(); | ||
73 | |||
74 | return ret; | ||
75 | } | ||
76 | |||
44 | void arch_cpu_idle(void) | 77 | void arch_cpu_idle(void) |
45 | { | 78 | { |
46 | /* sleep, but enable all interrupts before committing */ | 79 | /* sleep, but enable all interrupts before committing */ |