mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 00:28:52 +02:00 
			
		
		
		
	 907565337e
			
		
	
	
		907565337e
		
	
	
	
	
		
			
			Userspace applications should be allowed to expect the membarrier system call with MEMBARRIER_CMD_SHARED command to issue memory barriers on nohz_full CPUs, but synchronize_sched() does not take those into account. Given that we do not want unrelated processes to be able to affect real-time sensitive nohz_full CPUs, simply return ENOSYS when membarrier is invoked on a kernel with enabled nohz_full CPUs. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> CC: Josh Triplett <josh@joshtriplett.org> CC: Steven Rostedt <rostedt@goodmis.org> CC: <stable@vger.kernel.org> [3.10+] Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Chris Metcalf <cmetcalf@mellanox.com> Cc: Rik van Riel <riel@redhat.com> Acked-by: Lai Jiangshan <jiangshanlai@gmail.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
		
			
				
	
	
		
			70 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2010, 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
 | |
|  *
 | |
|  * membarrier system call
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License as published by
 | |
|  * the Free Software Foundation; either version 2 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
|  */
 | |
| 
 | |
| #include <linux/syscalls.h>
 | |
| #include <linux/membarrier.h>
 | |
| #include <linux/tick.h>
 | |
| 
 | |
| /*
 | |
|  * Bitmask made from a "or" of all commands within enum membarrier_cmd,
 | |
|  * except MEMBARRIER_CMD_QUERY.
 | |
|  */
 | |
| #define MEMBARRIER_CMD_BITMASK	(MEMBARRIER_CMD_SHARED)
 | |
| 
 | |
| /**
 | |
|  * sys_membarrier - issue memory barriers on a set of threads
 | |
|  * @cmd:   Takes command values defined in enum membarrier_cmd.
 | |
|  * @flags: Currently needs to be 0. For future extensions.
 | |
|  *
 | |
|  * If this system call is not implemented, -ENOSYS is returned. If the
 | |
|  * command specified does not exist, or if the command argument is invalid,
 | |
|  * this system call returns -EINVAL. For a given command, with flags argument
 | |
|  * set to 0, this system call is guaranteed to always return the same value
 | |
|  * until reboot.
 | |
|  *
 | |
|  * All memory accesses performed in program order from each targeted thread
 | |
|  * is guaranteed to be ordered with respect to sys_membarrier(). If we use
 | |
|  * the semantic "barrier()" to represent a compiler barrier forcing memory
 | |
|  * accesses to be performed in program order across the barrier, and
 | |
|  * smp_mb() to represent explicit memory barriers forcing full memory
 | |
|  * ordering across the barrier, we have the following ordering table for
 | |
|  * each pair of barrier(), sys_membarrier() and smp_mb():
 | |
|  *
 | |
|  * The pair ordering is detailed as (O: ordered, X: not ordered):
 | |
|  *
 | |
|  *                        barrier()   smp_mb() sys_membarrier()
 | |
|  *        barrier()          X           X            O
 | |
|  *        smp_mb()           X           O            O
 | |
|  *        sys_membarrier()   O           O            O
 | |
|  */
 | |
| SYSCALL_DEFINE2(membarrier, int, cmd, int, flags)
 | |
| {
 | |
| 	/* MEMBARRIER_CMD_SHARED is not compatible with nohz_full. */
 | |
| 	if (tick_nohz_full_enabled())
 | |
| 		return -ENOSYS;
 | |
| 	if (unlikely(flags))
 | |
| 		return -EINVAL;
 | |
| 	switch (cmd) {
 | |
| 	case MEMBARRIER_CMD_QUERY:
 | |
| 		return MEMBARRIER_CMD_BITMASK;
 | |
| 	case MEMBARRIER_CMD_SHARED:
 | |
| 		if (num_online_cpus() > 1)
 | |
| 			synchronize_sched();
 | |
| 		return 0;
 | |
| 	default:
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| }
 |