diff options
Diffstat (limited to 'kernel/compat.c')
-rw-r--r-- | kernel/compat.c | 53 |
1 files changed, 14 insertions, 39 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 32c254a8ab9a..72650e39b3e6 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/timex.h> | 23 | #include <linux/timex.h> |
24 | #include <linux/migrate.h> | 24 | #include <linux/migrate.h> |
25 | #include <linux/posix-timers.h> | 25 | #include <linux/posix-timers.h> |
26 | #include <linux/times.h> | ||
26 | 27 | ||
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
28 | 29 | ||
@@ -150,49 +151,23 @@ asmlinkage long compat_sys_setitimer(int which, | |||
150 | return 0; | 151 | return 0; |
151 | } | 152 | } |
152 | 153 | ||
154 | static compat_clock_t clock_t_to_compat_clock_t(clock_t x) | ||
155 | { | ||
156 | return compat_jiffies_to_clock_t(clock_t_to_jiffies(x)); | ||
157 | } | ||
158 | |||
153 | asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) | 159 | asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) |
154 | { | 160 | { |
155 | /* | ||
156 | * In the SMP world we might just be unlucky and have one of | ||
157 | * the times increment as we use it. Since the value is an | ||
158 | * atomically safe type this is just fine. Conceptually its | ||
159 | * as if the syscall took an instant longer to occur. | ||
160 | */ | ||
161 | if (tbuf) { | 161 | if (tbuf) { |
162 | struct tms tms; | ||
162 | struct compat_tms tmp; | 163 | struct compat_tms tmp; |
163 | struct task_struct *tsk = current; | 164 | |
164 | struct task_struct *t; | 165 | do_sys_times(&tms); |
165 | cputime_t utime, stime, cutime, cstime; | 166 | /* Convert our struct tms to the compat version. */ |
166 | 167 | tmp.tms_utime = clock_t_to_compat_clock_t(tms.tms_utime); | |
167 | read_lock(&tasklist_lock); | 168 | tmp.tms_stime = clock_t_to_compat_clock_t(tms.tms_stime); |
168 | utime = tsk->signal->utime; | 169 | tmp.tms_cutime = clock_t_to_compat_clock_t(tms.tms_cutime); |
169 | stime = tsk->signal->stime; | 170 | tmp.tms_cstime = clock_t_to_compat_clock_t(tms.tms_cstime); |
170 | t = tsk; | ||
171 | do { | ||
172 | utime = cputime_add(utime, t->utime); | ||
173 | stime = cputime_add(stime, t->stime); | ||
174 | t = next_thread(t); | ||
175 | } while (t != tsk); | ||
176 | |||
177 | /* | ||
178 | * While we have tasklist_lock read-locked, no dying thread | ||
179 | * can be updating current->signal->[us]time. Instead, | ||
180 | * we got their counts included in the live thread loop. | ||
181 | * However, another thread can come in right now and | ||
182 | * do a wait call that updates current->signal->c[us]time. | ||
183 | * To make sure we always see that pair updated atomically, | ||
184 | * we take the siglock around fetching them. | ||
185 | */ | ||
186 | spin_lock_irq(&tsk->sighand->siglock); | ||
187 | cutime = tsk->signal->cutime; | ||
188 | cstime = tsk->signal->cstime; | ||
189 | spin_unlock_irq(&tsk->sighand->siglock); | ||
190 | read_unlock(&tasklist_lock); | ||
191 | |||
192 | tmp.tms_utime = compat_jiffies_to_clock_t(cputime_to_jiffies(utime)); | ||
193 | tmp.tms_stime = compat_jiffies_to_clock_t(cputime_to_jiffies(stime)); | ||
194 | tmp.tms_cutime = compat_jiffies_to_clock_t(cputime_to_jiffies(cutime)); | ||
195 | tmp.tms_cstime = compat_jiffies_to_clock_t(cputime_to_jiffies(cstime)); | ||
196 | if (copy_to_user(tbuf, &tmp, sizeof(tmp))) | 171 | if (copy_to_user(tbuf, &tmp, sizeof(tmp))) |
197 | return -EFAULT; | 172 | return -EFAULT; |
198 | } | 173 | } |