diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-05-18 21:21:19 +0000 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-07-11 14:57:57 +0400 |
commit | f7b2b5c9c05831e6f5ba4af1d03524980aee1f52 (patch) | |
tree | df17a02f54a3f9a6766ac4213d70ce48107ebe0f | |
parent | 34751881be05d546f04dea2515e5b0d2617bff7c (diff) | |
download | accel-ppp-f7b2b5c9c05831e6f5ba4af1d03524980aee1f52.tar.gz accel-ppp-f7b2b5c9c05831e6f5ba4af1d03524980aee1f52.zip |
triton: fix possible race
-rw-r--r-- | accel-pppd/triton/md.c | 2 | ||||
-rw-r--r-- | accel-pppd/triton/timer.c | 8 | ||||
-rw-r--r-- | accel-pppd/triton/triton.c | 9 | ||||
-rw-r--r-- | accel-pppd/triton/triton_p.h | 2 |
4 files changed, 15 insertions, 6 deletions
diff --git a/accel-pppd/triton/md.c b/accel-pppd/triton/md.c index c9ec32e..c97be45 100644 --- a/accel-pppd/triton/md.c +++ b/accel-pppd/triton/md.c @@ -100,6 +100,7 @@ static void *md_thread(void *arg) while (!list_empty(&freed_list2)) { h = list_entry(freed_list2.next, typeof(*h), entry); list_del(&h->entry); + triton_context_release(h->ctx); mempool_free(h); } @@ -125,6 +126,7 @@ void __export triton_md_register_handler(struct triton_context_t *ctx, struct tr h->ctx = (struct _triton_context_t *)ctx->tpd; else h->ctx = (struct _triton_context_t *)default_ctx.tpd; + __sync_add_and_fetch(&h->ctx->refs, 1); ud->tpd = h; spin_lock(&h->ctx->lock); list_add_tail(&h->entry, &h->ctx->handlers); diff --git a/accel-pppd/triton/timer.c b/accel-pppd/triton/timer.c index e5ebeb5..d0ebcb4 100644 --- a/accel-pppd/triton/timer.c +++ b/accel-pppd/triton/timer.c @@ -107,15 +107,12 @@ void *timer_thread(void *arg) while (!list_empty(&freed_list2)) { t = list_entry(freed_list2.next, typeof(*t), entry); list_del(&t->entry); + triton_context_release(t->ctx); mempool_free(t); } pthread_mutex_lock(&freed_list_lock); - while (!list_empty(&freed_list)) { - t = list_entry(freed_list.next, typeof(*t), entry); - list_del(&t->entry); - list_add(&t->entry, &freed_list2); - } + list_splice_init(&freed_list, &freed_list2); pthread_mutex_unlock(&freed_list_lock); } @@ -147,6 +144,7 @@ int __export triton_timer_add(struct triton_context_t *ctx, struct triton_timer_ goto out_err; } + __sync_add_and_fetch(&t->ctx->refs, 1); ud->tpd = t; if (triton_timer_mod(ud, abs_time)) diff --git a/accel-pppd/triton/triton.c b/accel-pppd/triton/triton.c index f17ae31..667bb06 100644 --- a/accel-pppd/triton/triton.c +++ b/accel-pppd/triton/triton.c @@ -169,7 +169,7 @@ cont: if (thread->ctx->need_free) { log_debug2("- context %p removed\n", thread->ctx); - mempool_free(thread->ctx); + triton_context_release(thread->ctx); } thread->ctx = NULL; @@ -296,6 +296,12 @@ int triton_queue_ctx(struct _triton_context_t *ctx) return 1; } +void triton_context_release(struct _triton_context_t *ctx) +{ + if (__sync_sub_and_fetch(&ctx->refs, 1) == 0) + mempool_free(ctx); +} + int __export triton_context_register(struct triton_context_t *ud, void *bf_arg) { struct _triton_context_t *ctx = mempool_alloc(ctx_pool); @@ -308,6 +314,7 @@ int __export triton_context_register(struct triton_context_t *ud, void *bf_arg) ctx->ud = ud; ctx->bf_arg = bf_arg; ctx->init = 1; + ctx->refs = 1; spinlock_init(&ctx->lock); INIT_LIST_HEAD(&ctx->handlers); INIT_LIST_HEAD(&ctx->timers); diff --git a/accel-pppd/triton/triton_p.h b/accel-pppd/triton/triton_p.h index 443cede..9401729 100644 --- a/accel-pppd/triton/triton_p.h +++ b/accel-pppd/triton/triton_p.h @@ -41,6 +41,7 @@ struct _triton_context_t int need_free; int pending; int priority; + int refs; struct triton_context_t *ud; void *bf_arg; @@ -107,5 +108,6 @@ int conf_reload(const char *fname); void triton_log_error(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); void triton_log_debug(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2))); int load_modules(const char *name); +void triton_context_release(struct _triton_context_t *ctx); #endif |