21ab4e
From 1b8c236159ad56c038eaa58f5faf9eed7223013f Mon Sep 17 00:00:00 2001
21ab4e
From: Niels de Vos <ndevos@redhat.com>
21ab4e
Date: Wed, 29 Mar 2017 13:44:03 +0200
21ab4e
Subject: [PATCH 393/393] libglusterfs: provide standardized atomic operations
21ab4e
21ab4e
The current macros ATOMIC_INCREMENT() and ATOMIC_DECREMENT() expect a
21ab4e
lock as first argument. There are at least two issues with this
21ab4e
approach:
21ab4e
21ab4e
  1. this lock is unused on architectures that have atomic operations
21ab4e
  2. some structures use a single lock for multiple variables
21ab4e
21ab4e
By defining a gf_atomic_t type, the unused lock can be removed, saving a
21ab4e
few bytes on modern architectures.
21ab4e
21ab4e
Because the gf_atomic_t type locates the lock for the variable (in case
21ab4e
of older architectures), each variable is protected the same on all
21ab4e
architectures. This makes the behaviour across all architectures more
21ab4e
equal (per variable locking, by a gf_lock_t or compiler optimization).
21ab4e
21ab4e
>Signed-off-by: Niels de Vos <ndevos@redhat.com>
21ab4e
>Reviewed-on: https://review.gluster.org/16963
21ab4e
>Smoke: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: Xavier Hernandez <xhernandez@datalab.es>
21ab4e
>NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
21ab4e
>CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: Amar Tumballi <amarts@redhat.com>
21ab4e
>Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
21ab4e
21ab4e
BUG: 1427099
21ab4e
Change-Id: Ic164892b06ea676e6a9566f8a98b7faf0efe76d6
21ab4e
Signed-off-by: Poornima G <pgurusid@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/103883
21ab4e
Reviewed-by: Milind Changire <mchangir@redhat.com>
21ab4e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
21ab4e
---
21ab4e
 configure.ac                                |  21 +++---
21ab4e
 libglusterfs/src/Makefile.am                |   3 +-
21ab4e
 libglusterfs/src/atomic.h                   | 109 ++++++++++++++++++++++++++++
21ab4e
 libglusterfs/src/client_t.c                 |  45 ++++++------
21ab4e
 libglusterfs/src/client_t.h                 |   8 +-
21ab4e
 libglusterfs/src/globals.h                  |  21 +-----
21ab4e
 libglusterfs/src/logging.h                  |   1 +
21ab4e
 libglusterfs/src/mem-pool.c                 |   4 +-
21ab4e
 libglusterfs/src/mem-pool.h                 |  10 +--
21ab4e
 libglusterfs/src/xlator.c                   |   5 +-
21ab4e
 xlators/debug/io-stats/src/io-stats.c       |   8 +-
21ab4e
 xlators/performance/md-cache/src/md-cache.c |  93 +++++++++++++-----------
21ab4e
 12 files changed, 215 insertions(+), 113 deletions(-)
21ab4e
 create mode 100644 libglusterfs/src/atomic.h
21ab4e
21ab4e
diff --git a/configure.ac b/configure.ac
21ab4e
index b5357dc..d51fa87 100644
21ab4e
--- a/configure.ac
21ab4e
+++ b/configure.ac
21ab4e
@@ -931,16 +931,19 @@ AC_SUBST(ARGP_STANDALONE_CPPFLAGS)
21ab4e
 AC_SUBST(ARGP_STANDALONE_LDADD)
21ab4e
 AC_SUBST(ARGP_STANDALONE_DIR)
21ab4e
 
21ab4e
-# Check for atomic operation support
21ab4e
-echo -n "checking for atomic operation support... "
21ab4e
-AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { long int a = 4; __sync_fetch_and_add_8 (&a, 1); }]])],
21ab4e
-                   [have_sync_fetch_and_add_8=yes], [have_sync_fetch_and_add_8=no])
21ab4e
-if test "x${have_sync_fetch_and_add_8}" = "xyes"; then
21ab4e
-  echo "yes"
21ab4e
-  AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1, [have atomic builtins])
21ab4e
-else
21ab4e
-  echo "no"
21ab4e
+dnl Check for atomic operation support
21ab4e
+AC_CHECK_FUNC([__atomic_load], [have_atomic_builtins])
21ab4e
+if test "x${have_atomic_builtins}" = "xyes"; then
21ab4e
+   AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1, [define if __atomic_*() builtins are available])
21ab4e
+fi
21ab4e
+AC_SUBST(HAVE_ATOMIC_BUILTINS)
21ab4e
+
21ab4e
+dnl __sync_*() will not be needed if __atomic_*() is available
21ab4e
+AC_CHECK_FUNC([__sync_fetch_and_add], [have_sync_builtins])
21ab4e
+if test "x${have_sync_builtind}" = "xyes"; then
21ab4e
+   AC_DEFINE(HAVE_SYNC_BUILTINS, 1, [define if __sync_*() builtins are available])
21ab4e
 fi
21ab4e
+AC_SUBST(HAVE_SYNC_BUILTINS)
21ab4e
 
21ab4e
 AC_CHECK_HEADER([malloc.h], AC_DEFINE(HAVE_MALLOC_H, 1, [have malloc.h]))
21ab4e
 
21ab4e
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am
21ab4e
index b16b87a..01cb314 100644
21ab4e
--- a/libglusterfs/src/Makefile.am
21ab4e
+++ b/libglusterfs/src/Makefile.am
21ab4e
@@ -52,7 +52,8 @@ libglusterfs_la_HEADERS = common-utils.h defaults.h default-args.h \
21ab4e
 	glfs-message-id.h template-component-messages.h strfd.h \
21ab4e
 	syncop-utils.h parse-utils.h libglusterfs-messages.h tw.h \
21ab4e
 	lvm-defaults.h quota-common-utils.h rot-buffs.h \
21ab4e
-	compat-uuid.h upcall-utils.h events.h compound-fop-utils.h
21ab4e
+	compat-uuid.h upcall-utils.h events.h compound-fop-utils.h \
21ab4e
+        atomic.h
21ab4e
 
21ab4e
 libglusterfs_ladir = $(includedir)/glusterfs
21ab4e
 
21ab4e
diff --git a/libglusterfs/src/atomic.h b/libglusterfs/src/atomic.h
21ab4e
new file mode 100644
21ab4e
index 0000000..71fcb1e
21ab4e
--- /dev/null
21ab4e
+++ b/libglusterfs/src/atomic.h
21ab4e
@@ -0,0 +1,109 @@
21ab4e
+/*
21ab4e
+  Copyright (c) 2017 Red Hat, Inc. <http://www.redhat.com>
21ab4e
+  This file is part of GlusterFS.
21ab4e
+
21ab4e
+  This file is licensed to you under your choice of the GNU Lesser
21ab4e
+  General Public License, version 3 or any later version (LGPLv3 or
21ab4e
+  later), or the GNU General Public License, version 2 (GPLv2), in all
21ab4e
+  cases as published by the Free Software Foundation.
21ab4e
+*/
21ab4e
+
21ab4e
+#ifndef _ATOMIC_H
21ab4e
+#define _ATOMIC_H
21ab4e
+
21ab4e
+#include <inttypes.h>
21ab4e
+
21ab4e
+#if defined(HAVE_ATOMIC_BUILTINS) || defined(HAVE_SYNC_BUILTINS)
21ab4e
+/* optimized implementation, macros only */
21ab4e
+
21ab4e
+typedef struct gf_atomic_t {
21ab4e
+        int64_t    cnt;
21ab4e
+} gf_atomic_t;
21ab4e
+
21ab4e
+#if defined(HAVE_ATOMIC_BUILTINS)
21ab4e
+
21ab4e
+/* all macros have a 'gf_atomic_t' as 1st argument */
21ab4e
+#define GF_ATOMIC_INIT(op, n)     __atomic_store (&(op.cnt), __ATOMIC_RELEASE)
21ab4e
+#define GF_ATOMIC_GET(op)         __atomic_load (&(op.cnt), __ATOMIC_ACQUIRE)
21ab4e
+#define GF_ATOMIC_INC(op)         __atomic_add_and_fetch (&(op.cnt), 1, \
21ab4e
+                                                          __ATOMIC_ACQ_REL)
21ab4e
+#define GF_ATOMIC_DEC(op)         __atomic_sub_and_fetch (&(op.cnt), 1, \
21ab4e
+                                                          __ATOMIC_ACQ_REL)
21ab4e
+#define GF_ATOMIC_ADD(op, n)      __atomic_add_and_fetch (&(op.cnt), n, \
21ab4e
+                                                          __ATOMIC_ACQ_REL)
21ab4e
+#define GF_ATOMIC_SUB(op, n)      __atomic_sub_and_fetch (&(op.cnt), n, \
21ab4e
+                                                          __ATOMIC_ACQ_REL)
21ab4e
+
21ab4e
+#else /* !HAVE_ATOMIC_BUILTINS, but HAVE_SYNC_BUILTINS */
21ab4e
+
21ab4e
+/* all macros have a 'gf_atomic_t' as 1st argument */
21ab4e
+#define GF_ATOMIC_INIT(op, n)     ({ op.cnt = n; __sync_synchronize (); })
21ab4e
+#define GF_ATOMIC_GET(op)         __sync_add_and_fetch (&(op.cnt), 0)
21ab4e
+#define GF_ATOMIC_INC(op)         __sync_add_and_fetch (&(op.cnt), 1)
21ab4e
+#define GF_ATOMIC_DEC(op)         __sync_sub_and_fetch (&(op.cnt), 1)
21ab4e
+#define GF_ATOMIC_ADD(op, n)      __sync_add_and_fetch (&(op.cnt), n)
21ab4e
+#define GF_ATOMIC_SUB(op, n)      __sync_sub_and_fetch (&(op.cnt), n)
21ab4e
+
21ab4e
+#endif /* HAVE_ATOMIC_BUILTINS || HAVE_SYNC_BUILTINS */
21ab4e
+
21ab4e
+#else /* no HAVE_(ATOMIC|SYNC)_BUILTINS */
21ab4e
+/* fallback implementation, using small inline functions to improve type
21ab4e
+ * checking while compiling */
21ab4e
+
21ab4e
+#include "locking.h"
21ab4e
+
21ab4e
+typedef struct gf_atomic_t {
21ab4e
+        int64_t    cnt;
21ab4e
+        gf_lock_t  lk;
21ab4e
+} gf_atomic_t;
21ab4e
+
21ab4e
+
21ab4e
+static inline void
21ab4e
+gf_atomic_init (gf_atomic_t *op, int64_t cnt)
21ab4e
+{
21ab4e
+        LOCK_INIT (&op->lk);
21ab4e
+        op->cnt = cnt;
21ab4e
+}
21ab4e
+
21ab4e
+
21ab4e
+static inline uint64_t
21ab4e
+gf_atomic_get (gf_atomic_t *op)
21ab4e
+{
21ab4e
+        uint64_t ret;
21ab4e
+
21ab4e
+        LOCK (&op->lk);
21ab4e
+        {
21ab4e
+               ret = op->cnt;
21ab4e
+        }
21ab4e
+        UNLOCK (&op->lk);
21ab4e
+
21ab4e
+        return ret;
21ab4e
+}
21ab4e
+
21ab4e
+
21ab4e
+static inline int64_t
21ab4e
+gf_atomic_add (gf_atomic_t *op, int64_t n)
21ab4e
+{
21ab4e
+        uint64_t ret;
21ab4e
+
21ab4e
+        LOCK (&op->lk);
21ab4e
+        {
21ab4e
+                op->cnt += n;
21ab4e
+                ret = op->cnt;
21ab4e
+        }
21ab4e
+        UNLOCK (&op->lk);
21ab4e
+
21ab4e
+        return ret;
21ab4e
+}
21ab4e
+
21ab4e
+
21ab4e
+#define GF_ATOMIC_INIT(op, cnt)   gf_atomic_init (&op, cnt)
21ab4e
+#define GF_ATOMIC_GET(op)         gf_atomic_get (&op)
21ab4e
+#define GF_ATOMIC_INC(op)         gf_atomic_add (&op, 1)
21ab4e
+#define GF_ATOMIC_DEC(op)         gf_atomic_add (&op, -1)
21ab4e
+#define GF_ATOMIC_ADD(op, n)      gf_atomic_add (&op, n)
21ab4e
+#define GF_ATOMIC_SUB(op, n)      gf_atomic_add (&op, -n)
21ab4e
+
21ab4e
+#endif /* HAVE_ATOMIC_SYNC_OPS */
21ab4e
+
21ab4e
+#endif /* _ATOMIC_H */
21ab4e
diff --git a/libglusterfs/src/client_t.c b/libglusterfs/src/client_t.c
21ab4e
index 97181d4..97cf9f9 100644
21ab4e
--- a/libglusterfs/src/client_t.c
21ab4e
+++ b/libglusterfs/src/client_t.c
21ab4e
@@ -192,8 +192,7 @@ gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid)
21ab4e
                                         memcmp (cred->authdata,
21ab4e
                                                 client->auth.data,
21ab4e
                                                 client->auth.len) == 0))) {
21ab4e
-                                INCREMENT_ATOMIC (client->ref.lock,
21ab4e
-                                                  client->ref.bind);
21ab4e
+                                GF_ATOMIC_INC (client->bind);
21ab4e
                                 goto unlock;
21ab4e
                         }
21ab4e
                 }
21ab4e
@@ -207,7 +206,6 @@ gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid)
21ab4e
                 client->this = this;
21ab4e
 
21ab4e
                 LOCK_INIT (&client->scratch_ctx.lock);
21ab4e
-                LOCK_INIT (&client->ref.lock);
21ab4e
 
21ab4e
                 client->client_uid = gf_strdup (client_uid);
21ab4e
                 if (client->client_uid == NULL) {
21ab4e
@@ -229,8 +227,8 @@ gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid)
21ab4e
                         goto unlock;
21ab4e
                 }
21ab4e
 
21ab4e
-                /* no need to do these atomically here */
21ab4e
-                client->ref.bind = client->ref.count = 1;
21ab4e
+                GF_ATOMIC_INIT (client->bind, 1);
21ab4e
+                GF_ATOMIC_INIT (client->count, 1);
21ab4e
 
21ab4e
                 client->auth.flavour = cred->flavour;
21ab4e
                 if (cred->flavour != AUTH_NONE) {
21ab4e
@@ -277,9 +275,10 @@ unlock:
21ab4e
 
21ab4e
         if (client)
21ab4e
                 gf_msg_callingfn ("client_t", GF_LOG_DEBUG, 0, LG_MSG_BIND_REF,
21ab4e
-                                  "%s: bind_ref: %d, ref: %d",
21ab4e
-                                  client->client_uid, client->ref.bind,
21ab4e
-                                  client->ref.count);
21ab4e
+                                  "%s: bind_ref: %"GF_PRI_ATOMIC", ref: "
21ab4e
+                                  "%"GF_PRI_ATOMIC, client->client_uid,
21ab4e
+                                  GF_ATOMIC_GET (client->bind),
21ab4e
+                                  GF_ATOMIC_GET (client->count));
21ab4e
         return client;
21ab4e
 }
21ab4e
 
21ab4e
@@ -295,14 +294,15 @@ gf_client_put (client_t *client, gf_boolean_t *detached)
21ab4e
         if (detached)
21ab4e
                 *detached = _gf_false;
21ab4e
 
21ab4e
-        bind_ref = DECREMENT_ATOMIC (client->ref.lock, client->ref.bind);
21ab4e
+        bind_ref = GF_ATOMIC_DEC (client->bind);
21ab4e
         if (bind_ref == 0)
21ab4e
                 unref = _gf_true;
21ab4e
 
21ab4e
         gf_msg_callingfn ("client_t", GF_LOG_DEBUG, 0, LG_MSG_BIND_REF, "%s: "
21ab4e
-                          "bind_ref: %d, ref: %d, unref: %d",
21ab4e
-                          client->client_uid, client->ref.bind,
21ab4e
-                          client->ref.count, unref);
21ab4e
+                          "bind_ref: %"GF_PRI_ATOMIC", ref: %"GF_PRI_ATOMIC", "
21ab4e
+                          "unref: %d", client->client_uid,
21ab4e
+                          GF_ATOMIC_GET (client->bind),
21ab4e
+                          GF_ATOMIC_GET (client->count), unref);
21ab4e
         if (unref) {
21ab4e
                 if (detached)
21ab4e
                         *detached = _gf_true;
21ab4e
@@ -322,10 +322,10 @@ gf_client_ref (client_t *client)
21ab4e
                 return NULL;
21ab4e
         }
21ab4e
 
21ab4e
-        INCREMENT_ATOMIC (client->ref.lock, client->ref.count);
21ab4e
+        GF_ATOMIC_INC (client->count);
21ab4e
         gf_msg_callingfn ("client_t", GF_LOG_DEBUG, 0, LG_MSG_REF_COUNT, "%s: "
21ab4e
-                          "ref-count %d", client->client_uid,
21ab4e
-                          client->ref.count);
21ab4e
+                          "ref-count %"GF_PRI_ATOMIC, client->client_uid,
21ab4e
+                          GF_ATOMIC_GET (client->count));
21ab4e
         return client;
21ab4e
 }
21ab4e
 
21ab4e
@@ -360,7 +360,6 @@ client_destroy (client_t *client)
21ab4e
         clienttable = client->this->ctx->clienttable;
21ab4e
 
21ab4e
         LOCK_DESTROY (&client->scratch_ctx.lock);
21ab4e
-        LOCK_DESTROY (&client->ref.lock);
21ab4e
 
21ab4e
         LOCK (&clienttable->lock);
21ab4e
         {
21ab4e
@@ -417,7 +416,7 @@ gf_client_disconnect (client_t *client)
21ab4e
 void
21ab4e
 gf_client_unref (client_t *client)
21ab4e
 {
21ab4e
-        int refcount;
21ab4e
+        uint64_t refcount;
21ab4e
 
21ab4e
         if (!client) {
21ab4e
                 gf_msg_callingfn ("client_t", GF_LOG_ERROR, EINVAL,
21ab4e
@@ -425,10 +424,10 @@ gf_client_unref (client_t *client)
21ab4e
                 return;
21ab4e
         }
21ab4e
 
21ab4e
-        refcount = DECREMENT_ATOMIC (client->ref.lock, client->ref.count);
21ab4e
+        refcount = GF_ATOMIC_DEC (client->count);
21ab4e
         gf_msg_callingfn ("client_t", GF_LOG_DEBUG, 0, LG_MSG_REF_COUNT, "%s: "
21ab4e
-                          "ref-count %d", client->client_uid,
21ab4e
-                          (int)client->ref.count);
21ab4e
+                          "ref-count %"GF_PRI_ATOMIC, client->client_uid,
21ab4e
+                          refcount);
21ab4e
         if (refcount == 0) {
21ab4e
                 gf_msg (THIS->name, GF_LOG_INFO, 0, LG_MSG_DISCONNECT_CLIENT,
21ab4e
                         "Shutting down connection %s", client->client_uid);
21ab4e
@@ -584,7 +583,8 @@ client_dump (client_t *client, char *prefix)
21ab4e
                 return;
21ab4e
 
21ab4e
         memset(key, 0, sizeof key);
21ab4e
-        gf_proc_dump_write("refcount", "%d", client->ref.count);
21ab4e
+        gf_proc_dump_write("refcount", GF_PRI_ATOMIC,
21ab4e
+                           GF_ATOMIC_GET (client->count));
21ab4e
 }
21ab4e
 
21ab4e
 
21ab4e
@@ -778,7 +778,8 @@ gf_client_dump_fdtables (xlator_t *this)
21ab4e
 
21ab4e
                         gf_proc_dump_build_key (key, "conn", "%d.ref",
21ab4e
                                                         count);
21ab4e
-                        gf_proc_dump_write (key, "%d", client->ref.count);
21ab4e
+                        gf_proc_dump_write (key, GF_PRI_ATOMIC,
21ab4e
+                                            GF_ATOMIC_GET (client->count));
21ab4e
                         if (client->bound_xl) {
21ab4e
                                 gf_proc_dump_build_key (key, "conn",
21ab4e
                                                         "%d.bound_xl", count);
21ab4e
diff --git a/libglusterfs/src/client_t.h b/libglusterfs/src/client_t.h
21ab4e
index 29ea7f2..31f1bd0 100644
21ab4e
--- a/libglusterfs/src/client_t.h
21ab4e
+++ b/libglusterfs/src/client_t.h
21ab4e
@@ -13,6 +13,7 @@
21ab4e
 
21ab4e
 #include "glusterfs.h"
21ab4e
 #include "locking.h"  /* for gf_lock_t, not included by glusterfs.h */
21ab4e
+#include "atomic.h" /* for gf_atomic_t */
21ab4e
 
21ab4e
 struct client_ctx {
21ab4e
         void     *ctx_key;
21ab4e
@@ -26,11 +27,8 @@ typedef struct _client_t {
21ab4e
                 unsigned short       count;
21ab4e
                 struct client_ctx   *ctx;
21ab4e
         }            scratch_ctx;
21ab4e
-        struct {
21ab4e
-                gf_lock_t            lock;
21ab4e
-                volatile int         bind;
21ab4e
-                volatile int         count;
21ab4e
-        }            ref;
21ab4e
+        gf_atomic_t                  bind;
21ab4e
+        gf_atomic_t                  count;
21ab4e
         xlator_t    *bound_xl;
21ab4e
         xlator_t    *this;
21ab4e
         int          tbl_index;
21ab4e
diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h
21ab4e
index a1ec8f0..69c4c6d 100644
21ab4e
--- a/libglusterfs/src/globals.h
21ab4e
+++ b/libglusterfs/src/globals.h
21ab4e
@@ -97,25 +97,8 @@
21ab4e
 #define THIS (*__glusterfs_this_location())
21ab4e
 #define DECLARE_OLD_THIS        xlator_t *old_THIS = THIS
21ab4e
 
21ab4e
-/*
21ab4e
- * a more comprehensive feature test is shown at
21ab4e
- * http://lists.iptel.org/pipermail/semsdev/2010-October/005075.html
21ab4e
- * this is sufficient for RHEL5 i386 builds
21ab4e
- */
21ab4e
-#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__i386__)
21ab4e
-# define INCREMENT_ATOMIC(lk, op) __sync_add_and_fetch(&op, 1)
21ab4e
-# define DECREMENT_ATOMIC(lk, op) __sync_sub_and_fetch(&op, 1)
21ab4e
-#else
21ab4e
-/* These are only here for old gcc, e.g. on RHEL5 i386.
21ab4e
- * We're not ever going to use this in an if stmt,
21ab4e
- * but let's be pedantically correct for style points */
21ab4e
-# define INCREMENT_ATOMIC(lk, op) do { LOCK (&lk;; ++op; UNLOCK (&lk;; } while (0)
21ab4e
-/* this is a gcc 'statement expression', it works with llvm/clang too */
21ab4e
-# define DECREMENT_ATOMIC(lk, op) ({ LOCK (&lk;; --op; UNLOCK (&lk;; op; })
21ab4e
-#endif
21ab4e
-
21ab4e
-xlator_t **__glusterfs_this_location ();
21ab4e
-xlator_t *glusterfs_this_get ();
21ab4e
+xlator_t **__glusterfs_this_location (void);
21ab4e
+xlator_t *glusterfs_this_get (void);
21ab4e
 int glusterfs_this_set (xlator_t *);
21ab4e
 
21ab4e
 /* syncopctx */
21ab4e
diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h
21ab4e
index f3a694c..9348151 100644
21ab4e
--- a/libglusterfs/src/logging.h
21ab4e
+++ b/libglusterfs/src/logging.h
21ab4e
@@ -37,6 +37,7 @@
21ab4e
 #endif
21ab4e
 #define GF_PRI_BLKSIZE     PRId32
21ab4e
 #define GF_PRI_SIZET       "zu"
21ab4e
+#define GF_PRI_ATOMIC      PRIu64
21ab4e
 
21ab4e
 #ifdef GF_DARWIN_HOST_OS
21ab4e
 #define GF_PRI_TIME "ld"
21ab4e
diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c
21ab4e
index 2b3208c..9f5f762 100644
21ab4e
--- a/libglusterfs/src/mem-pool.c
21ab4e
+++ b/libglusterfs/src/mem-pool.c
21ab4e
@@ -80,7 +80,7 @@ gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr, size_t size,
21ab4e
         }
21ab4e
         UNLOCK(&xl->mem_acct->rec[type].lock);
21ab4e
 
21ab4e
-        INCREMENT_ATOMIC (xl->mem_acct->lock, xl->mem_acct->refcnt);
21ab4e
+        GF_ATOMIC_INC (xl->mem_acct->refcnt);
21ab4e
 
21ab4e
         header = (struct mem_header *) ptr;
21ab4e
         header->type = type;
21ab4e
@@ -325,7 +325,7 @@ __gf_free (void *free_ptr)
21ab4e
         }
21ab4e
         UNLOCK (&mem_acct->rec[header->type].lock);
21ab4e
 
21ab4e
-        if (DECREMENT_ATOMIC (mem_acct->lock, mem_acct->refcnt) == 0) {
21ab4e
+        if (GF_ATOMIC_DEC (mem_acct->refcnt) == 0) {
21ab4e
                 FREE (mem_acct);
21ab4e
         }
21ab4e
 
21ab4e
diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h
21ab4e
index 0dc1863..1b27119 100644
21ab4e
--- a/libglusterfs/src/mem-pool.h
21ab4e
+++ b/libglusterfs/src/mem-pool.h
21ab4e
@@ -13,6 +13,7 @@
21ab4e
 
21ab4e
 #include "list.h"
21ab4e
 #include "locking.h"
21ab4e
+#include "atomic.h"
21ab4e
 #include "logging.h"
21ab4e
 #include "mem-types.h"
21ab4e
 #include <stdlib.h>
21ab4e
@@ -48,14 +49,7 @@ struct mem_acct_rec {
21ab4e
 
21ab4e
 struct mem_acct {
21ab4e
         uint32_t            num_types;
21ab4e
-        /*
21ab4e
-         * The lock is only used on ancient platforms (e.g. RHEL5) to keep
21ab4e
-         * refcnt increment/decrement atomic.  We could even make its existence
21ab4e
-         * conditional on the right set of version/feature checks, but it's so
21ab4e
-         * lightweight that it's not worth the obfuscation.
21ab4e
-         */
21ab4e
-        gf_lock_t           lock;
21ab4e
-        unsigned int        refcnt;
21ab4e
+        gf_atomic_t         refcnt;
21ab4e
         struct mem_acct_rec rec[0];
21ab4e
 };
21ab4e
 
21ab4e
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c
21ab4e
index e6807c5..6775efc 100644
21ab4e
--- a/libglusterfs/src/xlator.c
21ab4e
+++ b/libglusterfs/src/xlator.c
21ab4e
@@ -579,8 +579,7 @@ xlator_mem_acct_init (xlator_t *xl, int num_types)
21ab4e
         memset (xl->mem_acct, 0, sizeof(struct mem_acct));
21ab4e
 
21ab4e
         xl->mem_acct->num_types = num_types;
21ab4e
-        LOCK_INIT (&xl->mem_acct->lock);
21ab4e
-        xl->mem_acct->refcnt = 1;
21ab4e
+        GF_ATOMIC_INIT (xl->mem_acct->refcnt, 1);
21ab4e
 
21ab4e
         for (i = 0; i < num_types; i++) {
21ab4e
                 memset (&xl->mem_acct->rec[i], 0, sizeof(struct mem_acct_rec));
21ab4e
@@ -637,7 +636,7 @@ xlator_memrec_free (xlator_t *xl)
21ab4e
                 for (i = 0; i < mem_acct->num_types; i++) {
21ab4e
                         LOCK_DESTROY (&(mem_acct->rec[i].lock));
21ab4e
                 }
21ab4e
-                if (DECREMENT_ATOMIC (mem_acct->lock, mem_acct->refcnt) == 0) {
21ab4e
+                if (GF_ATOMIC_DEC (mem_acct->refcnt) == 0) {
21ab4e
                         FREE (mem_acct);
21ab4e
                         xl->mem_acct = NULL;
21ab4e
                 }
21ab4e
diff --git a/xlators/debug/io-stats/src/io-stats.c b/xlators/debug/io-stats/src/io-stats.c
21ab4e
index 5875616..23cab8b 100644
21ab4e
--- a/xlators/debug/io-stats/src/io-stats.c
21ab4e
+++ b/xlators/debug/io-stats/src/io-stats.c
21ab4e
@@ -248,7 +248,13 @@ is_fop_latency_started (call_frame_t *frame)
21ab4e
                 conf->incremental.fop_hits[GF_FOP_##op]++;              \
21ab4e
         } while (0)
21ab4e
 
21ab4e
-#if defined(HAVE_ATOMIC_BUILTINS)
21ab4e
+#if defined(HAVE_SYNC_BUILTINS)
21ab4e
+/* FIXME: use gf_atomic_t from libglusterfs/src/atomic.h
21ab4e
+ *
21ab4e
+ * This is currently not behaving correctly. Values are going out of sync in
21ab4e
+ * the case where HAVE_SYNC_BUILTINS are available, but are updated under a
21ab4e
+ * single lock for other cases.
21ab4e
+ */
21ab4e
 #define STATS_LOCK(x)
21ab4e
 #define STATS_UNLOCK(x)
21ab4e
 #define STATS_ADD(x,i)  __sync_add_and_fetch (&x, i)
21ab4e
diff --git a/xlators/performance/md-cache/src/md-cache.c b/xlators/performance/md-cache/src/md-cache.c
21ab4e
index cbda6b2..5dd21c1 100644
21ab4e
--- a/xlators/performance/md-cache/src/md-cache.c
21ab4e
+++ b/xlators/performance/md-cache/src/md-cache.c
21ab4e
@@ -23,6 +23,7 @@
21ab4e
 #include <sys/time.h>
21ab4e
 #include "md-cache-messages.h"
21ab4e
 #include "statedump.h"
21ab4e
+#include "atomic.h"
21ab4e
 
21ab4e
 /* TODO:
21ab4e
    - cache symlink() link names and nuke symlink-cache
21ab4e
@@ -30,19 +31,25 @@
21ab4e
 */
21ab4e
 
21ab4e
 struct mdc_statistics {
21ab4e
-        uint64_t stat_hit; /* No. of times lookup/stat was served from mdc */
21ab4e
-        uint64_t stat_miss; /* No. of times valid stat wasn't present in mdc */
21ab4e
-        uint64_t xattr_hit; /* No. of times getxattr was served from mdc, Note:
21ab4e
-                             this doesn't count the xattr served from lookup */
21ab4e
-        uint64_t xattr_miss; /* No. of times xattr req was WIND from mdc */
21ab4e
-        uint64_t negative_lookup; /* No. of negative lookups */
21ab4e
-        uint64_t nameless_lookup; /* No. of negative lookups that were sent
21ab4e
-                                     sent to bricks */
21ab4e
-        uint64_t stat_invals; /* No. of invalidates recieved from upcall*/
21ab4e
-        uint64_t xattr_invals; /* No. of invalidates recieved from upcall*/
21ab4e
-        uint64_t need_lookup; /* No. of lookups issued, because other xlators
21ab4e
-                               * requested for explicit lookup */
21ab4e
-        gf_lock_t lock;
21ab4e
+        gf_atomic_t stat_hit; /* No. of times lookup/stat was served from
21ab4e
+                                 mdc */
21ab4e
+
21ab4e
+        gf_atomic_t stat_miss; /* No. of times valid stat wasn't present in
21ab4e
+                                  mdc */
21ab4e
+
21ab4e
+        gf_atomic_t xattr_hit; /* No. of times getxattr was served from mdc,
21ab4e
+                                  Note: this doesn't count the xattr served
21ab4e
+                                  from lookup */
21ab4e
+
21ab4e
+        gf_atomic_t xattr_miss; /* No. of times xattr req was WIND from mdc */
21ab4e
+        gf_atomic_t negative_lookup; /* No. of negative lookups */
21ab4e
+        gf_atomic_t nameless_lookup; /* No. of negative lookups that were sent
21ab4e
+                                        to bricks */
21ab4e
+
21ab4e
+        gf_atomic_t stat_invals; /* No. of invalidates received from upcall */
21ab4e
+        gf_atomic_t xattr_invals; /* No. of invalidates received from upcall */
21ab4e
+        gf_atomic_t need_lookup; /* No. of lookups issued, because other
21ab4e
+                                    xlators requested for explicit lookup */
21ab4e
 };
21ab4e
 
21ab4e
 struct mdc_conf {
21ab4e
@@ -1034,8 +1041,7 @@ mdc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
21ab4e
 
21ab4e
         if (op_ret != 0) {
21ab4e
                 if (op_errno == ENOENT)
21ab4e
-                        INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                          conf->mdc_counter.negative_lookup);
21ab4e
+                        GF_ATOMIC_INC (conf->mdc_counter.negative_lookup);
21ab4e
                 goto out;
21ab4e
         }
21ab4e
 
21ab4e
@@ -1071,15 +1077,14 @@ mdc_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc,
21ab4e
 
21ab4e
         local = mdc_local_get (frame);
21ab4e
         if (!local) {
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.stat_miss);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.stat_miss);
21ab4e
                 goto uncached;
21ab4e
         }
21ab4e
 
21ab4e
         loc_copy (&local->loc, loc);
21ab4e
 
21ab4e
 	if (!loc->name) {
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                  conf->mdc_counter.nameless_lookup);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.nameless_lookup);
21ab4e
 
21ab4e
                 gf_msg_trace ("md-cache", 0, "Nameless lookup(%s) sent to the "
21ab4e
                               "brick", uuid_utoa (loc->inode->gfid));
21ab4e
@@ -1091,34 +1096,30 @@ mdc_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc,
21ab4e
         }
21ab4e
 
21ab4e
         if (mdc_inode_reset_need_lookup (this, loc->inode)) {
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                  conf->mdc_counter.need_lookup);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.need_lookup);
21ab4e
                 goto uncached;
21ab4e
         }
21ab4e
 
21ab4e
         ret = mdc_inode_iatt_get (this, loc->inode, &stbuf);
21ab4e
         if (ret != 0) {
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                  conf->mdc_counter.stat_miss);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.stat_miss);
21ab4e
                 goto uncached;
21ab4e
         }
21ab4e
 
21ab4e
         if (xdata) {
21ab4e
                 ret = mdc_inode_xatt_get (this, loc->inode, &xattr_rsp);
21ab4e
                 if (ret != 0) {
21ab4e
-                        INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                          conf->mdc_counter.xattr_miss);
21ab4e
+                        GF_ATOMIC_INC (conf->mdc_counter.xattr_miss);
21ab4e
                         goto uncached;
21ab4e
                 }
21ab4e
 
21ab4e
                 if (!mdc_xattr_satisfied (this, xdata, xattr_rsp)) {
21ab4e
-                        INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                          conf->mdc_counter.xattr_miss);
21ab4e
+                        GF_ATOMIC_INC (conf->mdc_counter.xattr_miss);
21ab4e
                         goto uncached;
21ab4e
                 }
21ab4e
         }
21ab4e
 
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.stat_hit);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.stat_hit);
21ab4e
         MDC_STACK_UNWIND (lookup, frame, 0, 0, loc->inode, &stbuf,
21ab4e
                           xattr_rsp, &postparent);
21ab4e
 
21ab4e
@@ -1184,13 +1185,13 @@ mdc_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
21ab4e
         if (ret != 0)
21ab4e
                 goto uncached;
21ab4e
 
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.stat_hit);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.stat_hit);
21ab4e
         MDC_STACK_UNWIND (stat, frame, 0, 0, &stbuf, xdata);
21ab4e
 
21ab4e
         return 0;
21ab4e
 
21ab4e
 uncached:
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.stat_miss);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.stat_miss);
21ab4e
         STACK_WIND (frame, mdc_stat_cbk,
21ab4e
                     FIRST_CHILD(this), FIRST_CHILD(this)->fops->stat,
21ab4e
                     loc, xdata);
21ab4e
@@ -1239,13 +1240,13 @@ mdc_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata)
21ab4e
         if (ret != 0)
21ab4e
                 goto uncached;
21ab4e
 
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.stat_hit);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.stat_hit);
21ab4e
         MDC_STACK_UNWIND (fstat, frame, 0, 0, &stbuf, xdata);
21ab4e
 
21ab4e
         return 0;
21ab4e
 
21ab4e
 uncached:
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.stat_miss);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.stat_miss);
21ab4e
         STACK_WIND (frame, mdc_fstat_cbk,
21ab4e
                     FIRST_CHILD(this), FIRST_CHILD(this)->fops->fstat,
21ab4e
                     fd, xdata);
21ab4e
@@ -2124,13 +2125,13 @@ mdc_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *key,
21ab4e
 		op_errno = ENODATA;
21ab4e
 	}
21ab4e
 
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.xattr_hit);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.xattr_hit);
21ab4e
         MDC_STACK_UNWIND (getxattr, frame, ret, op_errno, xattr, xdata);
21ab4e
 
21ab4e
         return 0;
21ab4e
 
21ab4e
 uncached:
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.xattr_miss);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.xattr_miss);
21ab4e
         STACK_WIND (frame, mdc_getxattr_cbk,
21ab4e
                     FIRST_CHILD(this), FIRST_CHILD(this)->fops->getxattr,
21ab4e
                     loc, key, xdata);
21ab4e
@@ -2189,13 +2190,13 @@ mdc_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *key,
21ab4e
 		op_errno = ENODATA;
21ab4e
 	}
21ab4e
 
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.xattr_hit);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.xattr_hit);
21ab4e
         MDC_STACK_UNWIND (fgetxattr, frame, ret, op_errno, xattr, xdata);
21ab4e
 
21ab4e
         return 0;
21ab4e
 
21ab4e
 uncached:
21ab4e
-        INCREMENT_ATOMIC (conf->mdc_counter.lock, conf->mdc_counter.xattr_miss);
21ab4e
+        GF_ATOMIC_INC (conf->mdc_counter.xattr_miss);
21ab4e
         STACK_WIND (frame, mdc_fgetxattr_cbk,
21ab4e
                     FIRST_CHILD(this), FIRST_CHILD(this)->fops->fgetxattr,
21ab4e
                     fd, key, xdata);
21ab4e
@@ -2665,8 +2666,7 @@ mdc_invalidate (xlator_t *this, void *data)
21ab4e
             (UP_NLINK | UP_RENAME_FLAGS | UP_FORGET | UP_INVAL_ATTR)) {
21ab4e
                 mdc_inode_iatt_invalidate (this, inode);
21ab4e
                 mdc_inode_xatt_invalidate (this, inode);
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                  conf->mdc_counter.stat_invals);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.stat_invals);
21ab4e
                 goto out;
21ab4e
         }
21ab4e
 
21ab4e
@@ -2679,8 +2679,7 @@ mdc_invalidate (xlator_t *this, void *data)
21ab4e
                  */
21ab4e
                 if (ret < 0)
21ab4e
                         goto out;
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                  conf->mdc_counter.stat_invals);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.stat_invals);
21ab4e
         }
21ab4e
 
21ab4e
         if (up_ci->flags & UP_XATTR) {
21ab4e
@@ -2689,15 +2688,13 @@ mdc_invalidate (xlator_t *this, void *data)
21ab4e
                 else
21ab4e
                         ret = mdc_inode_xatt_invalidate (this, inode);
21ab4e
 
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                  conf->mdc_counter.xattr_invals);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.xattr_invals);
21ab4e
         } else if (up_ci->flags & UP_XATTR_RM) {
21ab4e
                 tmp.inode = inode;
21ab4e
                 tmp.this = this;
21ab4e
                 ret = dict_foreach (up_ci->dict, mdc_inval_xatt, &tmp);
21ab4e
 
21ab4e
-                INCREMENT_ATOMIC (conf->mdc_counter.lock,
21ab4e
-                                  conf->mdc_counter.xattr_invals);
21ab4e
+                GF_ATOMIC_INC (conf->mdc_counter.xattr_invals);
21ab4e
         }
21ab4e
 
21ab4e
 out:
21ab4e
@@ -2922,6 +2919,16 @@ init (xlator_t *this)
21ab4e
 
21ab4e
         LOCK_INIT (&conf->lock);
21ab4e
         time (&conf->last_child_down);
21ab4e
+        /* initialize gf_atomic_t counters */
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.stat_hit, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.stat_miss, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.xattr_hit, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.xattr_miss, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.negative_lookup, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.nameless_lookup, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.stat_invals, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.xattr_invals, 0);
21ab4e
+        GF_ATOMIC_INIT (conf->mdc_counter.need_lookup, 0);
21ab4e
 
21ab4e
         /* If timeout is greater than 60s (default before the patch that added
21ab4e
          * cache invalidation support was added) then, cache invalidation
21ab4e
-- 
21ab4e
1.8.3.1
21ab4e