diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-02 19:50:39 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-02 19:50:39 -0400 |
| commit | ce6eba3dba366b607c0a363c7cdbd4ee8fcc6434 (patch) | |
| tree | 7e8bb291ce843457c52659dfa4a5d14444c91c35 | |
| parent | a5532439ebab93e47784effb96aafa7d7ba4b760 (diff) | |
| parent | b3fc5c9bb373661224906bf434c09ca0de032e82 (diff) | |
Merge branch 'sched-wait-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull wait_var_event updates from Ingo Molnar:
"This introduces the new wait_var_event() API, which is a more flexible
waiting primitive than wait_on_atomic_t().
All wait_on_atomic_t() users are migrated over to the new API and
wait_on_atomic_t() is removed. The migration fixes one bug and should
result in no functional changes for the other usecases"
* 'sched-wait-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
sched/wait: Improve __var_waitqueue() code generation
sched/wait: Remove the wait_on_atomic_t() API
sched/wait, arch/mips: Fix and convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait, fs/ocfs2: Convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait, fs/nfs: Convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait, fs/fscache: Convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait, fs/btrfs: Convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait, fs/afs: Convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait, drivers/media: Convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait, drivers/drm: Convert wait_on_atomic_t() usage to the new wait_var_event() API
sched/wait: Introduce wait_var_event()
| -rw-r--r-- | arch/mips/kernel/process.c | 2 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_dp_aux_dev.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 14 | ||||
| -rw-r--r-- | drivers/media/platform/qcom/venus/hfi.c | 8 | ||||
| -rw-r--r-- | fs/afs/cell.c | 6 | ||||
| -rw-r--r-- | fs/afs/rxrpc.c | 6 | ||||
| -rw-r--r-- | fs/afs/server.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 14 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 2 | ||||
| -rw-r--r-- | fs/fscache/cookie.c | 7 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 5 | ||||
| -rw-r--r-- | fs/nfs/pagelist.c | 6 | ||||
| -rw-r--r-- | fs/nfs/pnfs_nfs.c | 2 | ||||
| -rw-r--r-- | fs/nfs/write.c | 6 | ||||
| -rw-r--r-- | fs/ocfs2/filecheck.c | 9 | ||||
| -rw-r--r-- | include/linux/fscache-cache.h | 2 | ||||
| -rw-r--r-- | include/linux/wait_bit.h | 95 | ||||
| -rw-r--r-- | kernel/sched/wait_bit.c | 110 |
19 files changed, 147 insertions, 170 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 57028d49c202..b9e9bf628849 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
| @@ -781,6 +781,8 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) | |||
| 781 | atomic_set(&task->mm->context.fp_mode_switching, 0); | 781 | atomic_set(&task->mm->context.fp_mode_switching, 0); |
| 782 | preempt_enable(); | 782 | preempt_enable(); |
| 783 | 783 | ||
| 784 | wake_up_var(&task->mm->context.fp_mode_switching); | ||
| 785 | |||
| 784 | return 0; | 786 | return 0; |
| 785 | } | 787 | } |
| 786 | 788 | ||
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 0ae4a731cc12..967e9e4e795e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -1248,8 +1248,8 @@ static int enable_restore_fp_context(int msa) | |||
| 1248 | * If an FP mode switch is currently underway, wait for it to | 1248 | * If an FP mode switch is currently underway, wait for it to |
| 1249 | * complete before proceeding. | 1249 | * complete before proceeding. |
| 1250 | */ | 1250 | */ |
| 1251 | wait_on_atomic_t(¤t->mm->context.fp_mode_switching, | 1251 | wait_var_event(¤t->mm->context.fp_mode_switching, |
| 1252 | atomic_t_wait, TASK_KILLABLE); | 1252 | !atomic_read(¤t->mm->context.fp_mode_switching)); |
| 1253 | 1253 | ||
| 1254 | if (!used_math()) { | 1254 | if (!used_math()) { |
| 1255 | /* First time FP context user. */ | 1255 | /* First time FP context user. */ |
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c index 053044201e31..0e4f25d63fd2 100644 --- a/drivers/gpu/drm/drm_dp_aux_dev.c +++ b/drivers/gpu/drm/drm_dp_aux_dev.c | |||
| @@ -177,8 +177,9 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to) | |||
| 177 | res = pos - iocb->ki_pos; | 177 | res = pos - iocb->ki_pos; |
| 178 | iocb->ki_pos = pos; | 178 | iocb->ki_pos = pos; |
| 179 | 179 | ||
| 180 | atomic_dec(&aux_dev->usecount); | 180 | if (atomic_dec_and_test(&aux_dev->usecount)) |
| 181 | wake_up_atomic_t(&aux_dev->usecount); | 181 | wake_up_var(&aux_dev->usecount); |
| 182 | |||
| 182 | return res; | 183 | return res; |
| 183 | } | 184 | } |
| 184 | 185 | ||
| @@ -218,8 +219,9 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 218 | res = pos - iocb->ki_pos; | 219 | res = pos - iocb->ki_pos; |
| 219 | iocb->ki_pos = pos; | 220 | iocb->ki_pos = pos; |
| 220 | 221 | ||
| 221 | atomic_dec(&aux_dev->usecount); | 222 | if (atomic_dec_and_test(&aux_dev->usecount)) |
| 222 | wake_up_atomic_t(&aux_dev->usecount); | 223 | wake_up_var(&aux_dev->usecount); |
| 224 | |||
| 223 | return res; | 225 | return res; |
| 224 | } | 226 | } |
| 225 | 227 | ||
| @@ -277,8 +279,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) | |||
| 277 | mutex_unlock(&aux_idr_mutex); | 279 | mutex_unlock(&aux_idr_mutex); |
| 278 | 280 | ||
| 279 | atomic_dec(&aux_dev->usecount); | 281 | atomic_dec(&aux_dev->usecount); |
| 280 | wait_on_atomic_t(&aux_dev->usecount, atomic_t_wait, | 282 | wait_var_event(&aux_dev->usecount, !atomic_read(&aux_dev->usecount)); |
| 281 | TASK_UNINTERRUPTIBLE); | ||
| 282 | 283 | ||
| 283 | minor = aux_dev->index; | 284 | minor = aux_dev->index; |
| 284 | if (aux_dev->dev) | 285 | if (aux_dev->dev) |
diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c index 54fc571b1102..46580026c7fc 100644 --- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | |||
| @@ -271,18 +271,13 @@ struct igt_wakeup { | |||
| 271 | u32 seqno; | 271 | u32 seqno; |
| 272 | }; | 272 | }; |
| 273 | 273 | ||
| 274 | static int wait_atomic_timeout(atomic_t *p, unsigned int mode) | ||
| 275 | { | ||
| 276 | return schedule_timeout(10 * HZ) ? 0 : -ETIMEDOUT; | ||
| 277 | } | ||
| 278 | |||
| 279 | static bool wait_for_ready(struct igt_wakeup *w) | 274 | static bool wait_for_ready(struct igt_wakeup *w) |
| 280 | { | 275 | { |
| 281 | DEFINE_WAIT(ready); | 276 | DEFINE_WAIT(ready); |
| 282 | 277 | ||
| 283 | set_bit(IDLE, &w->flags); | 278 | set_bit(IDLE, &w->flags); |
| 284 | if (atomic_dec_and_test(w->done)) | 279 | if (atomic_dec_and_test(w->done)) |
| 285 | wake_up_atomic_t(w->done); | 280 | wake_up_var(w->done); |
| 286 | 281 | ||
| 287 | if (test_bit(STOP, &w->flags)) | 282 | if (test_bit(STOP, &w->flags)) |
| 288 | goto out; | 283 | goto out; |
| @@ -299,7 +294,7 @@ static bool wait_for_ready(struct igt_wakeup *w) | |||
| 299 | out: | 294 | out: |
| 300 | clear_bit(IDLE, &w->flags); | 295 | clear_bit(IDLE, &w->flags); |
| 301 | if (atomic_dec_and_test(w->set)) | 296 | if (atomic_dec_and_test(w->set)) |
| 302 | wake_up_atomic_t(w->set); | 297 | wake_up_var(w->set); |
| 303 | 298 | ||
| 304 | return !test_bit(STOP, &w->flags); | 299 | return !test_bit(STOP, &w->flags); |
| 305 | } | 300 | } |
| @@ -342,7 +337,7 @@ static void igt_wake_all_sync(atomic_t *ready, | |||
| 342 | atomic_set(ready, 0); | 337 | atomic_set(ready, 0); |
| 343 | wake_up_all(wq); | 338 | wake_up_all(wq); |
| 344 | 339 | ||
| 345 | wait_on_atomic_t(set, atomic_t_wait, TASK_UNINTERRUPTIBLE); | 340 | wait_var_event(set, !atomic_read(set)); |
| 346 | atomic_set(ready, count); | 341 | atomic_set(ready, count); |
| 347 | atomic_set(done, count); | 342 | atomic_set(done, count); |
| 348 | } | 343 | } |
| @@ -350,7 +345,6 @@ static void igt_wake_all_sync(atomic_t *ready, | |||
| 350 | static int igt_wakeup(void *arg) | 345 | static int igt_wakeup(void *arg) |
| 351 | { | 346 | { |
| 352 | I915_RND_STATE(prng); | 347 | I915_RND_STATE(prng); |
| 353 | const int state = TASK_UNINTERRUPTIBLE; | ||
| 354 | struct intel_engine_cs *engine = arg; | 348 | struct intel_engine_cs *engine = arg; |
| 355 | struct igt_wakeup *waiters; | 349 | struct igt_wakeup *waiters; |
| 356 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); | 350 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); |
| @@ -418,7 +412,7 @@ static int igt_wakeup(void *arg) | |||
| 418 | * that they are ready for the next test. We wait until all | 412 | * that they are ready for the next test. We wait until all |
| 419 | * threads are complete and waiting for us (i.e. not a seqno). | 413 | * threads are complete and waiting for us (i.e. not a seqno). |
| 420 | */ | 414 | */ |
| 421 | err = wait_on_atomic_t(&done, wait_atomic_timeout, state); | 415 | err = wait_var_event_timeout(&done, !atomic_read(&done), 10 * HZ); |
| 422 | if (err) { | 416 | if (err) { |
| 423 | pr_err("Timed out waiting for %d remaining waiters\n", | 417 | pr_err("Timed out waiting for %d remaining waiters\n", |
| 424 | atomic_read(&done)); | 418 | atomic_read(&done)); |
diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index 1baf78d3c02d..bca894a00c07 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c | |||
| @@ -106,8 +106,8 @@ int hfi_core_deinit(struct venus_core *core, bool blocking) | |||
| 106 | 106 | ||
| 107 | if (!empty) { | 107 | if (!empty) { |
| 108 | mutex_unlock(&core->lock); | 108 | mutex_unlock(&core->lock); |
| 109 | wait_on_atomic_t(&core->insts_count, atomic_t_wait, | 109 | wait_var_event(&core->insts_count, |
| 110 | TASK_UNINTERRUPTIBLE); | 110 | !atomic_read(&core->insts_count)); |
| 111 | mutex_lock(&core->lock); | 111 | mutex_lock(&core->lock); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| @@ -229,8 +229,8 @@ void hfi_session_destroy(struct venus_inst *inst) | |||
| 229 | 229 | ||
| 230 | mutex_lock(&core->lock); | 230 | mutex_lock(&core->lock); |
| 231 | list_del_init(&inst->list); | 231 | list_del_init(&inst->list); |
| 232 | atomic_dec(&core->insts_count); | 232 | if (atomic_dec_and_test(&core->insts_count)) |
| 233 | wake_up_atomic_t(&core->insts_count); | 233 | wake_up_var(&core->insts_count); |
| 234 | mutex_unlock(&core->lock); | 234 | mutex_unlock(&core->lock); |
| 235 | } | 235 | } |
| 236 | EXPORT_SYMBOL_GPL(hfi_session_destroy); | 236 | EXPORT_SYMBOL_GPL(hfi_session_destroy); |
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 9bb921d120d0..3d2c5e0e854e 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
| @@ -25,7 +25,7 @@ static void afs_manage_cell(struct work_struct *); | |||
| 25 | static void afs_dec_cells_outstanding(struct afs_net *net) | 25 | static void afs_dec_cells_outstanding(struct afs_net *net) |
| 26 | { | 26 | { |
| 27 | if (atomic_dec_and_test(&net->cells_outstanding)) | 27 | if (atomic_dec_and_test(&net->cells_outstanding)) |
| 28 | wake_up_atomic_t(&net->cells_outstanding); | 28 | wake_up_var(&net->cells_outstanding); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | /* | 31 | /* |
| @@ -764,7 +764,7 @@ void afs_cell_purge(struct afs_net *net) | |||
| 764 | afs_queue_cell_manager(net); | 764 | afs_queue_cell_manager(net); |
| 765 | 765 | ||
| 766 | _debug("wait"); | 766 | _debug("wait"); |
| 767 | wait_on_atomic_t(&net->cells_outstanding, atomic_t_wait, | 767 | wait_var_event(&net->cells_outstanding, |
| 768 | TASK_UNINTERRUPTIBLE); | 768 | !atomic_read(&net->cells_outstanding)); |
| 769 | _leave(""); | 769 | _leave(""); |
| 770 | } | 770 | } |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index e1126659f043..e613dd754383 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
| @@ -103,8 +103,8 @@ void afs_close_socket(struct afs_net *net) | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | _debug("outstanding %u", atomic_read(&net->nr_outstanding_calls)); | 105 | _debug("outstanding %u", atomic_read(&net->nr_outstanding_calls)); |
| 106 | wait_on_atomic_t(&net->nr_outstanding_calls, atomic_t_wait, | 106 | wait_var_event(&net->nr_outstanding_calls, |
| 107 | TASK_UNINTERRUPTIBLE); | 107 | !atomic_read(&net->nr_outstanding_calls)); |
| 108 | _debug("no outstanding calls"); | 108 | _debug("no outstanding calls"); |
| 109 | 109 | ||
| 110 | kernel_sock_shutdown(net->socket, SHUT_RDWR); | 110 | kernel_sock_shutdown(net->socket, SHUT_RDWR); |
| @@ -175,7 +175,7 @@ void afs_put_call(struct afs_call *call) | |||
| 175 | trace_afs_call(call, afs_call_trace_free, 0, o, | 175 | trace_afs_call(call, afs_call_trace_free, 0, o, |
| 176 | __builtin_return_address(0)); | 176 | __builtin_return_address(0)); |
| 177 | if (o == 0) | 177 | if (o == 0) |
| 178 | wake_up_atomic_t(&net->nr_outstanding_calls); | 178 | wake_up_var(&net->nr_outstanding_calls); |
| 179 | } | 179 | } |
| 180 | } | 180 | } |
| 181 | 181 | ||
diff --git a/fs/afs/server.c b/fs/afs/server.c index 1880f1b6a9f1..a43ef77dabae 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c | |||
| @@ -25,7 +25,7 @@ static void afs_inc_servers_outstanding(struct afs_net *net) | |||
| 25 | static void afs_dec_servers_outstanding(struct afs_net *net) | 25 | static void afs_dec_servers_outstanding(struct afs_net *net) |
| 26 | { | 26 | { |
| 27 | if (atomic_dec_and_test(&net->servers_outstanding)) | 27 | if (atomic_dec_and_test(&net->servers_outstanding)) |
| 28 | wake_up_atomic_t(&net->servers_outstanding); | 28 | wake_up_var(&net->servers_outstanding); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | /* | 31 | /* |
| @@ -521,8 +521,8 @@ void afs_purge_servers(struct afs_net *net) | |||
| 521 | afs_queue_server_manager(net); | 521 | afs_queue_server_manager(net); |
| 522 | 522 | ||
| 523 | _debug("wait"); | 523 | _debug("wait"); |
| 524 | wait_on_atomic_t(&net->servers_outstanding, atomic_t_wait, | 524 | wait_var_event(&net->servers_outstanding, |
| 525 | TASK_UNINTERRUPTIBLE); | 525 | !atomic_read(&net->servers_outstanding)); |
| 526 | _leave(""); | 526 | _leave(""); |
| 527 | } | 527 | } |
| 528 | 528 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c1618ab9fecf..e0460d7b5622 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3990,7 +3990,7 @@ void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) | |||
| 3990 | bg = btrfs_lookup_block_group(fs_info, bytenr); | 3990 | bg = btrfs_lookup_block_group(fs_info, bytenr); |
| 3991 | ASSERT(bg); | 3991 | ASSERT(bg); |
| 3992 | if (atomic_dec_and_test(&bg->nocow_writers)) | 3992 | if (atomic_dec_and_test(&bg->nocow_writers)) |
| 3993 | wake_up_atomic_t(&bg->nocow_writers); | 3993 | wake_up_var(&bg->nocow_writers); |
| 3994 | /* | 3994 | /* |
| 3995 | * Once for our lookup and once for the lookup done by a previous call | 3995 | * Once for our lookup and once for the lookup done by a previous call |
| 3996 | * to btrfs_inc_nocow_writers() | 3996 | * to btrfs_inc_nocow_writers() |
| @@ -4001,8 +4001,7 @@ void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) | |||
| 4001 | 4001 | ||
| 4002 | void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg) | 4002 | void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg) |
| 4003 | { | 4003 | { |
| 4004 | wait_on_atomic_t(&bg->nocow_writers, atomic_t_wait, | 4004 | wait_var_event(&bg->nocow_writers, !atomic_read(&bg->nocow_writers)); |
| 4005 | TASK_UNINTERRUPTIBLE); | ||
| 4006 | } | 4005 | } |
| 4007 | 4006 | ||
| 4008 | static const char *alloc_name(u64 flags) | 4007 | static const char *alloc_name(u64 flags) |
| @@ -6526,7 +6525,7 @@ void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, | |||
| 6526 | bg = btrfs_lookup_block_group(fs_info, start); | 6525 | bg = btrfs_lookup_block_group(fs_info, start); |
| 6527 | ASSERT(bg); | 6526 | ASSERT(bg); |
| 6528 | if (atomic_dec_and_test(&bg->reservations)) | 6527 | if (atomic_dec_and_test(&bg->reservations)) |
| 6529 | wake_up_atomic_t(&bg->reservations); | 6528 | wake_up_var(&bg->reservations); |
| 6530 | btrfs_put_block_group(bg); | 6529 | btrfs_put_block_group(bg); |
| 6531 | } | 6530 | } |
| 6532 | 6531 | ||
| @@ -6552,8 +6551,7 @@ void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg) | |||
| 6552 | down_write(&space_info->groups_sem); | 6551 | down_write(&space_info->groups_sem); |
| 6553 | up_write(&space_info->groups_sem); | 6552 | up_write(&space_info->groups_sem); |
| 6554 | 6553 | ||
| 6555 | wait_on_atomic_t(&bg->reservations, atomic_t_wait, | 6554 | wait_var_event(&bg->reservations, !atomic_read(&bg->reservations)); |
| 6556 | TASK_UNINTERRUPTIBLE); | ||
| 6557 | } | 6555 | } |
| 6558 | 6556 | ||
| 6559 | /** | 6557 | /** |
| @@ -11061,7 +11059,7 @@ void btrfs_wait_for_snapshot_creation(struct btrfs_root *root) | |||
| 11061 | ret = btrfs_start_write_no_snapshotting(root); | 11059 | ret = btrfs_start_write_no_snapshotting(root); |
| 11062 | if (ret) | 11060 | if (ret) |
| 11063 | break; | 11061 | break; |
| 11064 | wait_on_atomic_t(&root->will_be_snapshotted, atomic_t_wait, | 11062 | wait_var_event(&root->will_be_snapshotted, |
| 11065 | TASK_UNINTERRUPTIBLE); | 11063 | !atomic_read(&root->will_be_snapshotted)); |
| 11066 | } | 11064 | } |
| 11067 | } | 11065 | } |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 111ee282b777..3278ae592a2c 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -723,7 +723,7 @@ fail: | |||
| 723 | btrfs_subvolume_release_metadata(fs_info, &pending_snapshot->block_rsv); | 723 | btrfs_subvolume_release_metadata(fs_info, &pending_snapshot->block_rsv); |
| 724 | dec_and_free: | 724 | dec_and_free: |
| 725 | if (atomic_dec_and_test(&root->will_be_snapshotted)) | 725 | if (atomic_dec_and_test(&root->will_be_snapshotted)) |
| 726 | wake_up_atomic_t(&root->will_be_snapshotted); | 726 | wake_up_var(&root->will_be_snapshotted); |
| 727 | free_pending: | 727 | free_pending: |
| 728 | kfree(pending_snapshot->root_item); | 728 | kfree(pending_snapshot->root_item); |
| 729 | btrfs_free_path(pending_snapshot->path); | 729 | btrfs_free_path(pending_snapshot->path); |
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index ff84258132bb..d705125665f0 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c | |||
| @@ -557,9 +557,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) | |||
| 557 | * n_active reaches 0). This makes sure outstanding reads and writes | 557 | * n_active reaches 0). This makes sure outstanding reads and writes |
| 558 | * have completed. | 558 | * have completed. |
| 559 | */ | 559 | */ |
| 560 | if (!atomic_dec_and_test(&cookie->n_active)) | 560 | if (!atomic_dec_and_test(&cookie->n_active)) { |
| 561 | wait_on_atomic_t(&cookie->n_active, atomic_t_wait, | 561 | wait_var_event(&cookie->n_active, |
| 562 | TASK_UNINTERRUPTIBLE); | 562 | !atomic_read(&cookie->n_active)); |
| 563 | } | ||
| 563 | 564 | ||
| 564 | /* Make sure any pending writes are cancelled. */ | 565 | /* Make sure any pending writes are cancelled. */ |
| 565 | if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) | 566 | if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 7d893543cf3b..d17a90c4fa37 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -85,11 +85,6 @@ int nfs_wait_bit_killable(struct wait_bit_key *key, int mode) | |||
| 85 | } | 85 | } |
| 86 | EXPORT_SYMBOL_GPL(nfs_wait_bit_killable); | 86 | EXPORT_SYMBOL_GPL(nfs_wait_bit_killable); |
| 87 | 87 | ||
| 88 | int nfs_wait_atomic_killable(atomic_t *p, unsigned int mode) | ||
| 89 | { | ||
| 90 | return nfs_wait_killable(mode); | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | 88 | /** |
| 94 | * nfs_compat_user_ino64 - returns the user-visible inode number | 89 | * nfs_compat_user_ino64 - returns the user-visible inode number |
| 95 | * @fileid: 64-bit fileid | 90 | * @fileid: 64-bit fileid |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 18a7626ac638..67d19cd92e44 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
| @@ -98,8 +98,8 @@ nfs_page_free(struct nfs_page *p) | |||
| 98 | int | 98 | int |
| 99 | nfs_iocounter_wait(struct nfs_lock_context *l_ctx) | 99 | nfs_iocounter_wait(struct nfs_lock_context *l_ctx) |
| 100 | { | 100 | { |
| 101 | return wait_on_atomic_t(&l_ctx->io_count, nfs_wait_atomic_killable, | 101 | return wait_var_event_killable(&l_ctx->io_count, |
| 102 | TASK_KILLABLE); | 102 | !atomic_read(&l_ctx->io_count)); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | /** | 105 | /** |
| @@ -395,7 +395,7 @@ static void nfs_clear_request(struct nfs_page *req) | |||
| 395 | } | 395 | } |
| 396 | if (l_ctx != NULL) { | 396 | if (l_ctx != NULL) { |
| 397 | if (atomic_dec_and_test(&l_ctx->io_count)) { | 397 | if (atomic_dec_and_test(&l_ctx->io_count)) { |
| 398 | wake_up_atomic_t(&l_ctx->io_count); | 398 | wake_up_var(&l_ctx->io_count); |
| 399 | if (test_bit(NFS_CONTEXT_UNLOCK, &ctx->flags)) | 399 | if (test_bit(NFS_CONTEXT_UNLOCK, &ctx->flags)) |
| 400 | rpc_wake_up(&NFS_SERVER(d_inode(ctx->dentry))->uoc_rpcwaitq); | 400 | rpc_wake_up(&NFS_SERVER(d_inode(ctx->dentry))->uoc_rpcwaitq); |
| 401 | } | 401 | } |
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index 03aaa60c7768..32ba2d471853 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
| @@ -245,7 +245,7 @@ pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, | |||
| 245 | { | 245 | { |
| 246 | if (list_empty(pages)) { | 246 | if (list_empty(pages)) { |
| 247 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) | 247 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) |
| 248 | wake_up_atomic_t(&cinfo->mds->rpcs_out); | 248 | wake_up_var(&cinfo->mds->rpcs_out); |
| 249 | /* don't call nfs_commitdata_release - it tries to put | 249 | /* don't call nfs_commitdata_release - it tries to put |
| 250 | * the open_context which is not acquired until nfs_init_commit | 250 | * the open_context which is not acquired until nfs_init_commit |
| 251 | * which has not been called on @data */ | 251 | * which has not been called on @data */ |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e7d8ceae8f26..6579f3b367bd 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -1620,8 +1620,8 @@ static void nfs_writeback_result(struct rpc_task *task, | |||
| 1620 | 1620 | ||
| 1621 | static int wait_on_commit(struct nfs_mds_commit_info *cinfo) | 1621 | static int wait_on_commit(struct nfs_mds_commit_info *cinfo) |
| 1622 | { | 1622 | { |
| 1623 | return wait_on_atomic_t(&cinfo->rpcs_out, | 1623 | return wait_var_event_killable(&cinfo->rpcs_out, |
| 1624 | nfs_wait_atomic_killable, TASK_KILLABLE); | 1624 | !atomic_read(&cinfo->rpcs_out)); |
| 1625 | } | 1625 | } |
| 1626 | 1626 | ||
| 1627 | static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo) | 1627 | static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo) |
| @@ -1632,7 +1632,7 @@ static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo) | |||
| 1632 | static void nfs_commit_end(struct nfs_mds_commit_info *cinfo) | 1632 | static void nfs_commit_end(struct nfs_mds_commit_info *cinfo) |
| 1633 | { | 1633 | { |
| 1634 | if (atomic_dec_and_test(&cinfo->rpcs_out)) | 1634 | if (atomic_dec_and_test(&cinfo->rpcs_out)) |
| 1635 | wake_up_atomic_t(&cinfo->rpcs_out); | 1635 | wake_up_var(&cinfo->rpcs_out); |
| 1636 | } | 1636 | } |
| 1637 | 1637 | ||
| 1638 | void nfs_commitdata_release(struct nfs_commit_data *data) | 1638 | void nfs_commitdata_release(struct nfs_commit_data *data) |
diff --git a/fs/ocfs2/filecheck.c b/fs/ocfs2/filecheck.c index e87279e49ba3..6b92cb241138 100644 --- a/fs/ocfs2/filecheck.c +++ b/fs/ocfs2/filecheck.c | |||
| @@ -134,9 +134,10 @@ ocfs2_filecheck_sysfs_free(struct ocfs2_filecheck_sysfs_entry *entry) | |||
| 134 | { | 134 | { |
| 135 | struct ocfs2_filecheck_entry *p; | 135 | struct ocfs2_filecheck_entry *p; |
| 136 | 136 | ||
| 137 | if (!atomic_dec_and_test(&entry->fs_count)) | 137 | if (!atomic_dec_and_test(&entry->fs_count)) { |
| 138 | wait_on_atomic_t(&entry->fs_count, atomic_t_wait, | 138 | wait_var_event(&entry->fs_count, |
| 139 | TASK_UNINTERRUPTIBLE); | 139 | !atomic_read(&entry->fs_count)); |
| 140 | } | ||
| 140 | 141 | ||
| 141 | spin_lock(&entry->fs_fcheck->fc_lock); | 142 | spin_lock(&entry->fs_fcheck->fc_lock); |
| 142 | while (!list_empty(&entry->fs_fcheck->fc_head)) { | 143 | while (!list_empty(&entry->fs_fcheck->fc_head)) { |
| @@ -183,7 +184,7 @@ static void | |||
| 183 | ocfs2_filecheck_sysfs_put(struct ocfs2_filecheck_sysfs_entry *entry) | 184 | ocfs2_filecheck_sysfs_put(struct ocfs2_filecheck_sysfs_entry *entry) |
| 184 | { | 185 | { |
| 185 | if (atomic_dec_and_test(&entry->fs_count)) | 186 | if (atomic_dec_and_test(&entry->fs_count)) |
| 186 | wake_up_atomic_t(&entry->fs_count); | 187 | wake_up_var(&entry->fs_count); |
| 187 | } | 188 | } |
| 188 | 189 | ||
| 189 | static struct ocfs2_filecheck_sysfs_entry * | 190 | static struct ocfs2_filecheck_sysfs_entry * |
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 4c467ef50159..3b03e29e2f1a 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h | |||
| @@ -496,7 +496,7 @@ static inline bool __fscache_unuse_cookie(struct fscache_cookie *cookie) | |||
| 496 | 496 | ||
| 497 | static inline void __fscache_wake_unused_cookie(struct fscache_cookie *cookie) | 497 | static inline void __fscache_wake_unused_cookie(struct fscache_cookie *cookie) |
| 498 | { | 498 | { |
| 499 | wake_up_atomic_t(&cookie->n_active); | 499 | wake_up_var(&cookie->n_active); |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | /** | 502 | /** |
diff --git a/include/linux/wait_bit.h b/include/linux/wait_bit.h index 61b39eaf7cad..9318b2166439 100644 --- a/include/linux/wait_bit.h +++ b/include/linux/wait_bit.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | struct wait_bit_key { | 10 | struct wait_bit_key { |
| 11 | void *flags; | 11 | void *flags; |
| 12 | int bit_nr; | 12 | int bit_nr; |
| 13 | #define WAIT_ATOMIC_T_BIT_NR -1 | ||
| 14 | unsigned long timeout; | 13 | unsigned long timeout; |
| 15 | }; | 14 | }; |
| 16 | 15 | ||
| @@ -22,21 +21,15 @@ struct wait_bit_queue_entry { | |||
| 22 | #define __WAIT_BIT_KEY_INITIALIZER(word, bit) \ | 21 | #define __WAIT_BIT_KEY_INITIALIZER(word, bit) \ |
| 23 | { .flags = word, .bit_nr = bit, } | 22 | { .flags = word, .bit_nr = bit, } |
| 24 | 23 | ||
| 25 | #define __WAIT_ATOMIC_T_KEY_INITIALIZER(p) \ | ||
| 26 | { .flags = p, .bit_nr = WAIT_ATOMIC_T_BIT_NR, } | ||
| 27 | |||
| 28 | typedef int wait_bit_action_f(struct wait_bit_key *key, int mode); | 24 | typedef int wait_bit_action_f(struct wait_bit_key *key, int mode); |
| 29 | typedef int wait_atomic_t_action_f(atomic_t *counter, unsigned int mode); | ||
| 30 | 25 | ||
| 31 | void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit); | 26 | void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit); |
| 32 | int __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); | 27 | int __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); |
| 33 | int __wait_on_bit_lock(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); | 28 | int __wait_on_bit_lock(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); |
| 34 | void wake_up_bit(void *word, int bit); | 29 | void wake_up_bit(void *word, int bit); |
| 35 | void wake_up_atomic_t(atomic_t *p); | ||
| 36 | int out_of_line_wait_on_bit(void *word, int, wait_bit_action_f *action, unsigned int mode); | 30 | int out_of_line_wait_on_bit(void *word, int, wait_bit_action_f *action, unsigned int mode); |
| 37 | int out_of_line_wait_on_bit_timeout(void *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout); | 31 | int out_of_line_wait_on_bit_timeout(void *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout); |
| 38 | int out_of_line_wait_on_bit_lock(void *word, int, wait_bit_action_f *action, unsigned int mode); | 32 | int out_of_line_wait_on_bit_lock(void *word, int, wait_bit_action_f *action, unsigned int mode); |
| 39 | int out_of_line_wait_on_atomic_t(atomic_t *p, wait_atomic_t_action_f action, unsigned int mode); | ||
| 40 | struct wait_queue_head *bit_waitqueue(void *word, int bit); | 33 | struct wait_queue_head *bit_waitqueue(void *word, int bit); |
| 41 | extern void __init wait_bit_init(void); | 34 | extern void __init wait_bit_init(void); |
| 42 | 35 | ||
| @@ -57,7 +50,6 @@ extern int bit_wait(struct wait_bit_key *key, int mode); | |||
| 57 | extern int bit_wait_io(struct wait_bit_key *key, int mode); | 50 | extern int bit_wait_io(struct wait_bit_key *key, int mode); |
| 58 | extern int bit_wait_timeout(struct wait_bit_key *key, int mode); | 51 | extern int bit_wait_timeout(struct wait_bit_key *key, int mode); |
| 59 | extern int bit_wait_io_timeout(struct wait_bit_key *key, int mode); | 52 | extern int bit_wait_io_timeout(struct wait_bit_key *key, int mode); |
| 60 | extern int atomic_t_wait(atomic_t *counter, unsigned int mode); | ||
| 61 | 53 | ||
| 62 | /** | 54 | /** |
| 63 | * wait_on_bit - wait for a bit to be cleared | 55 | * wait_on_bit - wait for a bit to be cleared |
| @@ -243,23 +235,74 @@ wait_on_bit_lock_action(unsigned long *word, int bit, wait_bit_action_f *action, | |||
| 243 | return out_of_line_wait_on_bit_lock(word, bit, action, mode); | 235 | return out_of_line_wait_on_bit_lock(word, bit, action, mode); |
| 244 | } | 236 | } |
| 245 | 237 | ||
| 246 | /** | 238 | extern void init_wait_var_entry(struct wait_bit_queue_entry *wbq_entry, void *var, int flags); |
| 247 | * wait_on_atomic_t - Wait for an atomic_t to become 0 | 239 | extern void wake_up_var(void *var); |
| 248 | * @val: The atomic value being waited on, a kernel virtual address | 240 | extern wait_queue_head_t *__var_waitqueue(void *p); |
| 249 | * @action: the function used to sleep, which may take special actions | 241 | |
| 250 | * @mode: the task state to sleep in | 242 | #define ___wait_var_event(var, condition, state, exclusive, ret, cmd) \ |
| 251 | * | 243 | ({ \ |
| 252 | * Wait for an atomic_t to become 0. We abuse the bit-wait waitqueue table for | 244 | __label__ __out; \ |
| 253 | * the purpose of getting a waitqueue, but we set the key to a bit number | 245 | struct wait_queue_head *__wq_head = __var_waitqueue(var); \ |
| 254 | * outside of the target 'word'. | 246 | struct wait_bit_queue_entry __wbq_entry; \ |
| 255 | */ | 247 | long __ret = ret; /* explicit shadow */ \ |
| 256 | static inline | 248 | \ |
| 257 | int wait_on_atomic_t(atomic_t *val, wait_atomic_t_action_f action, unsigned mode) | 249 | init_wait_var_entry(&__wbq_entry, var, \ |
| 258 | { | 250 | exclusive ? WQ_FLAG_EXCLUSIVE : 0); \ |
| 259 | might_sleep(); | 251 | for (;;) { \ |
| 260 | if (atomic_read(val) == 0) | 252 | long __int = prepare_to_wait_event(__wq_head, \ |
| 261 | return 0; | 253 | &__wbq_entry.wq_entry, \ |
| 262 | return out_of_line_wait_on_atomic_t(val, action, mode); | 254 | state); \ |
| 263 | } | 255 | if (condition) \ |
| 256 | break; \ | ||
| 257 | \ | ||
| 258 | if (___wait_is_interruptible(state) && __int) { \ | ||
| 259 | __ret = __int; \ | ||
| 260 | goto __out; \ | ||
| 261 | } \ | ||
| 262 | \ | ||
| 263 | cmd; \ | ||
| 264 | } \ | ||
| 265 | finish_wait(__wq_head, &__wbq_entry.wq_entry); \ | ||
| 266 | __out: __ret; \ | ||
| 267 | }) | ||
| 268 | |||
| 269 | #define __wait_var_event(var, condition) \ | ||
| 270 | ___wait_var_event(var, condition, TASK_UNINTERRUPTIBLE, 0, 0, \ | ||
| 271 | schedule()) | ||
| 272 | |||
| 273 | #define wait_var_event(var, condition) \ | ||
| 274 | do { \ | ||
| 275 | might_sleep(); \ | ||
| 276 | if (condition) \ | ||
| 277 | break; \ | ||
| 278 | __wait_var_event(var, condition); \ | ||
| 279 | } while (0) | ||
| 280 | |||
| 281 | #define __wait_var_event_killable(var, condition) \ | ||
| 282 | ___wait_var_event(var, condition, TASK_KILLABLE, 0, 0, \ | ||
| 283 | schedule()) | ||
| 284 | |||
| 285 | #define wait_var_event_killable(var, condition) \ | ||
| 286 | ({ \ | ||
| 287 | int __ret = 0; \ | ||
| 288 | might_sleep(); \ | ||
| 289 | if (!(condition)) \ | ||
| 290 | __ret = __wait_var_event_killable(var, condition); \ | ||
| 291 | __ret; \ | ||
| 292 | }) | ||
| 293 | |||
| 294 | #define __wait_var_event_timeout(var, condition, timeout) \ | ||
| 295 | ___wait_var_event(var, ___wait_cond_timeout(condition), \ | ||
| 296 | TASK_UNINTERRUPTIBLE, 0, timeout, \ | ||
| 297 | __ret = schedule_timeout(__ret)) | ||
| 298 | |||
| 299 | #define wait_var_event_timeout(var, condition, timeout) \ | ||
| 300 | ({ \ | ||
| 301 | long __ret = timeout; \ | ||
| 302 | might_sleep(); \ | ||
| 303 | if (!___wait_cond_timeout(condition)) \ | ||
| 304 | __ret = __wait_var_event_timeout(var, condition, timeout); \ | ||
| 305 | __ret; \ | ||
| 306 | }) | ||
| 264 | 307 | ||
| 265 | #endif /* _LINUX_WAIT_BIT_H */ | 308 | #endif /* _LINUX_WAIT_BIT_H */ |
diff --git a/kernel/sched/wait_bit.c b/kernel/sched/wait_bit.c index 4239c78f5cd3..c67c6d24adc2 100644 --- a/kernel/sched/wait_bit.c +++ b/kernel/sched/wait_bit.c | |||
| @@ -149,106 +149,48 @@ void wake_up_bit(void *word, int bit) | |||
| 149 | } | 149 | } |
| 150 | EXPORT_SYMBOL(wake_up_bit); | 150 | EXPORT_SYMBOL(wake_up_bit); |
| 151 | 151 | ||
| 152 | /* | 152 | wait_queue_head_t *__var_waitqueue(void *p) |
| 153 | * Manipulate the atomic_t address to produce a better bit waitqueue table hash | ||
| 154 | * index (we're keying off bit -1, but that would produce a horrible hash | ||
| 155 | * value). | ||
| 156 | */ | ||
| 157 | static inline wait_queue_head_t *atomic_t_waitqueue(atomic_t *p) | ||
| 158 | { | 153 | { |
| 159 | if (BITS_PER_LONG == 64) { | 154 | return bit_wait_table + hash_ptr(p, WAIT_TABLE_BITS); |
| 160 | unsigned long q = (unsigned long)p; | ||
| 161 | |||
| 162 | return bit_waitqueue((void *)(q & ~1), q & 1); | ||
| 163 | } | ||
| 164 | return bit_waitqueue(p, 0); | ||
| 165 | } | 155 | } |
| 156 | EXPORT_SYMBOL(__var_waitqueue); | ||
| 166 | 157 | ||
| 167 | static int wake_atomic_t_function(struct wait_queue_entry *wq_entry, unsigned mode, int sync, | 158 | static int |
| 168 | void *arg) | 159 | var_wake_function(struct wait_queue_entry *wq_entry, unsigned int mode, |
| 160 | int sync, void *arg) | ||
| 169 | { | 161 | { |
| 170 | struct wait_bit_key *key = arg; | 162 | struct wait_bit_key *key = arg; |
| 171 | struct wait_bit_queue_entry *wait_bit = container_of(wq_entry, struct wait_bit_queue_entry, wq_entry); | 163 | struct wait_bit_queue_entry *wbq_entry = |
| 172 | atomic_t *val = key->flags; | 164 | container_of(wq_entry, struct wait_bit_queue_entry, wq_entry); |
| 173 | 165 | ||
| 174 | if (wait_bit->key.flags != key->flags || | 166 | if (wbq_entry->key.flags != key->flags || |
| 175 | wait_bit->key.bit_nr != key->bit_nr || | 167 | wbq_entry->key.bit_nr != key->bit_nr) |
| 176 | atomic_read(val) != 0) | ||
| 177 | return 0; | 168 | return 0; |
| 178 | 169 | ||
| 179 | return autoremove_wake_function(wq_entry, mode, sync, key); | 170 | return autoremove_wake_function(wq_entry, mode, sync, key); |
| 180 | } | 171 | } |
| 181 | 172 | ||
| 182 | /* | 173 | void init_wait_var_entry(struct wait_bit_queue_entry *wbq_entry, void *var, int flags) |
| 183 | * To allow interruptible waiting and asynchronous (i.e. nonblocking) waiting, | ||
| 184 | * the actions of __wait_on_atomic_t() are permitted return codes. Nonzero | ||
| 185 | * return codes halt waiting and return. | ||
| 186 | */ | ||
| 187 | static __sched | ||
| 188 | int __wait_on_atomic_t(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, | ||
| 189 | wait_atomic_t_action_f action, unsigned int mode) | ||
| 190 | { | 174 | { |
| 191 | atomic_t *val; | 175 | *wbq_entry = (struct wait_bit_queue_entry){ |
| 192 | int ret = 0; | 176 | .key = { |
| 193 | 177 | .flags = (var), | |
| 194 | do { | 178 | .bit_nr = -1, |
| 195 | prepare_to_wait(wq_head, &wbq_entry->wq_entry, mode); | 179 | }, |
| 196 | val = wbq_entry->key.flags; | 180 | .wq_entry = { |
| 197 | if (atomic_read(val) == 0) | 181 | .private = current, |
| 198 | break; | 182 | .func = var_wake_function, |
| 199 | ret = (*action)(val, mode); | 183 | .entry = LIST_HEAD_INIT(wbq_entry->wq_entry.entry), |
| 200 | } while (!ret && atomic_read(val) != 0); | 184 | }, |
| 201 | finish_wait(wq_head, &wbq_entry->wq_entry); | 185 | }; |
| 202 | |||
| 203 | return ret; | ||
| 204 | } | 186 | } |
| 187 | EXPORT_SYMBOL(init_wait_var_entry); | ||
| 205 | 188 | ||
| 206 | #define DEFINE_WAIT_ATOMIC_T(name, p) \ | 189 | void wake_up_var(void *var) |
| 207 | struct wait_bit_queue_entry name = { \ | ||
| 208 | .key = __WAIT_ATOMIC_T_KEY_INITIALIZER(p), \ | ||
| 209 | .wq_entry = { \ | ||
| 210 | .private = current, \ | ||
| 211 | .func = wake_atomic_t_function, \ | ||
| 212 | .entry = \ | ||
| 213 | LIST_HEAD_INIT((name).wq_entry.entry), \ | ||
| 214 | }, \ | ||
| 215 | } | ||
| 216 | |||
| 217 | __sched int out_of_line_wait_on_atomic_t(atomic_t *p, | ||
| 218 | wait_atomic_t_action_f action, | ||
| 219 | unsigned int mode) | ||
| 220 | { | ||
| 221 | struct wait_queue_head *wq_head = atomic_t_waitqueue(p); | ||
| 222 | DEFINE_WAIT_ATOMIC_T(wq_entry, p); | ||
| 223 | |||
| 224 | return __wait_on_atomic_t(wq_head, &wq_entry, action, mode); | ||
| 225 | } | ||
| 226 | EXPORT_SYMBOL(out_of_line_wait_on_atomic_t); | ||
| 227 | |||
| 228 | __sched int atomic_t_wait(atomic_t *counter, unsigned int mode) | ||
| 229 | { | ||
| 230 | schedule(); | ||
| 231 | if (signal_pending_state(mode, current)) | ||
| 232 | return -EINTR; | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | EXPORT_SYMBOL(atomic_t_wait); | ||
| 237 | |||
| 238 | /** | ||
| 239 | * wake_up_atomic_t - Wake up a waiter on a atomic_t | ||
| 240 | * @p: The atomic_t being waited on, a kernel virtual address | ||
| 241 | * | ||
| 242 | * Wake up anyone waiting for the atomic_t to go to zero. | ||
| 243 | * | ||
| 244 | * Abuse the bit-waker function and its waitqueue hash table set (the atomic_t | ||
| 245 | * check is done by the waiter's wake function, not the by the waker itself). | ||
| 246 | */ | ||
| 247 | void wake_up_atomic_t(atomic_t *p) | ||
| 248 | { | 190 | { |
| 249 | __wake_up_bit(atomic_t_waitqueue(p), p, WAIT_ATOMIC_T_BIT_NR); | 191 | __wake_up_bit(__var_waitqueue(var), var, -1); |
| 250 | } | 192 | } |
| 251 | EXPORT_SYMBOL(wake_up_atomic_t); | 193 | EXPORT_SYMBOL(wake_up_var); |
| 252 | 194 | ||
| 253 | __sched int bit_wait(struct wait_bit_key *word, int mode) | 195 | __sched int bit_wait(struct wait_bit_key *word, int mode) |
| 254 | { | 196 | { |
