aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-10-09 18:10:57 -0700
committerGravatar Craig Tiller <ctiller@google.com>2015-10-09 18:12:15 -0700
commit8344daa1dfe627591b5566aaca705c1f8c057f4d (patch)
treeaa65bdc238ef5a0d3912ec3c6d2f06155dda92f5 /src/core
parent63bda56884f1dece057f84dc6f94f9c2a5ce1605 (diff)
Make getting metadata user data a lock free operation
Diffstat (limited to 'src/core')
-rw-r--r--src/core/transport/metadata.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index 02f9cda754..1b48b48e09 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -62,6 +62,8 @@
#define REF_MD_LOCKED(s) ref_md_locked((s))
#endif
+typedef void (*destroy_user_data_func)(void *user_data);
+
typedef struct internal_string {
/* must be byte compatible with grpc_mdstr */
gpr_slice slice;
@@ -88,8 +90,8 @@ typedef struct internal_metadata {
/* private only data */
gpr_mu mu_user_data;
- void *user_data;
- void (*destroy_user_data)(void *user_data);
+ gpr_atm destroy_user_data;
+ gpr_atm user_data;
grpc_mdctx *context;
struct internal_metadata *bucket_next;
@@ -201,12 +203,14 @@ static void discard_metadata(grpc_mdctx *ctx) {
for (i = 0; i < ctx->mdtab_capacity; i++) {
cur = ctx->mdtab[i];
while (cur) {
+ void *user_data = (void *)gpr_atm_no_barrier_load(&cur->user_data);
GPR_ASSERT(gpr_atm_acq_load(&cur->refcnt) == 0);
next = cur->bucket_next;
INTERNAL_STRING_UNREF(cur->key);
INTERNAL_STRING_UNREF(cur->value);
- if (cur->user_data) {
- cur->destroy_user_data(cur->user_data);
+ if (user_data != NULL) {
+ ((destroy_user_data_func)gpr_atm_no_barrier_load(
+ &cur->destroy_user_data))(user_data);
}
gpr_mu_destroy(&cur->mu_user_data);
gpr_free(cur);
@@ -392,12 +396,14 @@ static void gc_mdtab(grpc_mdctx *ctx) {
for (i = 0; i < ctx->mdtab_capacity; i++) {
prev_next = &ctx->mdtab[i];
for (md = ctx->mdtab[i]; md; md = next) {
+ void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data);
next = md->bucket_next;
if (gpr_atm_acq_load(&md->refcnt) == 0) {
INTERNAL_STRING_UNREF(md->key);
INTERNAL_STRING_UNREF(md->value);
if (md->user_data) {
- md->destroy_user_data(md->user_data);
+ ((destroy_user_data_func)gpr_atm_no_barrier_load(
+ &md->destroy_user_data))(user_data);
}
gpr_free(md);
*prev_next = next;
@@ -473,8 +479,8 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
md->context = ctx;
md->key = key;
md->value = value;
- md->user_data = NULL;
- md->destroy_user_data = NULL;
+ md->user_data = 0;
+ md->destroy_user_data = 0;
md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity];
gpr_mu_init(&md->mu_user_data);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
@@ -588,13 +594,14 @@ size_t grpc_mdctx_get_mdtab_free_test_only(grpc_mdctx *ctx) {
return ctx->mdtab_free;
}
-void *grpc_mdelem_get_user_data(grpc_mdelem *md,
- void (*if_destroy_func)(void *)) {
+void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) {
internal_metadata *im = (internal_metadata *)md;
void *result;
- gpr_mu_lock(&im->mu_user_data);
- result = im->destroy_user_data == if_destroy_func ? im->user_data : NULL;
- gpr_mu_unlock(&im->mu_user_data);
+ if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
+ return (void *)gpr_atm_no_barrier_load(&im->user_data);
+ } else {
+ return NULL;
+ }
return result;
}
@@ -603,7 +610,7 @@ void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
internal_metadata *im = (internal_metadata *)md;
GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
gpr_mu_lock(&im->mu_user_data);
- if (im->destroy_user_data) {
+ if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
/* user data can only be set once */
gpr_mu_unlock(&im->mu_user_data);
if (destroy_func != NULL) {
@@ -611,8 +618,8 @@ void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
}
return;
}
- im->destroy_user_data = destroy_func;
- im->user_data = user_data;
+ gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
+ gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
gpr_mu_unlock(&im->mu_user_data);
}