Blame view

RIOT/core/include/atomic.h 3.29 KB
fb11e647   vrobic   reseau statique a...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  /*
   * Copyright (C) 2014 Freie Universität Berlin
   * Copyright (C) 2015 Eistec AB
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   */
  
  /**
   * @addtogroup  core_util
   * @{
   *
   * @file
   * @brief       Functions for atomic handling of variables
   *
   * @author      Kaspar Schleiser <kaspar@schleiser.de>
   * @author      Joakim Nohlgård <joakim.nohlgard@eistec.se>
   */
  
  #ifndef ATOMIC_H_
  #define ATOMIC_H_
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * @brief Integer variable for use in atomic counters.
   *
   * @note    This type is a struct for hard type checking (let the compiler warn
   *          if int is assigned regularly).
   */
  typedef struct {
      volatile int value;         /**< the actual value */
  } atomic_int_t;
  
  /**
   * @brief Initializer for atomic variables
   *
   * @param[in] val  initial value for the atomic integer
   */
  #define ATOMIC_INIT(val) {(val)}
  
  /**
   * @brief Atomic Compare and Swap
   *
   * Updates the value in var iff the current value of var is equal to old.
   *
   * @param[inout] var  Atomic variable to update
   * @param[in]    old  The old value to compare against
   * @param[in]    now  The new value to write to var
   *
   * @return 1 if the write completed successfully
   * @return 0 if the write failed.
   */
  int atomic_cas(atomic_int_t *var, int old, int now);
  
  /**
   * @brief Increment a counter variable by one atomically and return the old value.
   *
   * @param[inout]  var   Pointer to a counter variable.
   *
   * @return The value of *val* before the increment.
   */
  static inline int atomic_inc(atomic_int_t *var)
  {
      int old;
  
      do {
          old = var->value;
      } while (!atomic_cas(var, old, old + 1));
  
      return old;
  }
  
  /**
   * @brief Decrement a counter variable by one atomically and return the old value.
   *
   * @param[inout]  var   Pointer to a counter variable.
   *
   * @return The value of *val* before the decrement.
   */
  static inline int atomic_dec(atomic_int_t *var)
  {
      int old;
  
      do {
          old = var->value;
      } while (!atomic_cas(var, old, old - 1));
  
      return old;
  }
  
  /**
   * @brief Set an atomic variable to 1.
   *
   * @param[inout]  var   Pointer to an atomic variable to update
   *
   * @return 1 if the old value was 0 and the variable was successfully updated
   * @return 0 if the variable was already set
   */
  static inline int atomic_set_to_one(atomic_int_t *var)
  {
      do {
          if (var->value != 0) {
              return 0;
          }
      } while (!atomic_cas(var, 0, 1));
  
      return 1;
  }
  
  /**
   * @brief Set an atomic variable to 0.
   *
   * @param[inout]  var   Pointer to an atomic variable to update
   *
   * @return 1 if the old value was not 0 and the variable was successfully updated
   * @return 0 if the variable was already cleared
   */
  static inline int atomic_set_to_zero(atomic_int_t *var)
  {
      int old;
  
      do {
          old = var->value;
  
          if (old == 0) {
              return 0;
          }
      } while (!atomic_cas(var, old, 0));
  
      return 1;
  }
  
  /**
   * @brief Get the value of an atomic int
   *
   * @param[in]  var   Atomic variable
   *
   * @return the value of the atomic integer
   *
   * @note This can be used for non-thread-safe assignment of the atomic integer
   */
  #define ATOMIC_VALUE(var) ((var).value)
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* ATOMIC_H_ */
  /** @} */