summaryrefslogtreecommitdiff
path: root/src/lib/shm_rdrbuff.c
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri.staessens@ugent.be>2018-03-11 14:28:49 +0100
committerSander Vrijders <sander.vrijders@ugent.be>2018-03-12 10:32:24 +0100
commit9bf0d277416c342a8a9e0b2017b2b10f1d093245 (patch)
treeea940f7f3337d5543aff9e1d2ef04f6b544ad899 /src/lib/shm_rdrbuff.c
parent6a4151baa8231cdaf746761fd8dc4aacb895c9e5 (diff)
downloadouroboros-9bf0d277416c342a8a9e0b2017b2b10f1d093245.tar.gz
ouroboros-9bf0d277416c342a8a9e0b2017b2b10f1d093245.zip
lib: Implement timeout on blocking write
This completes the implementation of the SNDTIMEO for a blocking write. Fixes #6. Signed-off-by: Dimitri Staessens <dimitri.staessens@ugent.be> Signed-off-by: Sander Vrijders <sander.vrijders@ugent.be>
Diffstat (limited to 'src/lib/shm_rdrbuff.c')
-rw-r--r--src/lib/shm_rdrbuff.c63
1 files changed, 38 insertions, 25 deletions
diff --git a/src/lib/shm_rdrbuff.c b/src/lib/shm_rdrbuff.c
index d5526c49..d1ad5a3b 100644
--- a/src/lib/shm_rdrbuff.c
+++ b/src/lib/shm_rdrbuff.c
@@ -419,11 +419,12 @@ ssize_t shm_rdrbuff_write(struct shm_rdrbuff * rdrb,
return sdb->idx;
}
-ssize_t shm_rdrbuff_write_b(struct shm_rdrbuff * rdrb,
- size_t headspace,
- size_t tailspace,
- const uint8_t * data,
- size_t len)
+ssize_t shm_rdrbuff_write_b(struct shm_rdrbuff * rdrb,
+ size_t headspace,
+ size_t tailspace,
+ const uint8_t * data,
+ size_t len,
+ const struct timespec * abstime)
{
struct shm_du_buff * sdb;
size_t size = headspace + len + tailspace;
@@ -432,6 +433,7 @@ ssize_t shm_rdrbuff_write_b(struct shm_rdrbuff * rdrb,
size_t padblocks = 0;
#endif
ssize_t sz = size + sizeof(*sdb);
+ int ret = 0;
assert(rdrb);
@@ -457,39 +459,50 @@ ssize_t shm_rdrbuff_write_b(struct shm_rdrbuff * rdrb,
if (blocks + *rdrb->head > (SHM_BUFFER_SIZE))
padblocks = (SHM_BUFFER_SIZE) - *rdrb->head;
- while (!shm_rdrb_free(rdrb, (blocks + padblocks))) {
+ while (!shm_rdrb_free(rdrb, (blocks + padblocks)) && ret != ETIMEDOUT) {
#else
- while (!shm_rdrb_free(rdrb, 1)) {
+ while (!shm_rdrb_free(rdrb, 1) && ret != ETIMEDOUT) {
#endif
pthread_cond_broadcast(rdrb->full);
- pthread_cond_wait(rdrb->healthy, rdrb->lock);
+ if (abstime != NULL)
+ ret = pthread_cond_timedwait(rdrb->healthy,
+ rdrb->lock,
+ abstime);
+ else
+ ret = pthread_cond_wait(rdrb->healthy, rdrb->lock);
}
+ if (ret != ETIMEDOUT) {
#ifdef SHM_RDRB_MULTI_BLOCK
- if (padblocks) {
- sdb = get_head_ptr(rdrb);
- sdb->size = 0;
- sdb->blocks = padblocks;
- sdb->flags = SDB_NULL;
- sdb->du_head = 0;
- sdb->du_tail = 0;
- sdb->idx = *rdrb->head;
-
- *rdrb->head = 0;
- }
+ if (padblocks) {
+ sdb = get_head_ptr(rdrb);
+ sdb->size = 0;
+ sdb->blocks = padblocks;
+ sdb->flags = SDB_NULL;
+ sdb->du_head = 0;
+ sdb->du_tail = 0;
+ sdb->idx = *rdrb->head;
+
+ *rdrb->head = 0;
+ }
#endif
- sdb = get_head_ptr(rdrb);
- sdb->flags = SDB_VALID;
- sdb->idx = *rdrb->head;
+ sdb = get_head_ptr(rdrb);
+ sdb->flags = SDB_VALID;
+ sdb->idx = *rdrb->head;
#ifdef SHM_RDRB_MULTI_BLOCK
- sdb->blocks = blocks;
+ sdb->blocks = blocks;
- *rdrb->head = (*rdrb->head + blocks) & ((SHM_BUFFER_SIZE) - 1);
+ *rdrb->head = (*rdrb->head + blocks) & ((SHM_BUFFER_SIZE) - 1);
#else
- *rdrb->head = (*rdrb->head + 1) & ((SHM_BUFFER_SIZE) - 1);
+ *rdrb->head = (*rdrb->head + 1) & ((SHM_BUFFER_SIZE) - 1);
#endif
+ }
+
pthread_cleanup_pop(true);
+ if (ret == ETIMEDOUT)
+ return -ETIMEDOUT;
+
sdb->size = size;
sdb->du_head = headspace;
sdb->du_tail = sdb->du_head + len;