diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/futex.c | 42 | ||||
-rw-r--r-- | kernel/futex_compat.c | 3 | ||||
-rw-r--r-- | kernel/hrtimer.c | 2 | ||||
-rw-r--r-- | kernel/time.c | 1 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 2 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 6 | ||||
-rw-r--r-- | kernel/time/timer_list.c | 2 |
7 files changed, 45 insertions, 13 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index db9824de8bf0..a6baaec44b8f 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -109,6 +109,9 @@ struct futex_q { | |||
109 | /* Optional priority inheritance state: */ | 109 | /* Optional priority inheritance state: */ |
110 | struct futex_pi_state *pi_state; | 110 | struct futex_pi_state *pi_state; |
111 | struct task_struct *task; | 111 | struct task_struct *task; |
112 | |||
113 | /* Bitset for the optional bitmasked wakeup */ | ||
114 | u32 bitset; | ||
112 | }; | 115 | }; |
113 | 116 | ||
114 | /* | 117 | /* |
@@ -722,7 +725,7 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2) | |||
722 | * to this virtual address: | 725 | * to this virtual address: |
723 | */ | 726 | */ |
724 | static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, | 727 | static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, |
725 | int nr_wake) | 728 | int nr_wake, u32 bitset) |
726 | { | 729 | { |
727 | struct futex_hash_bucket *hb; | 730 | struct futex_hash_bucket *hb; |
728 | struct futex_q *this, *next; | 731 | struct futex_q *this, *next; |
@@ -730,6 +733,9 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
730 | union futex_key key; | 733 | union futex_key key; |
731 | int ret; | 734 | int ret; |
732 | 735 | ||
736 | if (!bitset) | ||
737 | return -EINVAL; | ||
738 | |||
733 | futex_lock_mm(fshared); | 739 | futex_lock_mm(fshared); |
734 | 740 | ||
735 | ret = get_futex_key(uaddr, fshared, &key); | 741 | ret = get_futex_key(uaddr, fshared, &key); |
@@ -746,6 +752,11 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
746 | ret = -EINVAL; | 752 | ret = -EINVAL; |
747 | break; | 753 | break; |
748 | } | 754 | } |
755 | |||
756 | /* Check if one of the bits is set in both bitsets */ | ||
757 | if (!(this->bitset & bitset)) | ||
758 | continue; | ||
759 | |||
749 | wake_futex(this); | 760 | wake_futex(this); |
750 | if (++ret >= nr_wake) | 761 | if (++ret >= nr_wake) |
751 | break; | 762 | break; |
@@ -1156,7 +1167,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, | |||
1156 | static long futex_wait_restart(struct restart_block *restart); | 1167 | static long futex_wait_restart(struct restart_block *restart); |
1157 | 1168 | ||
1158 | static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | 1169 | static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, |
1159 | u32 val, ktime_t *abs_time) | 1170 | u32 val, ktime_t *abs_time, u32 bitset) |
1160 | { | 1171 | { |
1161 | struct task_struct *curr = current; | 1172 | struct task_struct *curr = current; |
1162 | DECLARE_WAITQUEUE(wait, curr); | 1173 | DECLARE_WAITQUEUE(wait, curr); |
@@ -1167,7 +1178,11 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
1167 | struct hrtimer_sleeper t; | 1178 | struct hrtimer_sleeper t; |
1168 | int rem = 0; | 1179 | int rem = 0; |
1169 | 1180 | ||
1181 | if (!bitset) | ||
1182 | return -EINVAL; | ||
1183 | |||
1170 | q.pi_state = NULL; | 1184 | q.pi_state = NULL; |
1185 | q.bitset = bitset; | ||
1171 | retry: | 1186 | retry: |
1172 | futex_lock_mm(fshared); | 1187 | futex_lock_mm(fshared); |
1173 | 1188 | ||
@@ -1252,6 +1267,8 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
1252 | t.timer.expires = *abs_time; | 1267 | t.timer.expires = *abs_time; |
1253 | 1268 | ||
1254 | hrtimer_start(&t.timer, t.timer.expires, HRTIMER_MODE_ABS); | 1269 | hrtimer_start(&t.timer, t.timer.expires, HRTIMER_MODE_ABS); |
1270 | if (!hrtimer_active(&t.timer)) | ||
1271 | t.task = NULL; | ||
1255 | 1272 | ||
1256 | /* | 1273 | /* |
1257 | * the timer could have already expired, in which | 1274 | * the timer could have already expired, in which |
@@ -1293,6 +1310,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
1293 | restart->futex.uaddr = (u32 *)uaddr; | 1310 | restart->futex.uaddr = (u32 *)uaddr; |
1294 | restart->futex.val = val; | 1311 | restart->futex.val = val; |
1295 | restart->futex.time = abs_time->tv64; | 1312 | restart->futex.time = abs_time->tv64; |
1313 | restart->futex.bitset = bitset; | ||
1296 | restart->futex.flags = 0; | 1314 | restart->futex.flags = 0; |
1297 | 1315 | ||
1298 | if (fshared) | 1316 | if (fshared) |
@@ -1319,7 +1337,8 @@ static long futex_wait_restart(struct restart_block *restart) | |||
1319 | restart->fn = do_no_restart_syscall; | 1337 | restart->fn = do_no_restart_syscall; |
1320 | if (restart->futex.flags & FLAGS_SHARED) | 1338 | if (restart->futex.flags & FLAGS_SHARED) |
1321 | fshared = ¤t->mm->mmap_sem; | 1339 | fshared = ¤t->mm->mmap_sem; |
1322 | return (long)futex_wait(uaddr, fshared, restart->futex.val, &t); | 1340 | return (long)futex_wait(uaddr, fshared, restart->futex.val, &t, |
1341 | restart->futex.bitset); | ||
1323 | } | 1342 | } |
1324 | 1343 | ||
1325 | 1344 | ||
@@ -1535,9 +1554,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
1535 | owner = rt_mutex_owner(&q.pi_state->pi_mutex); | 1554 | owner = rt_mutex_owner(&q.pi_state->pi_mutex); |
1536 | res = fixup_pi_state_owner(uaddr, &q, owner); | 1555 | res = fixup_pi_state_owner(uaddr, &q, owner); |
1537 | 1556 | ||
1538 | WARN_ON(rt_mutex_owner(&q.pi_state->pi_mutex) != | ||
1539 | owner); | ||
1540 | |||
1541 | /* propagate -EFAULT, if the fixup failed */ | 1557 | /* propagate -EFAULT, if the fixup failed */ |
1542 | if (res) | 1558 | if (res) |
1543 | ret = res; | 1559 | ret = res; |
@@ -1943,7 +1959,8 @@ retry: | |||
1943 | * PI futexes happens in exit_pi_state(): | 1959 | * PI futexes happens in exit_pi_state(): |
1944 | */ | 1960 | */ |
1945 | if (!pi && (uval & FUTEX_WAITERS)) | 1961 | if (!pi && (uval & FUTEX_WAITERS)) |
1946 | futex_wake(uaddr, &curr->mm->mmap_sem, 1); | 1962 | futex_wake(uaddr, &curr->mm->mmap_sem, 1, |
1963 | FUTEX_BITSET_MATCH_ANY); | ||
1947 | } | 1964 | } |
1948 | return 0; | 1965 | return 0; |
1949 | } | 1966 | } |
@@ -2043,10 +2060,14 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, | |||
2043 | 2060 | ||
2044 | switch (cmd) { | 2061 | switch (cmd) { |
2045 | case FUTEX_WAIT: | 2062 | case FUTEX_WAIT: |
2046 | ret = futex_wait(uaddr, fshared, val, timeout); | 2063 | val3 = FUTEX_BITSET_MATCH_ANY; |
2064 | case FUTEX_WAIT_BITSET: | ||
2065 | ret = futex_wait(uaddr, fshared, val, timeout, val3); | ||
2047 | break; | 2066 | break; |
2048 | case FUTEX_WAKE: | 2067 | case FUTEX_WAKE: |
2049 | ret = futex_wake(uaddr, fshared, val); | 2068 | val3 = FUTEX_BITSET_MATCH_ANY; |
2069 | case FUTEX_WAKE_BITSET: | ||
2070 | ret = futex_wake(uaddr, fshared, val, val3); | ||
2050 | break; | 2071 | break; |
2051 | case FUTEX_FD: | 2072 | case FUTEX_FD: |
2052 | /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */ | 2073 | /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */ |
@@ -2086,7 +2107,8 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, | |||
2086 | u32 val2 = 0; | 2107 | u32 val2 = 0; |
2087 | int cmd = op & FUTEX_CMD_MASK; | 2108 | int cmd = op & FUTEX_CMD_MASK; |
2088 | 2109 | ||
2089 | if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) { | 2110 | if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || |
2111 | cmd == FUTEX_WAIT_BITSET)) { | ||
2090 | if (copy_from_user(&ts, utime, sizeof(ts)) != 0) | 2112 | if (copy_from_user(&ts, utime, sizeof(ts)) != 0) |
2091 | return -EFAULT; | 2113 | return -EFAULT; |
2092 | if (!timespec_valid(&ts)) | 2114 | if (!timespec_valid(&ts)) |
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 0a43def6fee7..133d558db452 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c | |||
@@ -167,7 +167,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, | |||
167 | int val2 = 0; | 167 | int val2 = 0; |
168 | int cmd = op & FUTEX_CMD_MASK; | 168 | int cmd = op & FUTEX_CMD_MASK; |
169 | 169 | ||
170 | if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) { | 170 | if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || |
171 | cmd == FUTEX_WAIT_BITSET)) { | ||
171 | if (get_compat_timespec(&ts, utime)) | 172 | if (get_compat_timespec(&ts, utime)) |
172 | return -EFAULT; | 173 | return -EFAULT; |
173 | if (!timespec_valid(&ts)) | 174 | if (!timespec_valid(&ts)) |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index bd5d6b5060bc..1069998fe25f 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -1315,6 +1315,8 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod | |||
1315 | 1315 | ||
1316 | } while (t->task && !signal_pending(current)); | 1316 | } while (t->task && !signal_pending(current)); |
1317 | 1317 | ||
1318 | __set_current_state(TASK_RUNNING); | ||
1319 | |||
1318 | return t->task == NULL; | 1320 | return t->task == NULL; |
1319 | } | 1321 | } |
1320 | 1322 | ||
diff --git a/kernel/time.c b/kernel/time.c index 09d3c45c4da7..4064c0566e77 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
@@ -129,6 +129,7 @@ static inline void warp_clock(void) | |||
129 | write_seqlock_irq(&xtime_lock); | 129 | write_seqlock_irq(&xtime_lock); |
130 | wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60; | 130 | wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60; |
131 | xtime.tv_sec += sys_tz.tz_minuteswest * 60; | 131 | xtime.tv_sec += sys_tz.tz_minuteswest * 60; |
132 | update_xtime_cache(0); | ||
132 | write_sequnlock_irq(&xtime_lock); | 133 | write_sequnlock_irq(&xtime_lock); |
133 | clock_was_set(); | 134 | clock_was_set(); |
134 | } | 135 | } |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 63f24b550695..88267f0a8471 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -137,6 +137,7 @@ void tick_nohz_update_jiffies(void) | |||
137 | 137 | ||
138 | cpu_clear(cpu, nohz_cpu_mask); | 138 | cpu_clear(cpu, nohz_cpu_mask); |
139 | now = ktime_get(); | 139 | now = ktime_get(); |
140 | ts->idle_waketime = now; | ||
140 | 141 | ||
141 | local_irq_save(flags); | 142 | local_irq_save(flags); |
142 | tick_do_update_jiffies64(now); | 143 | tick_do_update_jiffies64(now); |
@@ -400,6 +401,7 @@ void tick_nohz_restart_sched_tick(void) | |||
400 | * Cancel the scheduled timer and restore the tick | 401 | * Cancel the scheduled timer and restore the tick |
401 | */ | 402 | */ |
402 | ts->tick_stopped = 0; | 403 | ts->tick_stopped = 0; |
404 | ts->idle_exittime = now; | ||
403 | hrtimer_cancel(&ts->sched_timer); | 405 | hrtimer_cancel(&ts->sched_timer); |
404 | ts->sched_timer.expires = ts->idle_tick; | 406 | ts->sched_timer.expires = ts->idle_tick; |
405 | 407 | ||
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 092a2366b5a9..cd5dbc4579c9 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -47,7 +47,7 @@ struct timespec wall_to_monotonic __attribute__ ((aligned (16))); | |||
47 | static unsigned long total_sleep_time; /* seconds */ | 47 | static unsigned long total_sleep_time; /* seconds */ |
48 | 48 | ||
49 | static struct timespec xtime_cache __attribute__ ((aligned (16))); | 49 | static struct timespec xtime_cache __attribute__ ((aligned (16))); |
50 | static inline void update_xtime_cache(u64 nsec) | 50 | void update_xtime_cache(u64 nsec) |
51 | { | 51 | { |
52 | xtime_cache = xtime; | 52 | xtime_cache = xtime; |
53 | timespec_add_ns(&xtime_cache, nsec); | 53 | timespec_add_ns(&xtime_cache, nsec); |
@@ -145,6 +145,7 @@ int do_settimeofday(struct timespec *tv) | |||
145 | 145 | ||
146 | set_normalized_timespec(&xtime, sec, nsec); | 146 | set_normalized_timespec(&xtime, sec, nsec); |
147 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); | 147 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); |
148 | update_xtime_cache(0); | ||
148 | 149 | ||
149 | clock->error = 0; | 150 | clock->error = 0; |
150 | ntp_clear(); | 151 | ntp_clear(); |
@@ -252,8 +253,8 @@ void __init timekeeping_init(void) | |||
252 | xtime.tv_nsec = 0; | 253 | xtime.tv_nsec = 0; |
253 | set_normalized_timespec(&wall_to_monotonic, | 254 | set_normalized_timespec(&wall_to_monotonic, |
254 | -xtime.tv_sec, -xtime.tv_nsec); | 255 | -xtime.tv_sec, -xtime.tv_nsec); |
256 | update_xtime_cache(0); | ||
255 | total_sleep_time = 0; | 257 | total_sleep_time = 0; |
256 | |||
257 | write_sequnlock_irqrestore(&xtime_lock, flags); | 258 | write_sequnlock_irqrestore(&xtime_lock, flags); |
258 | } | 259 | } |
259 | 260 | ||
@@ -290,6 +291,7 @@ static int timekeeping_resume(struct sys_device *dev) | |||
290 | } | 291 | } |
291 | /* Make sure that we have the correct xtime reference */ | 292 | /* Make sure that we have the correct xtime reference */ |
292 | timespec_add_ns(&xtime, timekeeping_suspend_nsecs); | 293 | timespec_add_ns(&xtime, timekeeping_suspend_nsecs); |
294 | update_xtime_cache(0); | ||
293 | /* re-base the last cycle value */ | 295 | /* re-base the last cycle value */ |
294 | clock->cycle_last = clocksource_read(clock); | 296 | clock->cycle_last = clocksource_read(clock); |
295 | clock->error = 0; | 297 | clock->error = 0; |
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 12c5f4cb6b8c..d3d94c1a0fd2 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c | |||
@@ -166,6 +166,8 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now) | |||
166 | P(idle_calls); | 166 | P(idle_calls); |
167 | P(idle_sleeps); | 167 | P(idle_sleeps); |
168 | P_ns(idle_entrytime); | 168 | P_ns(idle_entrytime); |
169 | P_ns(idle_waketime); | ||
170 | P_ns(idle_exittime); | ||
169 | P_ns(idle_sleeptime); | 171 | P_ns(idle_sleeptime); |
170 | P(last_jiffies); | 172 | P(last_jiffies); |
171 | P(next_jiffies); | 173 | P(next_jiffies); |