diff options
Diffstat (limited to 'include/linux/sched.h')
| -rw-r--r-- | include/linux/sched.h | 110 | 
1 files changed, 83 insertions, 27 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 68daf4f27e2c..21cd0303af51 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -220,7 +220,7 @@ extern char ___assert_task_state[1 - 2*!!(  			((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)  #define task_contributes_to_load(task)	\  				((task->state & TASK_UNINTERRUPTIBLE) != 0 && \ -				 (task->flags & PF_FREEZING) == 0) +				 (task->flags & PF_FROZEN) == 0)  #define __set_task_state(tsk, state_value)		\  	do { (tsk)->state = (state_value); } while (0) @@ -273,9 +273,11 @@ extern int runqueue_is_locked(int cpu);  #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)  extern void select_nohz_load_balancer(int stop_tick); +extern void set_cpu_sd_state_idle(void);  extern int get_nohz_timer_target(void);  #else  static inline void select_nohz_load_balancer(int stop_tick) { } +static inline void set_cpu_sd_state_idle(void) { }  #endif  /* @@ -483,8 +485,8 @@ struct task_cputime {  #define INIT_CPUTIME	\  	(struct task_cputime) {					\ -		.utime = cputime_zero,				\ -		.stime = cputime_zero,				\ +		.utime = 0,					\ +		.stime = 0,					\  		.sum_exec_runtime = 0,				\  	} @@ -635,13 +637,15 @@ struct signal_struct {  #endif  #ifdef CONFIG_CGROUPS  	/* -	 * The threadgroup_fork_lock prevents threads from forking with -	 * CLONE_THREAD while held for writing. Use this for fork-sensitive -	 * threadgroup-wide operations. It's taken for reading in fork.c in -	 * copy_process(). -	 * Currently only needed write-side by cgroups. +	 * group_rwsem prevents new tasks from entering the threadgroup and +	 * member tasks from exiting,a more specifically, setting of +	 * PF_EXITING.  fork and exit paths are protected with this rwsem +	 * using threadgroup_change_begin/end().  Users which require +	 * threadgroup to remain stable should use threadgroup_[un]lock() +	 * which also takes care of exec path.  Currently, cgroup is the +	 * only user.  	 */ -	struct rw_semaphore threadgroup_fork_lock; +	struct rw_semaphore group_rwsem;  #endif  	int oom_adj;		/* OOM kill score adjustment (bit shift) */ @@ -901,6 +905,10 @@ struct sched_group_power {  	 * single CPU.  	 */  	unsigned int power, power_orig; +	/* +	 * Number of busy cpus in this group. +	 */ +	atomic_t nr_busy_cpus;  };  struct sched_group { @@ -925,6 +933,15 @@ static inline struct cpumask *sched_group_cpus(struct sched_group *sg)  	return to_cpumask(sg->cpumask);  } +/** + * group_first_cpu - Returns the first cpu in the cpumask of a sched_group. + * @group: The group whose first cpu is to be returned. + */ +static inline unsigned int group_first_cpu(struct sched_group *group) +{ +	return cpumask_first(sched_group_cpus(group)); +} +  struct sched_domain_attr {  	int relax_domain_level;  }; @@ -1315,8 +1332,8 @@ struct task_struct {  	 * older sibling, respectively.  (p->father can be replaced with   	 * p->real_parent->pid)  	 */ -	struct task_struct *real_parent; /* real parent process */ -	struct task_struct *parent; /* recipient of SIGCHLD, wait4() reports */ +	struct task_struct __rcu *real_parent; /* real parent process */ +	struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */  	/*  	 * children/sibling forms the list of my natural children  	 */ @@ -1521,13 +1538,13 @@ struct task_struct {  #ifdef CONFIG_FAULT_INJECTION  	int make_it_fail;  #endif -	struct prop_local_single dirties;  	/*  	 * when (nr_dirtied >= nr_dirtied_pause), it's time to call  	 * balance_dirty_pages() for some dirty throttling pause  	 */  	int nr_dirtied;  	int nr_dirtied_pause; +	unsigned long dirty_paused_when; /* start of a write-and-pause period */  #ifdef CONFIG_LATENCYTOP  	int latency_record_count; @@ -1773,7 +1790,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *  #define PF_MEMALLOC	0x00000800	/* Allocating memory */  #define PF_NPROC_EXCEEDED 0x00001000	/* set_user noticed that RLIMIT_NPROC was exceeded */  #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */ -#define PF_FREEZING	0x00004000	/* freeze in progress. do not account to load */  #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */  #define PF_FROZEN	0x00010000	/* frozen for system suspend */  #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */ @@ -1789,7 +1805,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *  #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */  #define PF_MUTEX_TESTER	0x20000000	/* Thread belongs to the rt mutex tester */  #define PF_FREEZER_SKIP	0x40000000	/* Freezer should not count it as freezable */ -#define PF_FREEZER_NOSIG 0x80000000	/* Freezer won't send signals to it */  /*   * Only the _current_ task can read/write to tsk->flags, but other @@ -2071,6 +2086,14 @@ extern int sched_setscheduler(struct task_struct *, int,  extern int sched_setscheduler_nocheck(struct task_struct *, int,  				      const struct sched_param *);  extern struct task_struct *idle_task(int cpu); +/** + * is_idle_task - is the specified task an idle task? + * @tsk: the task in question. + */ +static inline bool is_idle_task(struct task_struct *p) +{ +	return p->pid == 0; +}  extern struct task_struct *curr_task(int cpu);  extern void set_curr_task(int cpu, struct task_struct *p); @@ -2374,29 +2397,62 @@ static inline void unlock_task_sighand(struct task_struct *tsk,  	spin_unlock_irqrestore(&tsk->sighand->siglock, *flags);  } -/* See the declaration of threadgroup_fork_lock in signal_struct. */  #ifdef CONFIG_CGROUPS -static inline void threadgroup_fork_read_lock(struct task_struct *tsk) +static inline void threadgroup_change_begin(struct task_struct *tsk)  { -	down_read(&tsk->signal->threadgroup_fork_lock); +	down_read(&tsk->signal->group_rwsem);  } -static inline void threadgroup_fork_read_unlock(struct task_struct *tsk) +static inline void threadgroup_change_end(struct task_struct *tsk)  { -	up_read(&tsk->signal->threadgroup_fork_lock); +	up_read(&tsk->signal->group_rwsem);  } -static inline void threadgroup_fork_write_lock(struct task_struct *tsk) + +/** + * threadgroup_lock - lock threadgroup + * @tsk: member task of the threadgroup to lock + * + * Lock the threadgroup @tsk belongs to.  No new task is allowed to enter + * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or + * perform exec.  This is useful for cases where the threadgroup needs to + * stay stable across blockable operations. + * + * fork and exit paths explicitly call threadgroup_change_{begin|end}() for + * synchronization.  While held, no new task will be added to threadgroup + * and no existing live task will have its PF_EXITING set. + * + * During exec, a task goes and puts its thread group through unusual + * changes.  After de-threading, exclusive access is assumed to resources + * which are usually shared by tasks in the same group - e.g. sighand may + * be replaced with a new one.  Also, the exec'ing task takes over group + * leader role including its pid.  Exclude these changes while locked by + * grabbing cred_guard_mutex which is used to synchronize exec path. + */ +static inline void threadgroup_lock(struct task_struct *tsk)  { -	down_write(&tsk->signal->threadgroup_fork_lock); +	/* +	 * exec uses exit for de-threading nesting group_rwsem inside +	 * cred_guard_mutex. Grab cred_guard_mutex first. +	 */ +	mutex_lock(&tsk->signal->cred_guard_mutex); +	down_write(&tsk->signal->group_rwsem);  } -static inline void threadgroup_fork_write_unlock(struct task_struct *tsk) + +/** + * threadgroup_unlock - unlock threadgroup + * @tsk: member task of the threadgroup to unlock + * + * Reverse threadgroup_lock(). + */ +static inline void threadgroup_unlock(struct task_struct *tsk)  { -	up_write(&tsk->signal->threadgroup_fork_lock); +	up_write(&tsk->signal->group_rwsem); +	mutex_unlock(&tsk->signal->cred_guard_mutex);  }  #else -static inline void threadgroup_fork_read_lock(struct task_struct *tsk) {} -static inline void threadgroup_fork_read_unlock(struct task_struct *tsk) {} -static inline void threadgroup_fork_write_lock(struct task_struct *tsk) {} -static inline void threadgroup_fork_write_unlock(struct task_struct *tsk) {} +static inline void threadgroup_change_begin(struct task_struct *tsk) {} +static inline void threadgroup_change_end(struct task_struct *tsk) {} +static inline void threadgroup_lock(struct task_struct *tsk) {} +static inline void threadgroup_unlock(struct task_struct *tsk) {}  #endif  #ifndef __HAVE_THREAD_FUNCTIONS  | 
