• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010, 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3  *
4  * membarrier system call
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 
17 #include <linux/syscalls.h>
18 #include <linux/membarrier.h>
19 #include <linux/tick.h>
20 
21 /*
22  * Bitmask made from a "or" of all commands within enum membarrier_cmd,
23  * except MEMBARRIER_CMD_QUERY.
24  */
25 #define MEMBARRIER_CMD_BITMASK	(MEMBARRIER_CMD_SHARED)
26 
27 /**
28  * sys_membarrier - issue memory barriers on a set of threads
29  * @cmd:   Takes command values defined in enum membarrier_cmd.
30  * @flags: Currently needs to be 0. For future extensions.
31  *
32  * If this system call is not implemented, -ENOSYS is returned. If the
33  * command specified does not exist, or if the command argument is invalid,
34  * this system call returns -EINVAL. For a given command, with flags argument
35  * set to 0, this system call is guaranteed to always return the same value
36  * until reboot.
37  *
38  * All memory accesses performed in program order from each targeted thread
39  * is guaranteed to be ordered with respect to sys_membarrier(). If we use
40  * the semantic "barrier()" to represent a compiler barrier forcing memory
41  * accesses to be performed in program order across the barrier, and
42  * smp_mb() to represent explicit memory barriers forcing full memory
43  * ordering across the barrier, we have the following ordering table for
44  * each pair of barrier(), sys_membarrier() and smp_mb():
45  *
46  * The pair ordering is detailed as (O: ordered, X: not ordered):
47  *
48  *                        barrier()   smp_mb() sys_membarrier()
49  *        barrier()          X           X            O
50  *        smp_mb()           X           O            O
51  *        sys_membarrier()   O           O            O
52  */
SYSCALL_DEFINE2(membarrier,int,cmd,int,flags)53 SYSCALL_DEFINE2(membarrier, int, cmd, int, flags)
54 {
55 	/* MEMBARRIER_CMD_SHARED is not compatible with nohz_full. */
56 	if (tick_nohz_full_enabled())
57 		return -ENOSYS;
58 	if (unlikely(flags))
59 		return -EINVAL;
60 	switch (cmd) {
61 	case MEMBARRIER_CMD_QUERY:
62 		return MEMBARRIER_CMD_BITMASK;
63 	case MEMBARRIER_CMD_SHARED:
64 		if (num_online_cpus() > 1)
65 			synchronize_sched();
66 		return 0;
67 	default:
68 		return -EINVAL;
69 	}
70 }
71