scheduler changes for v3.17
Subsystems (26)
Ingo Molnar
maintainerLinus,
Please pull the latest sched-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched-core-for-linus
# HEAD: cd3bd4e628a6d57d66afe77835fe8d93ae3e41f8 sched/fair: Fix 'make xmldocs' warning caused by missing description
* Move the nohz kick code out of the scheduler tick to a dedicated IPI, from Frederic Weisbecker.
This necessiated quite some background infrastructure rework, including:
* Clean up some irq-work internals
* Implement remote irq-work
* Implement nohz kick on top of remote irq-work
* Move full dynticks timer enqueue notification to new kick
* Move multi-task notification to new kick
* Remove unecessary barriers on multi-task notification
* Remove proliferation of wait_on_bit() action functions and allow wait_on_bit_action() functions to support a timeout. (Neil Brown)
* Another round of sched/numa improvements, cleanups and fixes. (Rik van Riel)
* Implement fast idling of CPUs when the system is partially loaded, for better scalability. (Tim Chen)
* Restructure and fix the CPU hotplug handling code that may leave cfs_rq and rt_rq's throttled when tasks are migrated away from a dead cpu. (Kirill Tkhai)
* Robustify the sched topology setup code. (Peterz Zijlstra)
* Improve sched_feat() handling wrt. static_keys (Jason Baron)
* Misc fixes.
Thanks,
Ingo
------------------>
Ben Segall (1):
sched: Fix potential near-infinite distribute_cfs_runtime() loop
Daniel Bristot de Oliveira (1):
sched: Fix sched_setparam() policy == -1 logic
Frederic Weisbecker (6):
irq_work: Split raised and lazy lists
irq_work: Implement remote queueing
nohz: Support nohz full remote kick
nohz: Switch to nohz full remote kick on timer enqueue
nohz: Use nohz own full kick on 2nd task enqueue
nohz: Use IPI implicit full barrier against rq->nr_running r/w
Hillf Danton (1):
sched: Fix CACHE_HOT_BUDY condition
Jason Baron (2):
sched: Remove extra static_key*() function indirection
sched: Fix static_key race with sched_feat()
Kirill Tkhai (4):
sched/fair: Disable runtime_enabled on dying rq
sched/rt: Enqueue just unthrottled rt_rq back on the stack in __disable_runtime()
sched: Rework check_for_tasks()
sched: Transform resched_task() into resched_curr()
Masanari Iida (1):
sched/fair: Fix 'make xmldocs' warning caused by missing description
Mike Galbraith (1):
sched: Fix clock_gettime(CLOCK_[PROCESS/THREAD]_CPUTIME_ID) monotonicity
NeilBrown (2):
sched: Remove proliferation of wait_on_bit() action functions
sched: Allow wait_on_bit_action() functions to support a timeout
Oleg Nesterov (1):
sched/deadline: Kill task_struct->pi_top_task
Peter Zijlstra (3):
irq_work: Remove BUG_ON in irq_work_run() sched/numa: Revert "Use effective_load() to balance NUMA loads"
sched: Robustify topology setup
Rik van Riel (9):
sched/numa: Ensure task_numa_migrate() checks the preferred node sched/numa: Always try to migrate to preferred node at task_numa_placement() time sched/numa: Use group's max nid as task's preferred nid
sched/numa: Move power adjustment into load_too_imbalanced() sched/numa: Use effective_load() to balance NUMA loads
sched/numa: Simplify task_numa_compare()
sched/numa: Examine a task move when examining a task swap sched/numa: Rework best node setting in task_numa_migrate() sched/numa: Change scan period code to match intent
Steven Rostedt (1):
sched: Use macro for magic number of -1 for setparam
Tim Chen (1):
sched/fair: Implement fast idling of CPUs when the system is partially loaded
Viresh Kumar (2):
sched/core: Fix formatting issues in sched_can_stop_tick() sched/idle: Drop !! while calculating 'broadcast'
xiaofeng.yan (1):
sched/rt: Fix replenish_dl_entity() comments to match the current upstream code
Documentation/filesystems/caching/operations.txt | 2 +- Documentation/trace/ftrace.txt | 2 +- drivers/md/dm-bufio.c | 41 ++-- drivers/md/dm-snap.c | 10 +- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 12 +- fs/btrfs/extent_io.c | 10 +- fs/buffer.c | 11 +- fs/cifs/connect.c | 10 +- fs/cifs/file.c | 9 +- fs/cifs/inode.c | 6 +- fs/cifs/misc.c | 2 +- fs/fs-writeback.c | 3 +- fs/fscache/cookie.c | 7 +- fs/fscache/internal.h | 2 - fs/fscache/main.c | 18 -- fs/fscache/page.c | 4 +- fs/gfs2/glock.c | 25 +-- fs/gfs2/lock_dlm.c | 8 +- fs/gfs2/ops_fstype.c | 11 +- fs/gfs2/recovery.c | 8 +- fs/gfs2/super.c | 8 +- fs/inode.c | 7 - fs/jbd2/transaction.c | 10 +- fs/nfs/file.c | 4 +- fs/nfs/filelayout/filelayoutdev.c | 4 +- fs/nfs/inode.c | 6 +- fs/nfs/internal.h | 2 +- fs/nfs/nfs4state.c | 4 +- fs/nfs/pagelist.c | 14 +- fs/nfs/pnfs.c | 2 +- fs/nfs/write.c | 4 +- include/linux/irq_work.h | 5 + include/linux/sched.h | 8 +- include/linux/sunrpc/sched.h | 2 +- include/linux/tick.h | 9 +- include/linux/wait.h | 125 +++++++++++- include/linux/writeback.h | 3 +- kernel/cpu.c | 33 +-- kernel/fork.c | 1 - kernel/irq_work.c | 110 +++++----- kernel/ptrace.c | 8 +- kernel/sched/core.c | 119 +++++++---- kernel/sched/deadline.c | 18 +- kernel/sched/fair.c | 244 ++++++++++++++--------- kernel/sched/idle.c | 4 +- kernel/sched/idle_task.c | 2 +- kernel/sched/rt.c | 30 +-- kernel/sched/sched.h | 38 ++-- kernel/sched/wait.c | 30 ++- kernel/smp.c | 9 + kernel/time/tick-sched.c | 10 +- mm/filemap.c | 20 +- mm/ksm.c | 8 +- net/bluetooth/hci_core.c | 8 +- net/sunrpc/sched.c | 4 +- security/keys/gc.c | 11 +- security/keys/request_key.c | 23 +-- 57 files changed, 588 insertions(+), 560 deletions(-)
Documentation/filesystems/caching/operations.txt +1 -1
@@ -90,7 +90,7 @@ operations: to be cleared before proceeding: wait_on_bit(&op->flags, FSCACHE_OP_WAITING, - fscache_wait_bit, TASK_UNINTERRUPTIBLE); + TASK_UNINTERRUPTIBLE); (2) The operation may be fast asynchronous (FSCACHE_OP_FAST), in which case it
Documentation/trace/ftrace.txt +1 -1
@@ -1515,7 +1515,7 @@ Doing the same with chrt -r 5 and function-trace set. <idle>-0 3d.h4 1us+: 0:120:R + [003] 2448: 94:R sleep <idle>-0 3d.h4 2us : ttwu_do_activate.constprop.87 <-try_to_wake_up <idle>-0 3d.h3 3us : check_preempt_curr <-ttwu_do_wakeup - <idle>-0 3d.h3 3us : resched_task <-check_preempt_curr + <idle>-0 3d.h3 3us : resched_curr <-check_preempt_curr <idle>-0 3dNh3 4us : task_woken_rt <-ttwu_do_wakeup <idle>-0 3dNh3 4us : _raw_spin_unlock <-try_to_wake_up <idle>-0 3dNh3 4us : sub_preempt_count <-_raw_spin_unlock
drivers/md/dm-bufio.c +14 -27
92 lines not on this page · raw message
drivers/md/dm-snap.c +1 -9
@@ -1032,21 +1032,13 @@ static void start_merge(struct dm_snapshot *s)snapshot_merge_next_chunks (s); } -static int wait_schedule (void *ptr) -{ -schedule (); - -return 0 ; -} -/* * Stop the merging process and wait until it finishes. */ static void stop_merge (struct dm_snapshot *s) {set_bit (SHUTDOWN_MERGE , &s->state_bits); -wait_on_bit (&s->state_bits,RUNNING_MERGE , wait_schedule, -TASK_UNINTERRUPTIBLE ); +wait_on_bit (&s->state_bits,RUNNING_MERGE ,TASK_UNINTERRUPTIBLE );clear_bit (SHUTDOWN_MERGE , &s->state_bits); }
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +2 -10
@@ -253,13 +253,6 @@ static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)return usb_urb_exitv2 (&adap->stream); } -static int wait_schedule (void *ptr) -{ -schedule (); - -return 0 ; -} -static int dvb_usb_start_feed (struct dvb_demux_feed *dvbdmxfeed) {struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
@@ -273,8 +266,7 @@ static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) dvbdmxfeed->pid, dvbdmxfeed->index);/* wait init is done */ -wait_on_bit (&adap->state_bits,ADAP_INIT , wait_schedule, -TASK_UNINTERRUPTIBLE ); +wait_on_bit (&adap->state_bits,ADAP_INIT ,TASK_UNINTERRUPTIBLE );if (adap->active_fe ==-1 )return -EINVAL ;
@@ -568,7 +560,7 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)if (!adap->suspend_resume_active) {set_bit (ADAP_SLEEP , &adap->state_bits); -wait_on_bit (&adap->state_bits,ADAP_STREAMING , wait_schedule, +wait_on_bit (&adap->state_bits,ADAP_STREAMING ,TASK_UNINTERRUPTIBLE ); }
fs/btrfs/extent_io.c +2 -8
@@ -3437,16 +3437,10 @@ done_unlocked:return 0 ; } -static int eb_wait (void *word) -{ -io_schedule (); -return 0 ; -} -void wait_on_extent_buffer_writeback (struct extent_buffer *eb) { -wait_on_bit (&eb->bflags,EXTENT_BUFFER_WRITEBACK , eb_wait, -TASK_UNINTERRUPTIBLE ); +wait_on_bit_io (&eb->bflags,EXTENT_BUFFER_WRITEBACK , +TASK_UNINTERRUPTIBLE ); }static noinline_for_stack int
fs/buffer.c +2 -9
@@ -61,16 +61,9 @@ inline void touch_buffer(struct buffer_head *bh) }EXPORT_SYMBOL (touch_buffer); -static int sleep_on_buffer (void *word) -{ -io_schedule (); -return 0 ; -} -void __lock_buffer (struct buffer_head *bh) { -wait_on_bit_lock (&bh->b_state, BH_Lock, sleep_on_buffer, -TASK_UNINTERRUPTIBLE ); +wait_on_bit_lock_io (&bh->b_state, BH_Lock,TASK_UNINTERRUPTIBLE ); }EXPORT_SYMBOL (__lock_buffer);
@@ -123,7 +116,7 @@ EXPORT_SYMBOL(buffer_check_dirty_writeback);*/ void __wait_on_buffer (struct buffer_head * bh) { -wait_on_bit (&bh->b_state, BH_Lock, sleep_on_buffer,TASK_UNINTERRUPTIBLE ); +wait_on_bit_io (&bh->b_state, BH_Lock,TASK_UNINTERRUPTIBLE ); }EXPORT_SYMBOL (__wait_on_buffer);
fs/cifs/connect.c +1 -9
@@ -3934,13 +3934,6 @@ cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)return tlink_tcon (cifs_sb_master_tlink (cifs_sb)); } -static int -cifs_sb_tcon_pending_wait (void *unused) -{ -schedule (); -return signal_pending (current) ? -ERESTARTSYS :0 ; -} -/* find and return a tlink with given uid */ static struct tcon_link *tlink_rb_search (struct rb_root *root,kuid_t uid)
@@ -4039,11 +4032,10 @@ cifs_sb_tlink(struct cifs_sb_info *cifs_sb) }else { wait_for_construction: ret =wait_on_bit (&tlink->tl_flags,TCON_LINK_PENDING , - cifs_sb_tcon_pending_wait,TASK_INTERRUPTIBLE );if (ret) {cifs_put_tlink (tlink); -return ERR_PTR (ret); +return ERR_PTR (-ERESTARTSYS ); }/* if it's good, return it */
fs/cifs/file.c +1 -8
@@ -3618,13 +3618,6 @@ static int cifs_launder_page(struct page *page)return rc; } -static int -cifs_pending_writers_wait (void *unused) -{ -schedule (); -return 0 ; -} -void cifs_oplock_break (struct work_struct *work) { struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
@@ -3636,7 +3629,7 @@ void cifs_oplock_break(struct work_struct *work)int rc =0 ;wait_on_bit (&cinode->flags,CIFS_INODE_PENDING_WRITERS , - cifs_pending_writers_wait,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE ); server->ops->downgrade_oplock (server, cinode,test_bit (CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 , &cinode->flags));
fs/cifs/inode.c +3 -3
@@ -1780,7 +1780,7 @@ cifs_invalidate_mapping(struct inode *inode)* @word: long word containing the bit lock */ static int -cifs_wait_bit_killable (void *word) +cifs_wait_bit_killable (struct wait_bit_key *key) {if (fatal_signal_pending (current))return -ERESTARTSYS ;
@@ -1794,8 +1794,8 @@ cifs_revalidate_mapping(struct inode *inode)int rc;unsigned long *flags = &CIFS_I (inode)->flags; - rc =wait_on_bit_lock (flags,CIFS_INO_LOCK , cifs_wait_bit_killable, -TASK_KILLABLE ); + rc =wait_on_bit_lock_action (flags,CIFS_INO_LOCK , cifs_wait_bit_killable, +TASK_KILLABLE );if (rc)return rc;
fs/cifs/misc.c +1 -1
@@ -582,7 +582,7 @@ int cifs_get_writer(struct cifsInodeInfo *cinode) start: rc =wait_on_bit (&cinode->flags,CIFS_INODE_PENDING_OPLOCK_BREAK , - cifs_oplock_break_wait,TASK_KILLABLE ); +TASK_KILLABLE );if (rc)return rc;
fs/fs-writeback.c +2 -1
@@ -342,7 +342,8 @@ static void __inode_wait_for_writeback(struct inode *inode) wqh =bit_waitqueue (&inode->i_state, __I_SYNC);while (inode->i_state &I_SYNC ) {spin_unlock (&inode->i_lock); -__wait_on_bit (wqh, &wq, inode_wait,TASK_UNINTERRUPTIBLE ); +__wait_on_bit (wqh, &wq, bit_wait, +TASK_UNINTERRUPTIBLE );spin_lock (&inode->i_lock); } }
fs/fscache/cookie.c +3 -4
@@ -160,7 +160,7 @@ void __fscache_enable_cookie(struct fscache_cookie *cookie,_enter ("%p" , cookie);wait_on_bit_lock (&cookie->flags,FSCACHE_COOKIE_ENABLEMENT_LOCK , - fscache_wait_bit,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE );if (test_bit (FSCACHE_COOKIE_ENABLED , &cookie->flags)) goto out_unlock;
@@ -255,7 +255,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)if (!fscache_defer_lookup) {_debug ("non-deferred lookup %p" , &cookie->flags);wait_on_bit (&cookie->flags,FSCACHE_COOKIE_LOOKING_UP , - fscache_wait_bit,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE );_debug ("complete" );if (test_bit (FSCACHE_COOKIE_UNAVAILABLE , &cookie->flags)) goto unavailable;
@@ -463,7 +463,6 @@ void __fscache_wait_on_invalidate(struct fscache_cookie *cookie)_enter ("%p" , cookie);wait_on_bit (&cookie->flags,FSCACHE_COOKIE_INVALIDATING , - fscache_wait_bit_interruptible,TASK_UNINTERRUPTIBLE );_leave ("" );
@@ -525,7 +524,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) }wait_on_bit_lock (&cookie->flags,FSCACHE_COOKIE_ENABLEMENT_LOCK , - fscache_wait_bit,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE );if (!test_and_clear_bit (FSCACHE_COOKIE_ENABLED , &cookie->flags)) goto out_unlock_enable;
fs/fscache/internal.h +0 -2
@@ -97,8 +97,6 @@ static inline bool fscache_object_congested(void)return workqueue_congested (WORK_CPU_UNBOUND , fscache_object_wq); } -extern int fscache_wait_bit (void *); -extern int fscache_wait_bit_interruptible (void *);extern int fscache_wait_atomic_t (atomic_t *);/*
fs/fscache/main.c +0 -18
@@ -197,24 +197,6 @@ static void __exit fscache_exit(void)module_exit (fscache_exit);/* -* wait_on_bit() sleep function for uninterruptible waiting -*/ -int fscache_wait_bit (void *flags) -{ -schedule (); -return 0 ; -} - -/* -* wait_on_bit() sleep function for interruptible waiting -*/ -int fscache_wait_bit_interruptible (void *flags) -{ -schedule (); -return signal_pending (current); -} - -/* * wait_on_atomic_t() sleep function for uninterruptible waiting */ int fscache_wait_atomic_t (atomic_t *p)
fs/fscache/page.c +1 -3
@@ -298,7 +298,6 @@ int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie) jif = jiffies;if (wait_on_bit (&cookie->flags,FSCACHE_COOKIE_LOOKING_UP , - fscache_wait_bit_interruptible,TASK_INTERRUPTIBLE ) !=0 ) {fscache_stat (&fscache_n_retrievals_intr);_leave (" = -ERESTARTSYS" );
@@ -342,7 +341,6 @@ int fscache_wait_for_operation_activation(struct fscache_object *object,if (stat_op_waits)fscache_stat (stat_op_waits);if (wait_on_bit (&op->flags,FSCACHE_OP_WAITING , - fscache_wait_bit_interruptible,TASK_INTERRUPTIBLE ) !=0 ) { ret =fscache_cancel_op (op, do_cancel);if (ret ==0 )
@@ -351,7 +349,7 @@ int fscache_wait_for_operation_activation(struct fscache_object *object,/* it's been removed from the pending queue by another party, * so we should get to run shortly */ wait_on_bit (&op->flags,FSCACHE_OP_WAITING , - fscache_wait_bit,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE ); }_debug ("<<< GO" );
fs/gfs2/glock.c +2 -23
@@ -856,27 +856,6 @@ void gfs2_holder_uninit(struct gfs2_holder *gh) }/** -* gfs2_glock_holder_wait -* @word: unused -* -* This function and gfs2_glock_demote_wait both show up in the WCHAN -* field. Thus I've separated these otherwise identical functions in -* order to be more informative to the user. -*/ - -static int gfs2_glock_holder_wait (void *word) -{ -schedule (); -return 0 ; -} - -static int gfs2_glock_demote_wait (void *word) -{ -schedule (); -return 0 ; -} - -/** * gfs2_glock_wait - wait on a glock acquisition * @gh: the glock holder *
@@ -888,7 +867,7 @@ int gfs2_glock_wait(struct gfs2_holder *gh)unsigned long time1 = jiffies;might_sleep (); -wait_on_bit (&gh->gh_iflags,HIF_WAIT , gfs2_glock_holder_wait,TASK_UNINTERRUPTIBLE ); +wait_on_bit (&gh->gh_iflags,HIF_WAIT ,TASK_UNINTERRUPTIBLE );if (time_after (jiffies, time1 +HZ ))/* have we waited > a second? */ /* Lengthen the minimum hold time. */ gh->gh_gl->gl_hold_time = min(gh->gh_gl->gl_hold_time +
@@ -1128,7 +1107,7 @@ void gfs2_glock_dq_wait(struct gfs2_holder *gh)struct gfs2_glock *gl = gh->gh_gl;gfs2_glock_dq (gh);might_sleep (); -wait_on_bit (&gl->gl_flags,GLF_DEMOTE , gfs2_glock_demote_wait,TASK_UNINTERRUPTIBLE ); +wait_on_bit (&gl->gl_flags,GLF_DEMOTE ,TASK_UNINTERRUPTIBLE ); }/**
fs/gfs2/lock_dlm.c +1 -7
@@ -936,12 +936,6 @@ fail:return error; } -static int dlm_recovery_wait (void *word) -{ -schedule (); -return 0 ; -} -static int control_first_done (struct gfs2_sbd *sdp) {struct lm_lockstruct *ls = &sdp->sd_lockstruct;
@@ -976,7 +970,7 @@ restart:fs_info (sdp,"control_first_done wait gen %u\n" , start_gen);wait_on_bit (&ls->ls_recover_flags,DFL_DLM_RECOVERY , - dlm_recovery_wait,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE ); goto restart; }
fs/gfs2/ops_fstype.c +2 -9
@@ -1024,20 +1024,13 @@ void gfs2_lm_unmount(struct gfs2_sbd *sdp) lm->lm_unmount (sdp); } -static int gfs2_journalid_wait (void *word) -{ -if (signal_pending (current)) -return -EINTR ; -schedule (); -return 0 ; -} -static int wait_on_journal (struct gfs2_sbd *sdp) {if (sdp->sd_lockstruct.ls_ops->lm_mount ==NULL )return 0 ; -return wait_on_bit (&sdp->sd_flags,SDF_NOJOURNALID , gfs2_journalid_wait,TASK_INTERRUPTIBLE ); +return wait_on_bit (&sdp->sd_flags,SDF_NOJOURNALID ,TASK_INTERRUPTIBLE ) + ? -EINTR :0 ; }void gfs2_online_uevent (struct gfs2_sbd *sdp)
fs/gfs2/recovery.c +1 -7
@@ -591,12 +591,6 @@ done:wake_up_bit (&jd->jd_flags,JDF_RECOVERY ); } -static int gfs2_recovery_wait (void *word) -{ -schedule (); -return 0 ; -} -int gfs2_recover_journal (struct gfs2_jdesc *jd,bool wait) {int rv;
@@ -609,7 +603,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd, bool wait)BUG_ON (!rv);if (wait) -wait_on_bit (&jd->jd_flags,JDF_RECOVERY , gfs2_recovery_wait, +wait_on_bit (&jd->jd_flags,JDF_RECOVERY ,TASK_UNINTERRUPTIBLE );return wait ? jd->jd_recover_error :0 ;
fs/gfs2/super.c +1 -7
@@ -864,12 +864,6 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)return error; } -static int gfs2_umount_recovery_wait (void *word) -{ -schedule (); -return 0 ; -} -/** * gfs2_put_super - Unmount the filesystem * @sb: The VFS superblock
@@ -894,7 +888,7 @@ restart:continue ;spin_unlock (&sdp->sd_jindex_spin);wait_on_bit (&jd->jd_flags,JDF_RECOVERY , - gfs2_umount_recovery_wait,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE ); goto restart; }spin_unlock (&sdp->sd_jindex_spin);
fs/inode.c +0 -7
@@ -1695,13 +1695,6 @@ int inode_needs_sync(struct inode *inode) }EXPORT_SYMBOL (inode_needs_sync); -int inode_wait (void *word) -{ -schedule (); -return 0 ; -} -EXPORT_SYMBOL (inode_wait); -/* * If we try to find an inode in the inode hash while it is being * deleted, we have to wait until the filesystem completes its
fs/jbd2/transaction.c +2 -8
@@ -763,12 +763,6 @@ static void warn_dirty_buffer(struct buffer_head *bh) bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr); } -static int sleep_on_shadow_bh (void *word) -{ -io_schedule (); -return 0 ; -} -/* * If the buffer is already part of the current transaction, then there * is nothing we need to do. If it is already part of a prior
@@ -906,8 +900,8 @@ repeat:if (buffer_shadow (bh)) {JBUFFER_TRACE (jh,"on shadow: sleep" );jbd_unlock_bh_state (bh); -wait_on_bit (&bh->b_state, BH_Shadow, - sleep_on_shadow_bh,TASK_UNINTERRUPTIBLE ); +wait_on_bit_io (&bh->b_state, BH_Shadow, +TASK_UNINTERRUPTIBLE ); goto repeat; }
fs/nfs/file.c +2 -2
@@ -361,8 +361,8 @@ start:* Prevent starvation issues if someone is doing a consistency * sync-to-disk */ - ret =wait_on_bit (&NFS_I (mapping->host)->flags,NFS_INO_FLUSHING , - nfs_wait_bit_killable,TASK_KILLABLE ); + ret =wait_on_bit_action (&NFS_I (mapping->host)->flags,NFS_INO_FLUSHING , + nfs_wait_bit_killable,TASK_KILLABLE );if (ret)return ret;
fs/nfs/filelayout/filelayoutdev.c +2 -2
@@ -783,8 +783,8 @@ nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)static void nfs4_wait_ds_connect (struct nfs4_pnfs_ds *ds) {might_sleep (); -wait_on_bit (&ds->ds_state,NFS4DS_CONNECTING , - nfs_wait_bit_killable,TASK_KILLABLE ); +wait_on_bit_action (&ds->ds_state,NFS4DS_CONNECTING , + nfs_wait_bit_killable,TASK_KILLABLE ); }static void nfs4_clear_ds_conn_bit (struct nfs4_pnfs_ds *ds)
fs/nfs/inode.c +3 -3
@@ -75,7 +75,7 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)* nfs_wait_bit_killable - helper for functions that are sleeping on bit locks * @word: long word containing the bit lock */ -int nfs_wait_bit_killable (void *word) +int nfs_wait_bit_killable (struct wait_bit_key *key) {if (fatal_signal_pending (current))return -ERESTARTSYS ;
@@ -1074,8 +1074,8 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)* the bit lock here if it looks like we're going to be doing that. */ for (;;) { - ret =wait_on_bit (bitlock,NFS_INO_INVALIDATING , - nfs_wait_bit_killable,TASK_KILLABLE ); + ret =wait_on_bit_action (bitlock,NFS_INO_INVALIDATING , + nfs_wait_bit_killable,TASK_KILLABLE );if (ret) goto out;spin_lock (&inode->i_lock);
fs/nfs/internal.h +1 -1
@@ -348,7 +348,7 @@ extern int nfs_drop_inode(struct inode *);extern void nfs_clear_inode (struct inode *);extern void nfs_evict_inode (struct inode *);void nfs_zap_acl_cache (struct inode *inode); -extern int nfs_wait_bit_killable (void *word); +extern int nfs_wait_bit_killable (struct wait_bit_key *key);/* super.c */ extern const struct super_operations nfs_sops;
fs/nfs/nfs4state.c +2 -2
@@ -1251,8 +1251,8 @@ int nfs4_wait_clnt_recover(struct nfs_client *clp)might_sleep ();atomic_inc (&clp->cl_count); - res =wait_on_bit (&clp->cl_state,NFS4CLNT_MANAGER_RUNNING , - nfs_wait_bit_killable,TASK_KILLABLE ); + res =wait_on_bit_action (&clp->cl_state,NFS4CLNT_MANAGER_RUNNING , + nfs_wait_bit_killable,TASK_KILLABLE );if (res) goto out;if (clp->cl_cons_state <0 )
fs/nfs/pagelist.c +3 -11
@@ -115,7 +115,7 @@ __nfs_iocounter_wait(struct nfs_io_counter *c)set_bit (NFS_IO_INPROGRESS , &c->flags);if (atomic_read (&c->io_count) ==0 )break ; - ret =nfs_wait_bit_killable (&c->flags); + ret =nfs_wait_bit_killable (&q.key); }while (atomic_read (&c->io_count) !=0 );finish_wait (wq, &q.wait);return ret;
@@ -136,12 +136,6 @@ nfs_iocounter_wait(struct nfs_io_counter *c)return __nfs_iocounter_wait (c); } -static int nfs_wait_bit_uninterruptible (void *word) -{ -io_schedule (); -return 0 ; -} -/* * nfs_page_group_lock - lock the head of the page group * @req - request in group that is to be locked
@@ -156,7 +150,6 @@ nfs_page_group_lock(struct nfs_page *req)WARN_ON_ONCE (head != head->wb_head);wait_on_bit_lock (&head->wb_flags,PG_HEADLOCK , - nfs_wait_bit_uninterruptible,TASK_UNINTERRUPTIBLE ); }
@@ -435,9 +428,8 @@ void nfs_release_request(struct nfs_page *req)int nfs_wait_on_request (struct nfs_page *req) { -return wait_on_bit (&req->wb_flags,PG_BUSY , - nfs_wait_bit_uninterruptible, -TASK_UNINTERRUPTIBLE ); +return wait_on_bit_io (&req->wb_flags,PG_BUSY , +TASK_UNINTERRUPTIBLE ); }/*
fs/nfs/pnfs.c +1 -1
@@ -1885,7 +1885,7 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)if (test_and_set_bit (NFS_INO_LAYOUTCOMMITTING , &nfsi->flags)) {if (!sync) goto out; - status =wait_on_bit_lock (&nfsi->flags, + status =wait_on_bit_lock_action (&nfsi->flags,NFS_INO_LAYOUTCOMMITTING , nfs_wait_bit_killable,TASK_KILLABLE );
fs/nfs/write.c +2 -2
@@ -623,7 +623,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)int err;/* Stop dirtying of new pages while we sync */ - err =wait_on_bit_lock (bitlock,NFS_INO_FLUSHING , + err =wait_on_bit_lock_action (bitlock,NFS_INO_FLUSHING , nfs_wait_bit_killable,TASK_KILLABLE );if (err) goto out_err;
@@ -1703,7 +1703,7 @@ int nfs_commit_inode(struct inode *inode, int how)return error;if (!may_wait) goto out_mark_dirty; - error =wait_on_bit (&NFS_I (inode)->flags, + error =wait_on_bit_action (&NFS_I (inode)->flags,NFS_INO_COMMIT , nfs_wait_bit_killable,TASK_KILLABLE );
include/linux/irq_work.h +5 -0
@@ -33,6 +33,11 @@ void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))#define DEFINE_IRQ_WORK (name, _f) struct irq_work name = { .func = (_f), }bool irq_work_queue (struct irq_work *work); + +#ifdef CONFIG_SMP +bool irq_work_queue_on (struct irq_work *work,int cpu); +#endif +void irq_work_run (void );void irq_work_sync (struct irq_work *work);
include/linux/sched.h +3 -5
@@ -1440,8 +1440,6 @@ struct task_struct {struct rb_node *pi_waiters_leftmost;/* Deadlock detection and priority inheritance handling */ struct rt_mutex_waiter *pi_blocked_on; -/* Top pi_waiters task */ -struct task_struct *pi_top_task;#endif #ifdef CONFIG_DEBUG_MUTEXES
@@ -2788,7 +2786,7 @@ static inline bool __must_check current_set_polling_and_test(void)/* * Polling state must be visible before we test NEED_RESCHED, -* paired by resched_task() +* paired by resched_curr() */ smp_mb__after_atomic ();
@@ -2806,7 +2804,7 @@ static inline bool __must_check current_clr_polling_and_test(void)/* * Polling state must be visible before we test NEED_RESCHED, -* paired by resched_task() +* paired by resched_curr() */ smp_mb__after_atomic ();
@@ -2838,7 +2836,7 @@ static inline void current_clr_polling(void)* TIF_NEED_RESCHED and the IPI handler, scheduler_ipi(), will also * fold. */ -smp_mb ();/* paired with resched_task() */ +smp_mb ();/* paired with resched_curr() */ preempt_fold_need_resched (); }
include/linux/sunrpc/sched.h +1 -1
@@ -236,7 +236,7 @@ void * rpc_malloc(struct rpc_task *, size_t);void rpc_free (void *);int rpciod_up (void );void rpciod_down (void ); -int __rpc_wait_for_completion_task (struct rpc_task *task,int (*)(void *)); +int __rpc_wait_for_completion_task (struct rpc_task *task,wait_bit_action_f *);#ifdef RPC_DEBUG struct net ;void rpc_show_tasks (struct net *);
include/linux/tick.h +8 -1
@@ -181,7 +181,13 @@ static inline bool tick_nohz_full_cpu(int cpu)extern void tick_nohz_init (void );extern void __tick_nohz_full_check (void ); -extern void tick_nohz_full_kick (void ); +extern void tick_nohz_full_kick_cpu (int cpu); + +static inline void tick_nohz_full_kick (void ) +{ +tick_nohz_full_kick_cpu (smp_processor_id ()); +} +extern void tick_nohz_full_kick_all (void );extern void __tick_nohz_task_switch (struct task_struct *tsk);#else
@@ -189,6 +195,7 @@ static inline void tick_nohz_init(void) { }static inline bool tick_nohz_full_enabled (void ) {return false; }static inline bool tick_nohz_full_cpu (int cpu) {return false; }static inline void __tick_nohz_full_check (void ) { } +static inline void tick_nohz_full_kick_cpu (int cpu) { }static inline void tick_nohz_full_kick (void ) { }static inline void tick_nohz_full_kick_all (void ) { }static inline void __tick_nohz_task_switch (struct task_struct *tsk) { }
include/linux/wait.h +117 -8
177 lines not on this page · raw message
include/linux/writeback.h +1 -2
@@ -90,7 +90,6 @@ struct writeback_control {* fs/fs-writeback.c */ struct bdi_writeback ; -int inode_wait (void *);void writeback_inodes_sb (struct super_block *,enum wb_reason reason);void writeback_inodes_sb_nr (struct super_block *,unsigned long nr,enum wb_reason reason);
@@ -105,7 +104,7 @@ void inode_wait_for_writeback(struct inode *inode);static inline void wait_on_inode (struct inode *inode) {might_sleep (); -wait_on_bit (&inode->i_state, __I_NEW, inode_wait,TASK_UNINTERRUPTIBLE ); +wait_on_bit (&inode->i_state, __I_NEW,TASK_UNINTERRUPTIBLE ); }/*
kernel/cpu.c +20 -13
@@ -274,21 +274,28 @@ void clear_tasks_mm_cpumask(int cpu)rcu_read_unlock (); } -static inline void check_for_tasks (int cpu) +static inline void check_for_tasks (int dead_cpu) { -struct task_struct *p; -cputime_t utime, stime; +struct task_struct *g, *p; -write_lock_irq (&tasklist_lock); -for_each_process (p) { -task_cputime (p, &utime, &stime); -if (task_cpu (p) == cpu && p->state ==TASK_RUNNING && - (utime || stime)) -pr_warn ("Task %s (pid = %d) is on cpu %d (state = %ld, flags = %x)\n" , - p->comm,task_pid_nr (p), cpu, - p->state, p->flags); - } -write_unlock_irq (&tasklist_lock); +read_lock_irq (&tasklist_lock); + do_each_thread(g, p) { +if (!p->on_rq) +continue ; +/* +* We do the check with unlocked task_rq(p)->lock. +* Order the reading to do not warn about a task, +* which was running on this cpu in the past, and +* it's just been woken on another cpu. +*/ +rmb (); +if (task_cpu (p) != dead_cpu) +continue ; + +pr_warn ("Task %s (pid=%d) is on cpu %d (state=%ld, flags=%x)\n" , + p->comm,task_pid_nr (p), dead_cpu, p->state, p->flags); + }while_each_thread (g, p); +read_unlock_irq (&tasklist_lock); }struct take_cpu_down_param {
kernel/fork.c +0 -1
@@ -1095,7 +1095,6 @@ static void rt_mutex_init_task(struct task_struct *p) p->pi_waiters =RB_ROOT ; p->pi_waiters_leftmost =NULL ; p->pi_blocked_on =NULL ; - p->pi_top_task =NULL ;#endif }
kernel/irq_work.c +45 -65
169 lines not on this page · raw message
kernel/ptrace.c +1 -7
@@ -28,12 +28,6 @@#include <linux/compat.h> -static int ptrace_trapping_sleep_fn (void *flags) -{ -schedule (); -return 0 ; -} -/* * ptrace a task: make the debugger its new parent and * move it to the ptrace list.
@@ -371,7 +365,7 @@ unlock_creds: out:if (!retval) {wait_on_bit (&task->jobctl,JOBCTL_TRAPPING_BIT , - ptrace_trapping_sleep_fn,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE );proc_ptrace_connector (task,PTRACE_ATTACH ); }
kernel/sched/core.c +79 -40
291 lines not on this page · raw message
kernel/sched/deadline.c +9 -9
@@ -306,7 +306,7 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se,* the overrunning entity can't interfere with other entity in the system and * can't make them miss their deadlines. Reasons why this kind of overruns * could happen are, typically, a entity voluntarily trying to overcome its -* runtime, or it just underestimated it during sched_setscheduler_ex(). +* runtime, or it just underestimated it during sched_setattr(). */ static void replenish_dl_entity (struct sched_dl_entity *dl_se,struct sched_dl_entity *pi_se)
@@ -535,7 +535,7 @@ again:if (task_has_dl_policy (rq->curr))check_preempt_curr_dl (rq, p,0 );else -resched_task (rq->curr); +resched_curr (rq);#ifdef CONFIG_SMP /* * Queueing this task back might have overloaded rq,
@@ -634,7 +634,7 @@ static void update_curr_dl(struct rq *rq)enqueue_task_dl (rq, curr,ENQUEUE_REPLENISH );if (!is_leftmost (curr, &rq->dl)) -resched_task (curr); +resched_curr (rq); }/*
@@ -964,7 +964,7 @@ static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p) cpudl_find(&rq->rd->cpudl, p, NULL) != -1) return; -resched_task (rq->curr); +resched_curr (rq); }static int pull_dl_task (struct rq *this_rq);
@@ -979,7 +979,7 @@ static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p, int flags) {if (dl_entity_preempt (&p->dl, &rq->curr->dl)) { -resched_task (rq->curr); +resched_curr (rq);return ; }
@@ -1333,7 +1333,7 @@ retry:if (dl_task (rq->curr) &&dl_time_before (next_task->dl.deadline, rq->curr->dl.deadline) && rq->curr->nr_cpus_allowed >1 ) { -resched_task (rq->curr); +resched_curr (rq);return 0 ; }
@@ -1373,7 +1373,7 @@ retry:set_task_cpu (next_task, later_rq->cpu);activate_task (later_rq, next_task,0 ); -resched_task (later_rq->curr); +resched_curr (later_rq);double_unlock_balance (rq, later_rq);
@@ -1632,14 +1632,14 @@ static void prio_changed_dl(struct rq *rq, struct task_struct *p,*/ if (dl_time_before (rq->dl.earliest_dl.curr, p->dl.deadline) && rq->curr == p) -resched_task (p); +resched_curr (rq);#else /* * Again, we don't know if p has a earlier * or later deadline, so let's blindly set a * (maybe not needed) rescheduling point. */ -resched_task (p); +resched_curr (rq);#endif /* CONFIG_SMP */ }else switched_to_dl (rq, p);
kernel/sched/fair.c +148 -96
543 lines not on this page · raw message
kernel/sched/idle.c +2 -2
@@ -79,7 +79,7 @@ static void cpuidle_idle_call(void)struct cpuidle_device *dev =__this_cpu_read (cpuidle_devices);struct cpuidle_driver *drv =cpuidle_get_cpu_driver (dev);int next_state, entered_state; -bool broadcast; +unsigned int broadcast;/* * Check if the idle task must be rescheduled. If it is the
@@ -135,7 +135,7 @@ use_default: goto exit_idle; } - broadcast = !!(drv->states[next_state].flags &CPUIDLE_FLAG_TIMER_STOP ); + broadcast = drv->states[next_state].flags &CPUIDLE_FLAG_TIMER_STOP ;/* * Tell the time framework to switch to a broadcast timer
kernel/sched/idle_task.c +1 -1
@@ -20,7 +20,7 @@ select_task_rq_idle(struct task_struct *p, int cpu, int sd_flag, int flags)*/ static void check_preempt_curr_idle (struct rq *rq,struct task_struct *p,int flags) { -resched_task (rq->idle); +resched_curr (rq); } static struct task_struct *
kernel/sched/rt.c +17 -13
@@ -463,9 +463,10 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se);static void sched_rt_rq_enqueue (struct rt_rq *rt_rq) {struct task_struct *curr =rq_of_rt_rq (rt_rq)->curr; +struct rq *rq =rq_of_rt_rq (rt_rq);struct sched_rt_entity *rt_se; -int cpu =cpu_of (rq_of_rt_rq (rt_rq)); +int cpu =cpu_of (rq); rt_se = rt_rq->tg->rt_se[cpu];
@@ -476,7 +477,7 @@ static void sched_rt_rq_enqueue(struct rt_rq *rt_rq)enqueue_rt_entity (rt_se, false);if (rt_rq->highest_prio.curr < curr->prio) -resched_task (curr); +resched_curr (rq); } }
@@ -566,7 +567,7 @@ static inline void sched_rt_rq_enqueue(struct rt_rq *rt_rq)return ;enqueue_top_rt_rq (rt_rq); -resched_task (rq->curr); +resched_curr (rq); }static inline void sched_rt_rq_dequeue (struct rt_rq *rt_rq)
@@ -740,6 +741,9 @@ balanced: rt_rq->rt_throttled =0 ;raw_spin_unlock (&rt_rq->rt_runtime_lock);raw_spin_unlock (&rt_b->rt_runtime_lock); + +/* Make rt_rq available for pick_next_task() */ +sched_rt_rq_enqueue (rt_rq); } }
@@ -948,7 +952,7 @@ static void update_curr_rt(struct rq *rq)raw_spin_lock (&rt_rq->rt_runtime_lock); rt_rq->rt_time += delta_exec;if (sched_rt_runtime_exceeded (rt_rq)) -resched_task (curr); +resched_curr (rq);raw_spin_unlock (&rt_rq->rt_runtime_lock); } }
@@ -1363,7 +1367,7 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)* to try and push current away: */ requeue_task_rt (rq, p,1 ); - resched_task(rq->curr); + resched_curr(rq); }#endif /* CONFIG_SMP */
@@ -1374,7 +1378,7 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)static void check_preempt_curr_rt (struct rq *rq,struct task_struct *p,int flags) {if (p->prio < rq->curr->prio) { -resched_task (rq->curr); +resched_curr (rq);return ; }
@@ -1690,7 +1694,7 @@ retry:* just reschedule current. */ if (unlikely (next_task->prio < rq->curr->prio)) { -resched_task (rq->curr); +resched_curr (rq);return 0 ; }
@@ -1737,7 +1741,7 @@ retry:activate_task (lowest_rq, next_task,0 ); ret =1 ; -resched_task (lowest_rq->curr); +resched_curr (lowest_rq);double_unlock_balance (rq, lowest_rq);
@@ -1936,7 +1940,7 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p)return ;if (pull_rt_task (rq)) -resched_task (rq->curr); +resched_curr (rq); }void __init init_sched_rt_class (void )
@@ -1974,7 +1978,7 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p) check_resched =0 ;#endif /* CONFIG_SMP */ if (check_resched && p->prio < rq->curr->prio) -resched_task (rq->curr); +resched_curr (rq); } }
@@ -2003,11 +2007,11 @@ prio_changed_rt(struct rq *rq, struct task_struct *p, int oldprio)* Only reschedule if p is still on the same runqueue. */ if (p->prio > rq->rt.highest_prio.curr && rq->curr == p) -resched_task (p); +resched_curr (rq);#else /* For UP simply resched on drop of prio */ if (oldprio < p->prio) -resched_task (p); +resched_curr (rq);#endif /* CONFIG_SMP */ }else {/*
@@ -2016,7 +2020,7 @@ prio_changed_rt(struct rq *rq, struct task_struct *p, int oldprio)* then reschedule. */ if (p->prio < rq->curr->prio) -resched_task (rq->curr); +resched_curr (rq); } }
kernel/sched/sched.h +21 -17
@@ -477,6 +477,9 @@ struct root_domain {cpumask_var_t span;cpumask_var_t online; +/* Indicate more than one runnable task for any CPU */ +bool overload; +/* * The bit corresponding to a CPU gets set here if such CPU has more * than one runnable -deadline task (as it is below for RT tasks).
@@ -884,20 +887,10 @@ enum {#undef SCHED_FEAT#if defined(CONFIG_SCHED_DEBUG ) && defined(HAVE_JUMP_LABEL ) -static __always_inline bool static_branch__true(struct static_key *key) -{ -return static_key_true (key);/* Not out of line branch. */ -} - -static __always_inline bool static_branch__false(struct static_key *key) -{ -return static_key_false (key);/* Out of line branch. */ -} -#define SCHED_FEAT (name, enabled) \ static __always_inline bool static_branch_##name(struct static_key *key) \ { \ - return static_branch__##enabled(key); \ + return static_key_##enabled(key); \ }#include "features.h"
@@ -1196,7 +1189,7 @@ extern void init_sched_rt_class(void);extern void init_sched_fair_class (void );extern void init_sched_dl_class (void ); -extern void resched_task (struct task_struct *p); +extern void resched_curr (struct rq *rq);extern void resched_cpu (int cpu);extern struct rt_bandwidth def_rt_bandwidth;
@@ -1218,15 +1211,26 @@ static inline void add_nr_running(struct rq *rq, unsigned count) rq->nr_running = prev_nr + count; -#ifdef CONFIG_NO_HZ_FULL if (prev_nr <2 && rq->nr_running >=2 ) { +#ifdef CONFIG_SMP +if (!rq->rd->overload) + rq->rd->overload = true; +#endif + +#ifdef CONFIG_NO_HZ_FULL if (tick_nohz_full_cpu (rq->cpu)) { -/* Order rq->nr_running write against the IPI */ -smp_wmb (); -smp_send_reschedule (rq->cpu); +/* +* Tick is needed if more than one task runs on a CPU. +* Send the target an IPI to kick it out of nohz mode. +* +* We assume that IPI implies full memory barrier and the +* new value of rq->nr_running is visible on reception +* from the target. +*/ +tick_nohz_full_kick_cpu (rq->cpu); } - }#endif + } }static inline void sub_nr_running (struct rq *rq,unsigned count)
kernel/sched/wait.c +24 -6
@@ -319,14 +319,14 @@ EXPORT_SYMBOL(wake_bit_function);*/ int __sched__wait_on_bit (wait_queue_head_t *wq,struct wait_bit_queue *q, -int (*action)(void *),unsigned mode) +wait_bit_action_f *action,unsigned mode) {int ret =0 ;do {prepare_to_wait (wq, &q->wait, mode);if (test_bit (q->key.bit_nr, q->key.flags)) - ret = (*action)(q->key.flags); + ret = (*action)(&q->key); }while (test_bit (q->key.bit_nr, q->key.flags) && !ret);finish_wait (wq, &q->wait);return ret;
@@ -334,7 +334,7 @@ __wait_on_bit(wait_queue_head_t *wq, struct wait_bit_queue *q,EXPORT_SYMBOL (__wait_on_bit); int __sched out_of_line_wait_on_bit(void *word, int bit, -int (*action)(void *),unsigned mode) +wait_bit_action_f *action,unsigned mode) {wait_queue_head_t *wq =bit_waitqueue (word, bit);DEFINE_WAIT_BIT (wait, word, bit);
@@ -345,7 +345,7 @@ EXPORT_SYMBOL(out_of_line_wait_on_bit); int __sched__wait_on_bit_lock (wait_queue_head_t *wq,struct wait_bit_queue *q, -int (*action)(void *),unsigned mode) +wait_bit_action_f *action,unsigned mode) { do { int ret;
@@ -353,7 +353,7 @@ __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,prepare_to_wait_exclusive (wq, &q->wait, mode);if (!test_bit (q->key.bit_nr, q->key.flags))continue ; - ret =action (q->key.flags); + ret =action (&q->key);if (!ret)continue ;abort_exclusive_wait (wq, &q->wait, mode, &q->key);
@@ -365,7 +365,7 @@ __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,EXPORT_SYMBOL (__wait_on_bit_lock); int __sched out_of_line_wait_on_bit_lock(void *word, int bit, -int (*action)(void *),unsigned mode) +wait_bit_action_f *action,unsigned mode) {wait_queue_head_t *wq =bit_waitqueue (word, bit);DEFINE_WAIT_BIT (wait, word, bit);
@@ -502,3 +502,21 @@ void wake_up_atomic_t(atomic_t *p)__wake_up_bit (atomic_t_waitqueue (p), p,WAIT_ATOMIC_T_BIT_NR ); }EXPORT_SYMBOL (wake_up_atomic_t); + +__sched int bit_wait(struct wait_bit_key *word) +{ +if (signal_pending_state (current->state, current)) +return 1 ; +schedule (); +return 0 ; +} +EXPORT_SYMBOL (bit_wait); + +__sched int bit_wait_io(struct wait_bit_key *word) +{ +if (signal_pending_state (current->state, current)) +return 1 ; +io_schedule (); +return 0 ; +} +EXPORT_SYMBOL (bit_wait_io);
kernel/smp.c +9 -0
@@ -3,6 +3,7 @@* * (C) Jens Axboe <[email protected]> 2008 */ +#include <linux/irq_work.h> #include <linux/rcupdate.h> #include <linux/rculist.h> #include <linux/kernel.h>
@@ -251,6 +252,14 @@ static void flush_smp_call_function_queue(bool warn_cpu_offline) csd->func (csd->info);csd_unlock (csd); } + +/* +* Handle irq works queued remotely by irq_work_queue_on(). +* Smp functions above are typically synchronous so they +* better run first since some other CPUs may be busy waiting +* for them. +*/ +irq_work_run (); }/*
kernel/time/tick-sched.c +6 -4
@@ -224,13 +224,15 @@ static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) = { };/* -* Kick the current CPU if it's full dynticks in order to force it to +* Kick the CPU if it's full dynticks in order to force it to * re-evaluate its dependency on the tick and restart it if necessary. */ -void tick_nohz_full_kick (void ) +void tick_nohz_full_kick_cpu (int cpu) { -if (tick_nohz_full_cpu (smp_processor_id ())) -irq_work_queue (&__get_cpu_var (nohz_full_kick_work)); +if (!tick_nohz_full_cpu (cpu)) +return ; + +irq_work_queue_on (&per_cpu (nohz_full_kick_work, cpu), cpu); }static void nohz_full_kick_ipi (void *info)
mm/filemap.c +4 -16
@@ -241,18 +241,6 @@ void delete_from_page_cache(struct page *page) }EXPORT_SYMBOL (delete_from_page_cache); -static int sleep_on_page (void *word) -{ -io_schedule (); -return 0 ; -} - -static int sleep_on_page_killable (void *word) -{ -sleep_on_page (word); -return fatal_signal_pending (current) ? -EINTR :0 ; -} -static int filemap_check_errors (struct address_space *mapping) {int ret =0 ;
@@ -692,7 +680,7 @@ void wait_on_page_bit(struct page *page, int bit_nr)DEFINE_WAIT_BIT (wait, &page->flags, bit_nr);if (test_bit (bit_nr, &page->flags)) -__wait_on_bit (page_waitqueue (page), &wait, sleep_on_page, +__wait_on_bit (page_waitqueue (page), &wait, bit_wait_io,TASK_UNINTERRUPTIBLE ); }EXPORT_SYMBOL (wait_on_page_bit);
@@ -705,7 +693,7 @@ int wait_on_page_bit_killable(struct page *page, int bit_nr)return 0 ;return __wait_on_bit (page_waitqueue (page), &wait, - sleep_on_page_killable,TASK_KILLABLE ); + bit_wait_io,TASK_KILLABLE ); }/**
@@ -806,7 +794,7 @@ void __lock_page(struct page *page) {DEFINE_WAIT_BIT (wait, &page->flags, PG_locked); -__wait_on_bit_lock (page_waitqueue (page), &wait, sleep_on_page, +__wait_on_bit_lock (page_waitqueue (page), &wait, bit_wait_io,TASK_UNINTERRUPTIBLE ); }EXPORT_SYMBOL (__lock_page);
@@ -816,7 +804,7 @@ int __lock_page_killable(struct page *page)DEFINE_WAIT_BIT (wait, &page->flags, PG_locked);return __wait_on_bit_lock (page_waitqueue (page), &wait, - sleep_on_page_killable,TASK_KILLABLE ); + bit_wait_io,TASK_KILLABLE ); }EXPORT_SYMBOL_GPL (__lock_page_killable);
mm/ksm.c +1 -7
@@ -1978,18 +1978,12 @@ void ksm_migrate_page(struct page *newpage, struct page *oldpage)#endif /* CONFIG_MIGRATION */ #ifdef CONFIG_MEMORY_HOTREMOVE -static int just_wait (void *word) -{ -schedule (); -return 0 ; -} -static void wait_while_offlining (void ) {while (ksm_run &KSM_RUN_OFFLINE ) {mutex_unlock (&ksm_thread_mutex);wait_on_bit (&ksm_run,ilog2 (KSM_RUN_OFFLINE ), - just_wait,TASK_UNINTERRUPTIBLE ); +TASK_UNINTERRUPTIBLE );mutex_lock (&ksm_thread_mutex); } }
net/bluetooth/hci_core.c +1 -7
@@ -2186,12 +2186,6 @@ static void hci_inq_req(struct hci_request *req, unsigned long opt)hci_req_add (req,HCI_OP_INQUIRY ,sizeof (cp), &cp); } -static int wait_inquiry (void *word) -{ -schedule (); -return signal_pending (current); -} -int hci_inquiry (void __user *arg) {__u8 __user *ptr = arg;
@@ -2242,7 +2236,7 @@ int hci_inquiry(void __user *arg)/* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is * cleared). If it is interrupted by a signal, return -EINTR. */ -if (wait_on_bit (&hdev->flags,HCI_INQUIRY , wait_inquiry, +if (wait_on_bit (&hdev->flags,HCI_INQUIRY ,TASK_INTERRUPTIBLE ))return -EINTR ; }
net/sunrpc/sched.c +2 -2
@@ -250,7 +250,7 @@ void rpc_destroy_wait_queue(struct rpc_wait_queue *queue) }EXPORT_SYMBOL_GPL (rpc_destroy_wait_queue); -static int rpc_wait_bit_killable (void *word) +static int rpc_wait_bit_killable (struct wait_bit_key *key) {if (fatal_signal_pending (current))return -ERESTARTSYS ;
@@ -309,7 +309,7 @@ static int rpc_complete_task(struct rpc_task *task)* to enforce taking of the wq->lock and hence avoid races with * rpc_complete_task(). */ -int __rpc_wait_for_completion_task (struct rpc_task *task,int (*action)(void *)) +int __rpc_wait_for_completion_task (struct rpc_task *task,wait_bit_action_f *action) {if (action ==NULL ) action = rpc_wait_bit_killable;
security/keys/gc.c +1 -10
@@ -92,15 +92,6 @@ static void key_gc_timer_func(unsigned long data) }/* -* wait_on_bit() sleep function for uninterruptible waiting -*/ -static int key_gc_wait_bit (void *flags) -{ -schedule (); -return 0 ; -} - -/* * Reap keys of dead type. * * We use three flags to make sure we see three complete cycles of the garbage
@@ -123,7 +114,7 @@ void key_gc_keytype(struct key_type *ktype)schedule_work (&key_gc_work);kdebug ("sleep" ); -wait_on_bit (&key_gc_flags,KEY_GC_REAPING_KEYTYPE , key_gc_wait_bit, +wait_on_bit (&key_gc_flags,KEY_GC_REAPING_KEYTYPE ,TASK_UNINTERRUPTIBLE ); key_gc_dead_keytype =NULL ;
security/keys/request_key.c +2 -21
@@ -21,24 +21,6 @@#define key_negative_timeout 60/* default timeout on a negative key's existence */ -/* -* wait_on_bit() sleep function for uninterruptible waiting -*/ -static int key_wait_bit (void *flags) -{ -schedule (); -return 0 ; -} - -/* -* wait_on_bit() sleep function for interruptible waiting -*/ -static int key_wait_bit_intr (void *flags) -{ -schedule (); -return signal_pending (current) ? -ERESTARTSYS :0 ; -} -/** * complete_request_key - Complete the construction of a key. * @cons: The key construction record.
@@ -592,10 +574,9 @@ int wait_for_key_construction(struct key *key, bool intr)int ret; ret =wait_on_bit (&key->flags,KEY_FLAG_USER_CONSTRUCT , - intr ? key_wait_bit_intr : key_wait_bit, intr ?TASK_INTERRUPTIBLE :TASK_UNINTERRUPTIBLE ); -if (ret <0 ) -return ret; +if (ret) +return -ERESTARTSYS ;if (test_bit (KEY_FLAG_NEGATIVE , &key->flags)) {smp_rmb ();return key->type_data.reject_error;