diff options
author | dimitri staessens <[email protected]> | 2016-09-07 10:31:27 +0200 |
---|---|---|
committer | dimitri staessens <[email protected]> | 2016-09-07 10:31:27 +0200 |
commit | 6de6ada73798186ea1ac41c8cb1f8bf123e0f932 (patch) | |
tree | 5e06824ade8a0a5df1fea2573c2ac198867e0381 /src/lib | |
parent | 4645f409abe9916723baeae7f6ba164c3b69489c (diff) | |
download | ouroboros-6de6ada73798186ea1ac41c8cb1f8bf123e0f932.tar.gz ouroboros-6de6ada73798186ea1ac41c8cb1f8bf123e0f932.zip |
lib: Add lazy copy of flow_set
The flow_set now has a safe copy which is threadsafe for the select
call without needing a lock. This greatly speeds up consecutive
select calls.
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/dev.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/src/lib/dev.c b/src/lib/dev.c index 64327dd3..391563da 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -35,7 +35,9 @@ #include <stdio.h> struct flow_set { - bool b[IRMD_MAX_FLOWS]; + bool dirty; + bool b[IRMD_MAX_FLOWS]; /* working copy */ + bool s[IRMD_MAX_FLOWS]; /* safe copy */ pthread_rwlock_t lock; }; @@ -653,6 +655,8 @@ struct flow_set * flow_set_create() memset(&set->b, 0, sizeof(set->b)); + set->dirty = true; + return set; } @@ -660,6 +664,7 @@ void flow_set_zero(struct flow_set * set) { pthread_rwlock_wrlock(&set->lock); memset(&set->b, 0, sizeof(set->b)); + set->dirty = true; pthread_rwlock_unlock(&set->lock); } @@ -667,6 +672,7 @@ void flow_set_add(struct flow_set * set, int fd) { pthread_rwlock_wrlock(&set->lock); set->b[ai->flows[fd].port_id] = true; + set->dirty = true; pthread_rwlock_unlock(&set->lock); } @@ -674,6 +680,7 @@ void flow_set_del(struct flow_set * set, int fd) { pthread_rwlock_wrlock(&set->lock); set->b[ai->flows[fd].port_id] = false; + set->dirty = true; pthread_rwlock_unlock(&set->lock); } @@ -692,22 +699,23 @@ void flow_set_destroy(struct flow_set * set) free(set); } -static void flow_set_cpy(bool * dst, struct flow_set * src) +static void flow_set_cpy(struct flow_set * set) { - pthread_rwlock_rdlock(&src->lock); - memcpy(dst, src->b, IRMD_MAX_FLOWS); - pthread_rwlock_unlock(&src->lock); + pthread_rwlock_rdlock(&set->lock); + if (set->dirty) + memcpy(set->s, set->b, IRMD_MAX_FLOWS); + set->dirty = false; + pthread_rwlock_unlock(&set->lock); } int flow_select(struct flow_set * set, const struct timespec * timeout) { int port_id; - bool b[IRMD_MAX_FLOWS]; if (set == NULL) { port_id = shm_ap_rbuff_peek_b(ai->rb, NULL, timeout); } else { - flow_set_cpy(b, set); - port_id = shm_ap_rbuff_peek_b(ai->rb, (bool *) b, timeout); + flow_set_cpy(set); + port_id = shm_ap_rbuff_peek_b(ai->rb, (bool *) set->s, timeout); } if (port_id < 0) return port_id; |