syslog-ng source
atomic-gssize.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002-2018 Balabit
3  * Copyright (c) 2018 Laszlo Budai <laszlo.budai@balabit.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * As an additional exemption you are allowed to compile & link against the
20  * OpenSSL libraries as published by the OpenSSL project. See the file
21  * COPYING for details.
22  *
23  */
24 
25 #ifndef ATOMIC_GSSIZE_H_INCLUDED
26 #define ATOMIC_GSSIZE_H_INCLUDED
27 
28 #include "syslog-ng.h"
29 
30 G_STATIC_ASSERT(sizeof(gssize) == sizeof(gpointer));
31 
32 typedef struct
33 {
34  gssize value;
36 
37 /*
38  * All atomic operations below use __atomic_* compiler builtins directly.
39  *
40  * The GLib g_atomic_pointer_* macros expect gpointer * storage, but our
41  * value is gssize. Using those macros causes type-mismatch errors across
42  * different GLib/compiler combinations (strict-aliasing, -Wincompatible-
43  * pointer-types, -Wint-conversion). The __atomic_* builtins are available
44  * on GCC 4.7+ and Clang 3.1+ and accept any scalar type, so they are the
45  * portable, type-safe alternative.
46  */
47 
48 static inline gssize
49 atomic_gssize_add(atomic_gssize *a, gssize add)
50 {
51  return (gssize) __atomic_fetch_add(&a->value, add, __ATOMIC_SEQ_CST);
52 }
53 
54 static inline gssize
55 atomic_gssize_sub(atomic_gssize *a, gssize sub)
56 {
57  return (gssize) __atomic_fetch_sub(&a->value, sub, __ATOMIC_SEQ_CST);
58 }
59 
60 static inline gssize
61 atomic_gssize_inc(atomic_gssize *a)
62 {
63  return (gssize) __atomic_fetch_add(&a->value, 1, __ATOMIC_SEQ_CST);
64 }
65 
66 static inline gssize
67 atomic_gssize_dec(atomic_gssize *a)
68 {
69  return (gssize) __atomic_fetch_sub(&a->value, 1, __ATOMIC_SEQ_CST);
70 }
71 
72 static inline gssize
73 atomic_gssize_get(atomic_gssize *a)
74 {
75  return (gssize) __atomic_load_n(&a->value, __ATOMIC_SEQ_CST);
76 }
77 
78 static inline void
79 atomic_gssize_set(atomic_gssize *a, gssize value)
80 {
81  __atomic_store_n(&a->value, value, __ATOMIC_SEQ_CST);
82 }
83 
84 static inline gsize
85 atomic_gssize_get_unsigned(atomic_gssize *a)
86 {
87  return (gsize) __atomic_load_n(&a->value, __ATOMIC_SEQ_CST);
88 }
89 
90 static inline gssize
91 atomic_gssize_racy_get(atomic_gssize *a)
92 {
93  return a->value;
94 }
95 
96 static inline gsize
97 atomic_gssize_racy_get_unsigned(atomic_gssize *a)
98 {
99  return (gsize) a->value;
100 }
101 
102 static inline void
103 atomic_gssize_racy_set(atomic_gssize *a, gssize value)
104 {
105  a->value = value;
106 }
107 
108 static inline gsize
109 atomic_gssize_or(atomic_gssize *a, gsize value)
110 {
111  return (gsize) __atomic_fetch_or(&a->value, value, __ATOMIC_SEQ_CST);
112 }
113 
114 static inline gsize
115 atomic_gssize_xor(atomic_gssize *a, gsize value)
116 {
117  return (gsize) __atomic_fetch_xor(&a->value, value, __ATOMIC_SEQ_CST);
118 }
119 
120 static inline gsize
121 atomic_gssize_and(atomic_gssize *a, gsize value)
122 {
123  return (gsize) __atomic_fetch_and(&a->value, value, __ATOMIC_SEQ_CST);
124 }
125 
126 static inline gboolean
127 atomic_gssize_compare_and_exchange(atomic_gssize *a, gssize oldval, gssize newval)
128 {
129  return !!__atomic_compare_exchange_n(&a->value, &oldval, newval, FALSE,
130  __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
131 }
132 
133 static inline gssize
134 atomic_gssize_set_and_get(atomic_gssize *a, gssize value)
135 {
136  gssize oldval = atomic_gssize_get(a);
137 
138  while (!atomic_gssize_compare_and_exchange(a, oldval, value))
139  {
140  oldval = atomic_gssize_get(a);
141  }
142 
143  return oldval;
144 }
145 #endif
G_STATIC_ASSERT(sizeof(gssize)==sizeof(gpointer))
Definition: atomic-gssize.h:33
gssize value
Definition: atomic-gssize.h:34
GString * value
Definition: test_decode.c:28