summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordimitri staessens <[email protected]>2016-07-11 22:11:36 +0200
committerdimitri staessens <[email protected]>2016-07-11 22:28:33 +0200
commite04defa422bd7d365d9d8389fde13e675e9783a2 (patch)
tree97858c114caf656a94d4267fa599b272e19d6725
parent39462e9b22509f59e9fa9afb8eec31988c21dece (diff)
downloadouroboros-e04defa422bd7d365d9d8389fde13e675e9783a2.tar.gz
ouroboros-e04defa422bd7d365d9d8389fde13e675e9783a2.zip
lib: shm_du_map: PCI allocation / deallocation
Correct implementation of allocation for the Protocol Control Information. Also removes stale code checking for a corner case when the du map still wrapped multi-block SDU's.
-rw-r--r--include/ouroboros/shm_du_map.h24
-rw-r--r--src/lib/shm_du_map.c124
2 files changed, 103 insertions, 45 deletions
diff --git a/include/ouroboros/shm_du_map.h b/include/ouroboros/shm_du_map.h
index 23c0c3aa..11fe35c6 100644
--- a/include/ouroboros/shm_du_map.h
+++ b/include/ouroboros/shm_du_map.h
@@ -50,16 +50,18 @@ int shm_du_map_read(uint8_t ** dst,
struct shm_du_map * dum,
ssize_t idx);
int shm_du_map_remove(struct shm_du_map * dum,
- ssize_t idx);
-
-/* FIXME: use shm_du_map * and index */
-uint8_t * shm_du_buff_head_alloc(struct shm_du_buff * sdb,
- size_t size);
-uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb,
- size_t size);
-int shm_du_buff_head_release(struct shm_du_buff * sdb,
- size_t size);
-int shm_du_buff_tail_release(struct shm_du_buff * sdb,
- size_t size);
+ ssize_t idx);
+uint8_t * shm_du_buff_head_alloc(struct shm_du_map * dum,
+ int idx,
+ ssize_t size);
+uint8_t * shm_du_buff_tail_alloc(struct shm_du_map * dum,
+ int idx,
+ ssize_t size);
+int shm_du_buff_head_release(struct shm_du_map * dum,
+ int idx,
+ ssize_t size);
+int shm_du_buff_tail_release(struct shm_du_map * dum,
+ int idx,
+ ssize_t size);
#endif /* OUROBOROS_SHM_DU_MAP_H */
diff --git a/src/lib/shm_du_map.c b/src/lib/shm_du_map.c
index 6a4b7361..9d2d4f6e 100644
--- a/src/lib/shm_du_map.c
+++ b/src/lib/shm_du_map.c
@@ -413,8 +413,7 @@ ssize_t shm_du_map_write(struct shm_du_map * dum,
#ifdef SHM_DU_MAP_MULTI_BLOCK
long blocks = 0;
long padblocks = 0;
- int sz = headspace + len + sizeof *sdb;
- int sz2 = sz + tailspace;
+ int sz = size + sizeof *sdb;
#endif
uint8_t * write_pos;
ssize_t index = -1;
@@ -425,7 +424,7 @@ ssize_t shm_du_map_write(struct shm_du_map * dum,
}
#ifndef SHM_DU_MAP_MULTI_BLOCK
- if (size + sizeof *sdb > SHM_DU_BUFF_BLOCK_SIZE) {
+ if (sz > SHM_DU_BUFF_BLOCK_SIZE) {
LOG_DBGF("Multi-block SDU's disabled. Dropping.");
return -1;
}
@@ -435,14 +434,8 @@ ssize_t shm_du_map_write(struct shm_du_map * dum,
pthread_mutex_consistent(dum->shm_mutex);
}
#ifdef SHM_DU_MAP_MULTI_BLOCK
- while (sz2 > 0) {
- sz2 -= SHM_DU_BUFF_BLOCK_SIZE;
+ while (sz > 0) {
sz -= SHM_DU_BUFF_BLOCK_SIZE;
- if (sz < 0 && sz2 > 0) {
- pthread_mutex_unlock(dum->shm_mutex);
- LOG_DBG("Can't handle this packet now.");
- return -EAGAIN;
- }
++blocks;
}
@@ -478,7 +471,7 @@ ssize_t shm_du_map_write(struct shm_du_map * dum,
#ifdef SHM_DU_MAP_MULTI_BLOCK
sdb->blocks = blocks;
#endif
- write_pos = ((uint8_t *) sdb) + sizeof *sdb + headspace;
+ write_pos = ((uint8_t *) (sdb + 1)) + headspace;
memcpy(write_pos, data, len);
@@ -515,7 +508,7 @@ int shm_du_map_read(uint8_t ** dst,
sdb = idx_to_du_buff_ptr(dum, idx);
len = sdb->du_tail - sdb->du_head;
- *dst = ((uint8_t *) sdb) + sizeof(struct shm_du_buff) + sdb->du_head;
+ *dst = ((uint8_t *) (sdb + 1)) + sdb->du_head;
pthread_mutex_unlock(dum->shm_mutex);
@@ -547,6 +540,7 @@ int shm_du_map_remove(struct shm_du_map * dum, ssize_t idx)
garbage_collect(dum);
*dum->choked = 0;
+
pthread_cond_signal(dum->healthy);
pthread_mutex_unlock(dum->shm_mutex);
@@ -554,74 +548,136 @@ int shm_du_map_remove(struct shm_du_map * dum, ssize_t idx)
return 0;
}
-uint8_t * shm_du_buff_head_alloc(struct shm_du_buff * sdb,
- size_t size)
+uint8_t * shm_du_buff_head_alloc(struct shm_du_map * dum,
+ int idx,
+ ssize_t size)
{
- if (sdb == NULL) {
- LOG_DBGF("Bogus input, bugging out.");
+ struct shm_du_buff * sdb;
+ uint8_t * buf;
+
+ if (dum == NULL)
+ return NULL;
+
+ if (idx < 0 || idx > SHM_BLOCKS_IN_MAP)
return NULL;
+
+ if (pthread_mutex_lock(dum->shm_mutex) == EOWNERDEAD) {
+ LOG_DBGF("Recovering dead mutex.");
+ pthread_mutex_consistent(dum->shm_mutex);
}
+ sdb = idx_to_du_buff_ptr(dum, idx);
+
if ((long) (sdb->du_head - size) < 0) {
+ pthread_mutex_unlock(dum->shm_mutex);
LOG_DBGF("Failed to allocate PCI headspace.");
return NULL;
}
sdb->du_head -= size;
- return (uint8_t *) sdb + sizeof *sdb + sdb->du_head;
+ buf = (uint8_t *) (sdb + 1) + sdb->du_head;
+
+ pthread_mutex_unlock(dum->shm_mutex);
+
+ return buf;
}
-uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb,
- size_t size)
+uint8_t * shm_du_buff_tail_alloc(struct shm_du_map * dum,
+ int idx,
+ ssize_t size)
{
- if (sdb == NULL) {
- LOG_DBGF("Bogus input, bugging out.");
+ struct shm_du_buff * sdb;
+ uint8_t * buf;
+
+ if (dum == NULL)
return NULL;
+
+ if (idx < 0 || idx > SHM_BLOCKS_IN_MAP)
+ return NULL;
+
+ if (pthread_mutex_lock(dum->shm_mutex) == EOWNERDEAD) {
+ LOG_DBGF("Recovering dead mutex.");
+ pthread_mutex_consistent(dum->shm_mutex);
}
+ sdb = idx_to_du_buff_ptr(dum, idx);
+
if (sdb->du_tail + size >= sdb->size) {
+ pthread_mutex_unlock(dum->shm_mutex);
LOG_DBGF("Failed to allocate PCI tailspace.");
return NULL;
}
+ buf = (uint8_t *) (sdb + 1) + sdb->du_tail;
+
sdb->du_tail += size;
- return (uint8_t *) sdb + sizeof *sdb + sdb->du_tail;
+ pthread_mutex_unlock(dum->shm_mutex);
+
+ return buf;
}
-int shm_du_buff_head_release(struct shm_du_buff * sdb,
- size_t size)
+int shm_du_buff_head_release(struct shm_du_map * dum,
+ int idx,
+ ssize_t size)
{
- if (sdb == NULL) {
- LOG_DBGF("Bogus input, bugging out.");
- return -EINVAL;
+ struct shm_du_buff * sdb;
+
+ if (dum == NULL)
+ return -1;
+
+ if (idx < 0 || idx > SHM_BLOCKS_IN_MAP)
+ return -1;
+
+ if (pthread_mutex_lock(dum->shm_mutex) == EOWNERDEAD) {
+ LOG_DBGF("Recovering dead mutex.");
+ pthread_mutex_consistent(dum->shm_mutex);
}
+ sdb = idx_to_du_buff_ptr(dum, idx);
+
if (size > sdb->du_tail - sdb->du_head) {
+ pthread_mutex_unlock(dum->shm_mutex);
LOG_DBGF("Tried to release beyond sdu boundary.");
return -EOVERFLOW;
}
sdb->du_head += size;
- return sdb->du_head;
+ pthread_mutex_unlock(dum->shm_mutex);
+
+ return 0;
}
-int shm_du_buff_tail_release(struct shm_du_buff * sdb,
- size_t size)
+int shm_du_buff_tail_release(struct shm_du_map * dum,
+ int idx,
+ ssize_t size)
{
- if (sdb == NULL) {
- LOG_DBGF("Bogus input, bugging out.");
- return -EINVAL;
+ struct shm_du_buff * sdb;
+
+ if (dum == NULL)
+ return -1;
+
+ if (idx < 0 || idx > SHM_BLOCKS_IN_MAP)
+ return -1;
+
+ if (pthread_mutex_lock(dum->shm_mutex) == EOWNERDEAD) {
+ LOG_DBGF("Recovering dead mutex.");
+ pthread_mutex_consistent(dum->shm_mutex);
}
+ sdb = idx_to_du_buff_ptr(dum, idx);
+
if (size > sdb->du_tail - sdb->du_head) {
+ pthread_mutex_unlock(dum->shm_mutex);
LOG_DBGF("Tried to release beyond sdu boundary.");
return -EOVERFLOW;
}
sdb->du_tail -= size;
- return sdb->du_tail;
+ pthread_mutex_unlock(dum->shm_mutex);
+
+ return 0;
}