summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/syncop.h
diff options
context:
space:
mode:
authorAnand Avati <avati@redhat.com>2013-04-22 04:35:03 -0700
committerAnand Avati <avati@redhat.com>2013-05-04 00:33:01 -0700
commit83cedcd9be2676e63b1be72ecaf3316a781773cb (patch)
tree70c3bd94e31db88f86ae78cd1efa4f031046ef1d /libglusterfs/src/syncop.h
parent54b9cd3df357ac196af17f53282b3b1975dd4fb9 (diff)
synctask: implement barriers around yield, not the other way
In the current implementation, barriers are in the core of the syncprocessors. Wake()s are treated as syncbarrier wake. This is however delicate, as spurious wake()s of the synctask can mess up the accounting of the barrier and waking it prematurely. The fix is to keep yield() and wake() as the basic primitives, and implement barriers as an object impelemented on top of these primitives. This way, only an explicit barrier_wake() gets counted towards the barrier accounting, and spurious wakes will be truly safe. Change-Id: I8087f0f446113e5b2d0853431c0354335ccda076 BUG: 948686 Signed-off-by: Anand Avati <avati@redhat.com> Reviewed-on: http://review.gluster.org/4921 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Diffstat (limited to 'libglusterfs/src/syncop.h')
-rw-r--r--libglusterfs/src/syncop.h40
1 files changed, 27 insertions, 13 deletions
diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h
index cf044d40f36..7ede9663819 100644
--- a/libglusterfs/src/syncop.h
+++ b/libglusterfs/src/syncop.h
@@ -57,7 +57,6 @@ struct synctask {
void *stack;
int woken;
int slept;
- int waitfor;
int ret;
uid_t uid;
@@ -107,6 +106,16 @@ struct synclock {
};
typedef struct synclock synclock_t;
+
+struct syncbarrier {
+ pthread_mutex_t guard; /* guard the remaining members, pair @cond */
+ pthread_cond_t cond; /* waiting non-synctasks */
+ struct list_head waitq; /* waiting synctasks */
+ int count; /* count the number of wakes */
+};
+typedef struct syncbarrier syncbarrier_t;
+
+
struct syncargs {
int op_ret;
int op_errno;
@@ -128,11 +137,13 @@ struct syncargs {
dict_t *dict;
pthread_mutex_t lock_dict;
+ syncbarrier_t barrier;
+
/* do not touch */
struct synctask *task;
pthread_mutex_t mutex;
pthread_cond_t cond;
- int wakecnt;
+ int done;
};
@@ -143,7 +154,7 @@ struct syncargs {
} else { \
pthread_mutex_init (&args->mutex, NULL); \
pthread_cond_init (&args->cond, NULL); \
- args->wakecnt = 0; \
+ args->done = 0; \
} \
} while (0)
@@ -154,7 +165,7 @@ struct syncargs {
} else { \
pthread_mutex_lock (&args->mutex); \
{ \
- args->wakecnt++; \
+ args->done = 1; \
pthread_cond_signal (&args->cond); \
} \
pthread_mutex_unlock (&args->mutex); \
@@ -162,13 +173,13 @@ struct syncargs {
} while (0)
-#define __waitfor(args, cnt) do { \
+#define __yield(args) do { \
if (args->task) { \
- synctask_waitfor (args->task, cnt); \
+ synctask_yield (args->task); \
} else { \
pthread_mutex_lock (&args->mutex); \
{ \
- while (args->wakecnt < cnt) \
+ while (!args->done) \
pthread_cond_wait (&args->cond, \
&args->mutex); \
} \
@@ -179,9 +190,6 @@ struct syncargs {
} while (0)
-#define __yield(args) __waitfor(args, 1)
-
-
#define SYNCOP(subvol, stb, cbk, op, params ...) do { \
struct synctask *task = NULL; \
call_frame_t *frame = NULL; \
@@ -225,9 +233,9 @@ void synctask_yield (struct synctask *task);
void synctask_yawn (struct synctask *task);
void synctask_waitfor (struct synctask *task, int count);
-#define synctask_barrier_init(args) __yawn (args)
-#define synctask_barrier_wait(args, n) __waitfor (args, n)
-#define synctask_barrier_wake(args) __wake (args)
+#define synctask_barrier_init(args) syncbarrier_init (&args->barrier)
+#define synctask_barrier_wait(args, n) syncbarrier_wait (&args->barrier, n)
+#define synctask_barrier_wake(args) syncbarrier_wake (&args->barrier)
int synctask_setid (struct synctask *task, uid_t uid, gid_t gid);
#define SYNCTASK_SETID(uid, gid) synctask_setid (synctask_get(), uid, gid);
@@ -256,6 +264,12 @@ int synclock_lock (synclock_t *lock);
int synclock_trylock (synclock_t *lock);
int synclock_unlock (synclock_t *lock);
+
+int syncbarrier_init (syncbarrier_t *barrier);
+int syncbarrier_wait (syncbarrier_t *barrier, int waitfor);
+int syncbarrier_wake (syncbarrier_t *barrier);
+int syncbarrier_destroy (syncbarrier_t *barrier);
+
int syncop_lookup (xlator_t *subvol, loc_t *loc, dict_t *xattr_req,
/* out */
struct iatt *iatt, dict_t **xattr_rsp, struct iatt *parent);