| /* Copyright (c) 2010 The Regents of the University of California |
| * Barret Rhoden <brho@cs.berkeley.edu> |
| * See LICENSE for details. |
| * |
| * Locking and atomics that are part of the kernel interface. */ |
| |
| #pragma once |
| |
| #include <ros/common.h> |
| #include <ros/arch/membar.h> |
| |
| typedef void* atomic_t; |
| |
| /* The seq counters are used by userspace to see if the kernel is updating |
| * something or if something is valid, such as the vcore->pcore mapping. The |
| * way a reader can tell nothing has changed is to read the counter before and |
| * after. If the value has changed, the reader needs to re-read. If the value |
| * is odd, a write is in progress or it is otherwise invalid/locked. */ |
| |
| typedef uint32_t seq_ctr_t; |
| #define SEQCTR_INITIALIZER 0 |
| |
| static inline bool seq_is_locked(seq_ctr_t seq_ctr); |
| static inline bool seqctr_retry(seq_ctr_t old_ctr, seq_ctr_t new_ctr); |
| |
| /* Basic helpers for readers. Ex: |
| * do { |
| * seq_ctr_t seq = kernel_maintained_seq_ctr |
| * read_data_whatever(); |
| * } while (seqctr_retry(seq, kernel_maintained_seq_ctr); |
| */ |
| static inline bool seq_is_locked(seq_ctr_t seq_ctr) |
| { |
| return READ_ONCE(seq_ctr) % 2; |
| } |
| |
| static inline bool seqctr_retry(seq_ctr_t old_ctr, seq_ctr_t new_ctr) |
| { |
| seq_ctr_t old_val; |
| |
| rmb(); /* don't allow protected reads to reorder after the check */ |
| /* Even though old_ctr is passed in, we might be inlined and can't |
| * guarantee old_ctr was in a register or otherwise won't be re-read. */ |
| old_val = READ_ONCE(old_ctr); |
| return (seq_is_locked(old_val)) || (old_val != new_ctr); |
| } |