uatomic/x86: Remove redundant memory barriers
[urcu.git] / src / urcu-poll-impl.h
CommitLineData
acdb82a2
MJ
1// SPDX-FileCopyrightText: 2023 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4
111bda8f 5/*
111bda8f 6 * Userspace RCU library - Grace period polling API
111bda8f
MD
7 */
8
9#include <pthread.h>
10#include <stdbool.h>
11
12#include <urcu/urcu-poll.h>
13#include <urcu/call-rcu.h>
14
15struct urcu_poll_worker_state {
16 struct urcu_gp_poll_state current_state;
17 struct urcu_gp_poll_state latest_target; /* Most recent snapshot taken */
18 struct rcu_head rcu_head;
19 pthread_mutex_t lock;
20 bool active;
21};
22
23static struct urcu_poll_worker_state poll_worker_gp_state = {
24 .lock = PTHREAD_MUTEX_INITIALIZER,
25};
26
27static
28void urcu_poll_worker_cb(struct rcu_head *head __attribute__((unused)))
29{
30 mutex_lock(&poll_worker_gp_state.lock);
31 /* A new grace period has been reached. */
32 poll_worker_gp_state.current_state.grace_period_id++;
33 if ((long)(poll_worker_gp_state.latest_target.grace_period_id - poll_worker_gp_state.current_state.grace_period_id) >= 0) {
34 /* Need to re-queue. */
35 call_rcu(&poll_worker_gp_state.rcu_head, urcu_poll_worker_cb);
36 } else {
37 /* No user waiting for a target grace period. */
38 poll_worker_gp_state.active = false;
39 }
40 mutex_unlock(&poll_worker_gp_state.lock);
41}
42
43/*
44 * Start polling on grace period. If no worker is currently active,
45 * snapshot the current value and start a worker callback. If the worker
46 * is currently active, snapshot the current value + 1, and set this
47 * value as the latest snapshot, which will cause the worker to re-queue
48 * itself with call_rcu to issue one more grace period.
49 *
50 * Because it uses call_rcu, it needs to be called from a registered RCU
51 * thread.
52 */
53struct urcu_gp_poll_state start_poll_synchronize_rcu(void)
54{
55 struct urcu_gp_poll_state new_target_gp_state;
56 bool was_active = false;
57
58 mutex_lock(&poll_worker_gp_state.lock);
59 new_target_gp_state.grace_period_id = poll_worker_gp_state.current_state.grace_period_id;
60 was_active = poll_worker_gp_state.active;
61 if (!was_active)
62 poll_worker_gp_state.active = true;
63 else
64 new_target_gp_state.grace_period_id++;
65 poll_worker_gp_state.latest_target.grace_period_id = new_target_gp_state.grace_period_id;
66 if (!was_active)
67 call_rcu(&poll_worker_gp_state.rcu_head, urcu_poll_worker_cb);
68 mutex_unlock(&poll_worker_gp_state.lock);
69 return new_target_gp_state;
70}
71
72/*
73 * Poll the grace period state. Return true if quiescence was reached
74 * since the snapshot was taken, return false if quiescence was not
75 * reached since snapshot.
76 */
77bool poll_state_synchronize_rcu(struct urcu_gp_poll_state target_gp_state)
78{
79 bool target_gp_reached = false;
80
81 mutex_lock(&poll_worker_gp_state.lock);
82 if ((long)(target_gp_state.grace_period_id - poll_worker_gp_state.current_state.grace_period_id) < 0)
83 target_gp_reached = true;
84 mutex_unlock(&poll_worker_gp_state.lock);
85 return target_gp_reached;
86}
This page took 0.02603 seconds and 4 git commands to generate.