]> git.ipfire.org Git - thirdparty/json-c.git/commitdiff
Explicitly check for GCC's atomic functions instead of depending on the __GNUC__...
authorEric Haszlakiewicz <erh+git@nimenees.com>
Sat, 2 Sep 2017 18:48:17 +0000 (14:48 -0400)
committerEric Haszlakiewicz <erh+git@nimenees.com>
Sat, 2 Sep 2017 18:48:17 +0000 (14:48 -0400)
Add a comment mentioning the limitation even though the _ref_count value is hanled atomically.

configure.ac
json_object.c

index bbaacf51964c1bf29d779603df02f6b60d49aef3..4f507ffb6ace35d2565985bc36200025113b64ca 100644 (file)
@@ -66,6 +66,30 @@ AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]])
 AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]])
 AC_CHECK_DECLS([_isnan], [], [], [[#include <float.h>]])
 AC_CHECK_DECLS([_finite], [], [], [[#include <float.h>]])
+AC_MSG_CHECKING(for GCC atomic builtins)
+AC_LINK_IFELSE(
+[
+ AC_LANG_SOURCE([[
+   int main() {
+      volatile unsigned int val = 1;
+      /* Note: __sync_val_compare_and_swap isn't checked here
+       * because it's protected by __GCC_HAVE_SYNC_COMPARE_AND_SWAP_<n>,
+       * which is automatically defined by gcc.
+       */
+      __sync_add_and_fetch(&val, 1);
+      __sync_sub_and_fetch(&val, 1);
+      return 0;
+   }
+ ]])
+],
+[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_ATOMIC_BUILTINS],[1],[Has atomic builtins])
+],
+[
+ AC_MSG_RESULT([no])
+ AC_MSG_WARN([json-c will be built without atomic refcounts because atomic builtins are missing])
+])
 
 case "${host_os}" in
        linux*)
index 028d495667b2aac190395264ae2e61ae71a862d5..c09d61d14ac4283429f3bbeea7d06aef94197c29 100644 (file)
@@ -165,7 +165,7 @@ extern struct json_object* json_object_get(struct json_object *jso)
 {
        if (!jso) return jso;
 
-#if defined __GNUC__
+#ifdef HAVE_ATOMIC_BUILTINS
        __sync_add_and_fetch(&jso->_ref_count, 1);
 #else
        ++jso->_ref_count;
@@ -178,7 +178,13 @@ int json_object_put(struct json_object *jso)
 {
        if(!jso) return 0;
 
-#if defined __GNUC__
+#ifdef HAVE_ATOMIC_BUILTINS
+       /* Note: this only allow the refcount to remain correct
+        * when multiple threads are adjusting it.  It is still an error 
+        * for a thread to decrement the refcount if it doesn't "own" it,
+        * as that can result in the thread that loses the race to 0
+        * operating on an already-freed object.
+        */
        if (__sync_sub_and_fetch(&jso->_ref_count, 1) > 0) return 0;
 #else
        if (--jso->_ref_count > 0) return 0;