|
@@ -26,11 +26,20 @@
|
|
|
* Bitmask made from a "or" of all commands within enum membarrier_cmd,
|
|
|
* except MEMBARRIER_CMD_QUERY.
|
|
|
*/
|
|
|
+#ifdef CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE
|
|
|
+#define MEMBARRIER_PRIVATE_EXPEDITED_SYNC_CORE_BITMASK \
|
|
|
+ (MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE \
|
|
|
+ | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE)
|
|
|
+#else
|
|
|
+#define MEMBARRIER_PRIVATE_EXPEDITED_SYNC_CORE_BITMASK 0
|
|
|
+#endif
|
|
|
+
|
|
|
#define MEMBARRIER_CMD_BITMASK \
|
|
|
(MEMBARRIER_CMD_GLOBAL | MEMBARRIER_CMD_GLOBAL_EXPEDITED \
|
|
|
| MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED \
|
|
|
| MEMBARRIER_CMD_PRIVATE_EXPEDITED \
|
|
|
- | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED)
|
|
|
+ | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED \
|
|
|
+ | MEMBARRIER_PRIVATE_EXPEDITED_SYNC_CORE_BITMASK)
|
|
|
|
|
|
static void ipi_mb(void *info)
|
|
|
{
|
|
@@ -104,15 +113,23 @@ static int membarrier_global_expedited(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int membarrier_private_expedited(void)
|
|
|
+static int membarrier_private_expedited(int flags)
|
|
|
{
|
|
|
int cpu;
|
|
|
bool fallback = false;
|
|
|
cpumask_var_t tmpmask;
|
|
|
|
|
|
- if (!(atomic_read(¤t->mm->membarrier_state)
|
|
|
- & MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY))
|
|
|
- return -EPERM;
|
|
|
+ if (flags & MEMBARRIER_FLAG_SYNC_CORE) {
|
|
|
+ if (!IS_ENABLED(CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE))
|
|
|
+ return -EINVAL;
|
|
|
+ if (!(atomic_read(¤t->mm->membarrier_state) &
|
|
|
+ MEMBARRIER_STATE_PRIVATE_EXPEDITED_SYNC_CORE_READY))
|
|
|
+ return -EPERM;
|
|
|
+ } else {
|
|
|
+ if (!(atomic_read(¤t->mm->membarrier_state) &
|
|
|
+ MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY))
|
|
|
+ return -EPERM;
|
|
|
+ }
|
|
|
|
|
|
if (num_online_cpus() == 1)
|
|
|
return 0;
|
|
@@ -205,20 +222,29 @@ static int membarrier_register_global_expedited(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int membarrier_register_private_expedited(void)
|
|
|
+static int membarrier_register_private_expedited(int flags)
|
|
|
{
|
|
|
struct task_struct *p = current;
|
|
|
struct mm_struct *mm = p->mm;
|
|
|
+ int state = MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY;
|
|
|
+
|
|
|
+ if (flags & MEMBARRIER_FLAG_SYNC_CORE) {
|
|
|
+ if (!IS_ENABLED(CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE))
|
|
|
+ return -EINVAL;
|
|
|
+ state = MEMBARRIER_STATE_PRIVATE_EXPEDITED_SYNC_CORE_READY;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* We need to consider threads belonging to different thread
|
|
|
* groups, which use the same mm. (CLONE_VM but not
|
|
|
* CLONE_THREAD).
|
|
|
*/
|
|
|
- if (atomic_read(&mm->membarrier_state)
|
|
|
- & MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY)
|
|
|
+ if (atomic_read(&mm->membarrier_state) & state)
|
|
|
return 0;
|
|
|
atomic_or(MEMBARRIER_STATE_PRIVATE_EXPEDITED, &mm->membarrier_state);
|
|
|
+ if (flags & MEMBARRIER_FLAG_SYNC_CORE)
|
|
|
+ atomic_or(MEMBARRIER_STATE_PRIVATE_EXPEDITED_SYNC_CORE,
|
|
|
+ &mm->membarrier_state);
|
|
|
if (!(atomic_read(&mm->mm_users) == 1 && get_nr_threads(p) == 1)) {
|
|
|
/*
|
|
|
* Ensure all future scheduler executions will observe the
|
|
@@ -226,8 +252,7 @@ static int membarrier_register_private_expedited(void)
|
|
|
*/
|
|
|
synchronize_sched();
|
|
|
}
|
|
|
- atomic_or(MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY,
|
|
|
- &mm->membarrier_state);
|
|
|
+ atomic_or(state, &mm->membarrier_state);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -283,9 +308,13 @@ SYSCALL_DEFINE2(membarrier, int, cmd, int, flags)
|
|
|
case MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED:
|
|
|
return membarrier_register_global_expedited();
|
|
|
case MEMBARRIER_CMD_PRIVATE_EXPEDITED:
|
|
|
- return membarrier_private_expedited();
|
|
|
+ return membarrier_private_expedited(0);
|
|
|
case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED:
|
|
|
- return membarrier_register_private_expedited();
|
|
|
+ return membarrier_register_private_expedited(0);
|
|
|
+ case MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE:
|
|
|
+ return membarrier_private_expedited(MEMBARRIER_FLAG_SYNC_CORE);
|
|
|
+ case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE:
|
|
|
+ return membarrier_register_private_expedited(MEMBARRIER_FLAG_SYNC_CORE);
|
|
|
default:
|
|
|
return -EINVAL;
|
|
|
}
|