#include "rx.h"
#include "rx_globals.h"
#include "rx_trace.h"
+#include "rx_atomic.h"
#define AFSOP_STOP_RXCALLBACK 210 /* Stop CALLBACK process */
#define AFSOP_STOP_AFS 211 /* Stop AFS process */
#define AFSOP_STOP_BKG 212 /* Stop BKG process */
# include "rx_user.h"
# include "rx_clock.h"
# include "rx_queue.h"
+# include "rx_atomic.h"
# include "rx_globals.h"
# include "rx_trace.h"
# include <afs/rxgen_consts.h>
#include <stddef.h> /* for definition of offsetof() */
#endif
+#ifdef RX_ENABLE_LOCKS
+afs_kmutex_t rx_atomic_mutex;
+#endif
+
#ifdef AFS_PTHREAD_ENV
#include <assert.h>
MUTEX_INIT(&rx_clock_mutex, "clock", MUTEX_DEFAULT, 0);
MUTEX_INIT(&rx_stats_mutex, "stats", MUTEX_DEFAULT, 0);
MUTEX_INIT(&rx_waiting_mutex, "waiting", MUTEX_DEFAULT, 0);
+ MUTEX_INIT(&rx_atomic_mutex, "atomic", MUTEX_DEFAULT, 0);
MUTEX_INIT(&rx_quota_mutex, "quota", MUTEX_DEFAULT, 0);
MUTEX_INIT(&rx_pthread_mutex, "pthread", MUTEX_DEFAULT, 0);
MUTEX_INIT(&rx_packets_mutex, "packets", MUTEX_DEFAULT, 0);
* multi_handle->lock
* rxevent_lock
* rx_stats_mutex
+ * rx_atomic_mutex
*
* Do we need a lock to protect the peer field in the conn structure?
* conn->peer was previously a constant for all intents and so has no
--- /dev/null
+/*
+ * Copyright (c) 2010 Your Filesystem Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define RX_ATOMIC_INIT(i) { (i) }
+
+#ifdef AFS_NT40_ENV
+typedef struct {
+ volatile int var;
+} rx_atomic_t;
+
+static_inline void
+rx_atomic_set(rx_atomic_t *atomic, int val) {
+ atomic->var = val;
+}
+
+static_inline int
+rx_atomic_read(rx_atomic_t *atomic) {
+ return atomic->var;
+}
+
+static_inline void
+rx_atomic_inc(rx_atomic_t *atomic) {
+ InterlockedIncrement(&atomic->var);
+}
+
+static_inline int
+rx_atomic_inc_and_read(rx_atomic_t *atomic) {
+ return InterlockedIncrement(&atomic->var);
+}
+
+static_inline void
+rx_atomic_add(rx_atomic_t *atomic, int change) {
+ InterlockedExchangeAdd(&atomic->var, change);
+}
+
+static_inline void
+rx_atomic_dec(rx_atomic_t *atomic) {
+ InterlockedDecrement(&atomic->var);
+}
+
+static_inline void
+rx_atomic_sub(rx_atomic_t *atomic, int change) {
+ InterlockedExchangeAdd(&atomic->var, 0 - change);
+}
+
+#elif defined(AFS_DARWIN80_ENV) || defined(AFS_USR_DARWIN80_ENV)
+
+#include <libkern/OSAtomic.h>
+typedef struct {
+ volatile int var;
+} rx_atomic_t;
+
+static_inline void
+rx_atomic_set(rx_atomic_t *atomic, int val) {
+ atomic->var = val;
+}
+
+static_inline int
+rx_atomic_read(rx_atomic_t *atomic) {
+ return atomic->var;
+}
+
+static_inline void
+rx_atomic_inc(rx_atomic_t *atomic) {
+ OSAtomicIncrement32(&atomic->var);
+}
+
+static_inline int
+rx_atomic_inc_and_read(rx_atomic_t *atomic) {
+ return OSAtomicIncrement32(&atomic->var);
+}
+
+static_inline void
+rx_atomic_add(rx_atomic_t *atomic, int change) {
+ OSAtomicAdd32(change, &atomic->var);
+}
+
+static_inline void
+rx_atomic_dec(rx_atomic_t *atomic) {
+ OSAtomicDecrement32(&atomic->var);
+}
+
+static_inline void
+rx_atomic_sub(rx_atomic_t *atomic, int change) {
+ OSAtomicAdd32(0 - change, &atomic->var);
+}
+#elif defined(AFS_LINUX20_ENV) && defined(KERNEL)
+#include <asm/atomic.h>
+
+typedef atomic_t rx_atomic_t;
+
+#define rx_atomic_set(X) atomic_set(X)
+#define rx_atomic_read(X) atomic_read(X)
+#define rx_atomic_inc(X) atomic_inc(X)
+#define rx_atomic_inc_and_read(X) atomic_inc_return(X)
+#define rx_atomic_add(X, V) atomic_add(X, V)
+#define rx_atomic_dec(X) atomic_dec(X)
+#define rx_atomic_sub(X, V) atomic_sub(X, V)
+
+#elif defined(AFS_SUN58_ENV)
+typedef struct {
+ volatile int var;
+} rx_atomic_t;
+
+static_inline void
+rx_atomic_set(rx_atomic_t *atomic, int val) {
+ atomic->var = val;
+}
+
+static_inline int
+rx_atomic_read(rx_atomic_t *atomic) {
+ return atomic->var;
+}
+
+static_inline void
+rx_atomic_inc(rx_atomic_t *atomic) {
+ atomic_inc_32(&atomic->var);
+}
+
+static_inline int
+rx_atomic_inc_and_read(rx_atomic_t *atomic) {
+ return atomic_inc_32_nv(&atomic->var);
+}
+
+static_inline void
+rx_atomic_add(rx_atomic_t *atomic, int change) {
+ atomic_add_32(&atomic->var, change);
+}
+
+static_inline void
+rx_atomic_dec(rx_atomic_t *atomic) {
+ atomic_dec_32(&atomic->var);
+}
+
+static_inline void
+rx_atomic_sub(rx_atomic_t *atomic, int change) {
+ atomic_add_32(&object, 0 - change);
+}
+
+#elif defined(__GNUC__) && defined(HAVE_SYNC_FETCH_AND_ADD)
+
+typedef struct {
+ volatile int var;
+} rx_atomic_t;
+
+static_inline void
+rx_atomic_set(rx_atomic_t *atomic, int val) {
+ atomic->var = val;
+}
+
+static_inline int
+rx_atomic_read(rx_atomic_t *atomic) {
+ return atomic->var;
+}
+
+static_inline void
+rx_atomic_inc(rx_atomic_t *atomic) {
+ (void)__sync_fetch_and_add(&atomic->var, 1);
+}
+
+static_inline int
+rx_atomic_inc_and_read(rx_atomic_t *atomic) {
+ return __sync_add_and_fetch(&atomic->var, 1);
+}
+
+static_inline void
+rx_atomic_add(rx_atomic_t *atomic, int change) {
+ (void)__sync_fetch_and_add(&atomic->var, change);
+}
+
+static_inline void
+rx_atomic_dec(rx_atomic_t *atomic) {
+ (void)__sync_fetch_and_sub(&atomic->var, 1);
+}
+
+static_inline void
+rx_atomic_sub(rx_atomic_t *atomic, int change) {
+ (void)__sync_fetch_and_sub(&atomic->var, change);
+}
+
+#else
+
+/* If we're on a platform where we have no idea how to do atomics,
+ * then we fall back to using a single process wide mutex to protect
+ * all atomic variables. This won't be the quickest thing ever.
+ */
+
+#ifdef RX_ENABLE_LOCKS
+extern afs_kmutex_t rx_atomic_mutex;
+#endif
+
+typedef struct {
+ int var;
+} rx_atomic_t;
+
+static_inline void
+rx_atomic_set(rx_atomic_t *atomic, int val) {
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var = val;
+ MUTEX_EXIT(&rx_atomic_mutex);
+}
+
+static_inline int
+rx_atomic_read(rx_atomic_t *atomic) {
+ int out;
+
+ MUTEX_ENTER(&rx_atomic_mutex);
+ out = atomic->var;
+ MUTEX_EXIT(&rx_atomic_mutex);
+
+ return out;
+}
+
+static_inline void
+rx_atomic_inc(rx_atomic_t *atomic) {
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var++;
+ MUTEX_EXIT(&rx_atomic_mutex);
+}
+
+static_inline int
+rx_atomic_inc_and_read(rx_atomic_t *atomic) {
+ int retval;
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var++;
+ retval = atomic->var;
+ MUTEX_EXIT(&rx_atomic_mutex);
+ return retval;
+}
+
+static_inline void
+rx_atomic_add(rx_atomic_t *atomic, int change) {
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var += change;
+ MUTEX_EXIT(&rx_atomic_mutex);
+}
+
+static_inline void
+rx_atomic_dec(rx_atomic_t *atomic) {
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var--;
+ MUTEX_EXIT(&rx_atomic_mutex);
+}
+
+static_inline void
+rx_atomic_sub(rx_atomic_t *atomic, int change) {
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var -= change;
+ MUTEX_ENTER(&rx_atomic_mutex);
+}
+
+#endif