diff options
-rw-r--r-- | src/ipcpd/shim-data.c | 113 | ||||
-rw-r--r-- | src/ipcpd/shim-data.h | 9 | ||||
-rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 26 |
3 files changed, 87 insertions, 61 deletions
diff --git a/src/ipcpd/shim-data.c b/src/ipcpd/shim-data.c index 747a210b..355cec68 100644 --- a/src/ipcpd/shim-data.c +++ b/src/ipcpd/shim-data.c @@ -46,6 +46,40 @@ struct dir_entry { uint64_t addr; }; +static void destroy_dir_query(struct dir_query * query) +{ + assert(query); + + pthread_mutex_lock(&query->lock); + + switch (query->state) { + case QUERY_INIT: + query->state = QUERY_DONE; + break; + case QUERY_PENDING: + query->state = QUERY_DESTROY; + pthread_cond_broadcast(&query->cond); + break; + case QUERY_RESPONSE: + case QUERY_DONE: + break; + case QUERY_DESTROY: + pthread_mutex_unlock(&query->lock); + return; + } + + while (query->state != QUERY_DONE) + pthread_cond_wait(&query->cond, &query->lock); + + pthread_mutex_unlock(&query->lock); + + pthread_cond_destroy(&query->cond); + pthread_mutex_destroy(&query->lock); + + free(query->hash); + free(query); +} + static struct reg_entry * reg_entry_create(uint8_t * hash) { struct reg_entry * entry = malloc(sizeof(*entry)); @@ -151,7 +185,7 @@ static void clear_dir_queries(struct shim_data * data) list_for_each_safe(h, t, &data->dir_queries) { struct dir_query * e = list_entry(h, struct dir_query, next); list_del(&e->next); - shim_data_dir_query_destroy(e); + destroy_dir_query(e); } } @@ -391,7 +425,8 @@ uint64_t shim_data_dir_get_addr(struct shim_data * data, return addr; } -struct dir_query * shim_data_dir_query_create(const uint8_t * hash) +struct dir_query * shim_data_dir_query_create(struct shim_data * data, + const uint8_t * hash) { struct dir_query * query; pthread_condattr_t cattr; @@ -417,58 +452,64 @@ struct dir_query * shim_data_dir_query_create(const uint8_t * hash) list_head_init(&query->next); + pthread_mutex_lock(&data->dir_queries_lock); + list_add(&query->next, &data->dir_queries); + pthread_mutex_unlock(&data->dir_queries_lock); + return query; } -void shim_data_dir_query_respond(struct dir_query * query) +void shim_data_dir_query_respond(struct shim_data * data, + const uint8_t * hash) { - assert(query); + struct dir_query * e = NULL; + struct list_head * pos; + bool found = false; - pthread_mutex_lock(&query->lock); - - if (query->state != QUERY_PENDING) { - pthread_mutex_unlock(&query->lock); - return; - } - - query->state = QUERY_RESPONSE; - pthread_cond_broadcast(&query->cond); + pthread_mutex_lock(&data->dir_queries_lock); - while (query->state == QUERY_RESPONSE) - pthread_cond_wait(&query->cond, &query->lock); + list_for_each(pos, &data->dir_queries) { + e = list_entry(pos, struct dir_query, next); - pthread_mutex_unlock(&query->lock); -} + if (memcmp(e->hash, hash, ipcp_dir_hash_len()) == 0) { + found = true; + break; + } + } -void shim_data_dir_query_destroy(struct dir_query * query) -{ - assert(query); + if (!found) { + pthread_mutex_unlock(&data->dir_queries_lock); + return; + } - pthread_mutex_lock(&query->lock); + pthread_mutex_lock(&e->lock); - if (query->state == QUERY_DESTROY) { - pthread_mutex_unlock(&query->lock); + if (e->state != QUERY_PENDING) { + pthread_mutex_unlock(&e->lock); + pthread_mutex_unlock(&data->dir_queries_lock); return; } - if (query->state == QUERY_INIT) - query->state = QUERY_DONE; + e->state = QUERY_RESPONSE; + pthread_cond_broadcast(&e->cond); - if (query->state == QUERY_PENDING) { - query->state = QUERY_DESTROY; - pthread_cond_broadcast(&query->cond); - } + while (e->state == QUERY_RESPONSE) + pthread_cond_wait(&e->cond, &e->lock); - while (query->state != QUERY_DONE) - pthread_cond_wait(&query->cond, &query->lock); + pthread_mutex_unlock(&e->lock); - pthread_mutex_unlock(&query->lock); + pthread_mutex_unlock(&data->dir_queries_lock); +} - pthread_cond_destroy(&query->cond); - pthread_mutex_destroy(&query->lock); +void shim_data_dir_query_destroy(struct shim_data * data, + struct dir_query * query) +{ + pthread_mutex_lock(&data->dir_queries_lock); - free(query->hash); - free(query); + list_del(&query->next); + destroy_dir_query(query); + + pthread_mutex_unlock(&data->dir_queries_lock); } int shim_data_dir_query_wait(struct dir_query * query, diff --git a/src/ipcpd/shim-data.h b/src/ipcpd/shim-data.h index 983f97f6..6380eea7 100644 --- a/src/ipcpd/shim-data.h +++ b/src/ipcpd/shim-data.h @@ -85,11 +85,14 @@ bool shim_data_dir_has(struct shim_data * data, uint64_t shim_data_dir_get_addr(struct shim_data * data, const uint8_t * hash); -struct dir_query * shim_data_dir_query_create(const uint8_t * hash); +struct dir_query * shim_data_dir_query_create(struct shim_data * data, + const uint8_t * hash); -void shim_data_dir_query_respond(struct dir_query * query); +void shim_data_dir_query_destroy(struct shim_data * data, + struct dir_query * query); -void shim_data_dir_query_destroy(struct dir_query * query); +void shim_data_dir_query_respond(struct shim_data * data, + const uint8_t * hash); int shim_data_dir_query_wait(struct dir_query * query, const struct timespec * timeout); diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index e5f0cba8..b8e987ba 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -512,24 +512,13 @@ static int eth_llc_ipcp_name_query_req(const uint8_t * hash, static int eth_llc_ipcp_name_query_reply(const uint8_t * hash, uint8_t * r_addr) { - uint64_t address = 0; - struct list_head * pos; + uint64_t address = 0; memcpy(&address, r_addr, MAC_SIZE); shim_data_dir_add_entry(eth_llc_data.shim_data, hash, address); - pthread_mutex_lock(ð_llc_data.shim_data->dir_queries_lock); - - list_for_each(pos, ð_llc_data.shim_data->dir_queries) { - struct dir_query * e = - list_entry(pos, struct dir_query, next); - if (memcmp(e->hash, hash, ipcp_dir_hash_len()) == 0) { - shim_data_dir_query_respond(e); - } - } - - pthread_mutex_unlock(ð_llc_data.shim_data->dir_queries_lock); + shim_data_dir_query_respond(eth_llc_data.shim_data, hash); return 0; } @@ -1053,22 +1042,15 @@ static int eth_llc_ipcp_query(const uint8_t * hash) memset(r_addr, 0xff, MAC_SIZE); - query = shim_data_dir_query_create(hash); + query = shim_data_dir_query_create(eth_llc_data.shim_data, hash); if (query == NULL) return -1; - pthread_mutex_lock(ð_llc_data.shim_data->dir_queries_lock); - list_add(&query->next, ð_llc_data.shim_data->dir_queries); - pthread_mutex_unlock(ð_llc_data.shim_data->dir_queries_lock); - eth_llc_ipcp_send_mgmt_frame(&msg, r_addr); ret = shim_data_dir_query_wait(query, &timeout); - pthread_mutex_lock(ð_llc_data.shim_data->dir_queries_lock); - list_del(&query->next); - shim_data_dir_query_destroy(query); - pthread_mutex_unlock(ð_llc_data.shim_data->dir_queries_lock); + shim_data_dir_query_destroy(eth_llc_data.shim_data, query); return ret; } |