diff options
Diffstat (limited to 'mm/oom_kill.c')
| -rw-r--r-- | mm/oom_kill.c | 86 | 
1 files changed, 19 insertions, 67 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 79e0f3e2483..18f1ae2b45d 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -44,48 +44,6 @@ int sysctl_oom_kill_allocating_task;  int sysctl_oom_dump_tasks = 1;  static DEFINE_SPINLOCK(zone_scan_lock); -/* - * compare_swap_oom_score_adj() - compare and swap current's oom_score_adj - * @old_val: old oom_score_adj for compare - * @new_val: new oom_score_adj for swap - * - * Sets the oom_score_adj value for current to @new_val iff its present value is - * @old_val.  Usually used to reinstate a previous value to prevent racing with - * userspacing tuning the value in the interim. - */ -void compare_swap_oom_score_adj(int old_val, int new_val) -{ -	struct sighand_struct *sighand = current->sighand; - -	spin_lock_irq(&sighand->siglock); -	if (current->signal->oom_score_adj == old_val) -		current->signal->oom_score_adj = new_val; -	trace_oom_score_adj_update(current); -	spin_unlock_irq(&sighand->siglock); -} - -/** - * test_set_oom_score_adj() - set current's oom_score_adj and return old value - * @new_val: new oom_score_adj value - * - * Sets the oom_score_adj value for current to @new_val with proper - * synchronization and returns the old value.  Usually used to temporarily - * set a value, save the old value in the caller, and then reinstate it later. - */ -int test_set_oom_score_adj(int new_val) -{ -	struct sighand_struct *sighand = current->sighand; -	int old_val; - -	spin_lock_irq(&sighand->siglock); -	old_val = current->signal->oom_score_adj; -	current->signal->oom_score_adj = new_val; -	trace_oom_score_adj_update(current); -	spin_unlock_irq(&sighand->siglock); - -	return old_val; -} -  #ifdef CONFIG_NUMA  /**   * has_intersects_mems_allowed() - check task eligiblity for kill @@ -193,7 +151,7 @@ unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg,  	if (!p)  		return 0; -	adj = p->signal->oom_score_adj; +	adj = (long)p->signal->oom_score_adj;  	if (adj == OOM_SCORE_ADJ_MIN) {  		task_unlock(p);  		return 0; @@ -310,26 +268,20 @@ enum oom_scan_t oom_scan_process_thread(struct task_struct *task,  	if (!task->mm)  		return OOM_SCAN_CONTINUE; -	if (task->flags & PF_EXITING) { +	/* +	 * If task is allocating a lot of memory and has been marked to be +	 * killed first if it triggers an oom, then select it. +	 */ +	if (oom_task_origin(task)) +		return OOM_SCAN_SELECT; + +	if (task->flags & PF_EXITING && !force_kill) {  		/* -		 * If task is current and is in the process of releasing memory, -		 * allow the "kill" to set TIF_MEMDIE, which will allow it to -		 * access memory reserves.  Otherwise, it may stall forever. -		 * -		 * The iteration isn't broken here, however, in case other -		 * threads are found to have already been oom killed. +		 * If this task is not being ptraced on exit, then wait for it +		 * to finish before killing some other task unnecessarily.  		 */ -		if (task == current) -			return OOM_SCAN_SELECT; -		else if (!force_kill) { -			/* -			 * If this task is not being ptraced on exit, then wait -			 * for it to finish before killing some other task -			 * unnecessarily. -			 */ -			if (!(task->group_leader->ptrace & PT_TRACE_EXIT)) -				return OOM_SCAN_ABORT; -		} +		if (!(task->group_leader->ptrace & PT_TRACE_EXIT)) +			return OOM_SCAN_ABORT;  	}  	return OOM_SCAN_OK;  } @@ -412,7 +364,7 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas  			continue;  		} -		pr_info("[%5d] %5d %5d %8lu %8lu %7lu %8lu         %5d %s\n", +		pr_info("[%5d] %5d %5d %8lu %8lu %7lu %8lu         %5hd %s\n",  			task->pid, from_kuid(&init_user_ns, task_uid(task)),  			task->tgid, task->mm->total_vm, get_mm_rss(task->mm),  			task->mm->nr_ptes, @@ -428,7 +380,7 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,  {  	task_lock(current);  	pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, " -		"oom_score_adj=%d\n", +		"oom_score_adj=%hd\n",  		current->comm, gfp_mask, order,  		current->signal->oom_score_adj);  	cpuset_print_task_mems_allowed(current); @@ -706,11 +658,11 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,  		return;  	/* -	 * If current has a pending SIGKILL, then automatically select it.  The -	 * goal is to allow it to allocate so that it may quickly exit and free -	 * its memory. +	 * If current has a pending SIGKILL or is exiting, then automatically +	 * select it.  The goal is to allow it to allocate so that it may +	 * quickly exit and free its memory.  	 */ -	if (fatal_signal_pending(current)) { +	if (fatal_signal_pending(current) || current->flags & PF_EXITING) {  		set_thread_flag(TIF_MEMDIE);  		return;  	}  |