18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* Function to determine if a thread group is single threaded or not 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 68c2ecf20Sopenharmony_ci * - Derived from security/selinux/hooks.c 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 98c2ecf20Sopenharmony_ci#include <linux/sched/task.h> 108c2ecf20Sopenharmony_ci#include <linux/sched/mm.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* 138c2ecf20Sopenharmony_ci * Returns true if the task does not share ->mm with another thread/process. 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_cibool current_is_single_threaded(void) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct task_struct *task = current; 188c2ecf20Sopenharmony_ci struct mm_struct *mm = task->mm; 198c2ecf20Sopenharmony_ci struct task_struct *p, *t; 208c2ecf20Sopenharmony_ci bool ret; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci if (atomic_read(&task->signal->live) != 1) 238c2ecf20Sopenharmony_ci return false; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci if (atomic_read(&mm->mm_users) == 1) 268c2ecf20Sopenharmony_ci return true; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci ret = false; 298c2ecf20Sopenharmony_ci rcu_read_lock(); 308c2ecf20Sopenharmony_ci for_each_process(p) { 318c2ecf20Sopenharmony_ci if (unlikely(p->flags & PF_KTHREAD)) 328c2ecf20Sopenharmony_ci continue; 338c2ecf20Sopenharmony_ci if (unlikely(p == task->group_leader)) 348c2ecf20Sopenharmony_ci continue; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci for_each_thread(p, t) { 378c2ecf20Sopenharmony_ci if (unlikely(t->mm == mm)) 388c2ecf20Sopenharmony_ci goto found; 398c2ecf20Sopenharmony_ci if (likely(t->mm)) 408c2ecf20Sopenharmony_ci break; 418c2ecf20Sopenharmony_ci /* 428c2ecf20Sopenharmony_ci * t->mm == NULL. Make sure next_thread/next_task 438c2ecf20Sopenharmony_ci * will see other CLONE_VM tasks which might be 448c2ecf20Sopenharmony_ci * forked before exiting. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci smp_rmb(); 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci ret = true; 508c2ecf20Sopenharmony_cifound: 518c2ecf20Sopenharmony_ci rcu_read_unlock(); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return ret; 548c2ecf20Sopenharmony_ci} 55