[PATCH] IPC: provide finer grained flowcontrol
by Angus Salkeld
this will allow the user to control the behaviour better.
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbipcc.h | 10 ++++++++++
include/qb/qbipcs.h | 1 +
lib/ipc_int.h | 1 +
lib/ipcc.c | 17 ++++++++++++++---
lib/ipcs.c | 9 ++++++++-
5 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/include/qb/qbipcc.h b/include/qb/qbipcc.h
index 0d71293..acecac9 100644
--- a/include/qb/qbipcc.h
+++ b/include/qb/qbipcc.h
@@ -88,6 +88,16 @@ void qb_ipcc_disconnect(qb_ipcc_connection_t* c);
int32_t qb_ipcc_fd_get(qb_ipcc_connection_t* c, int32_t * fd);
/**
+ * Set the maximum allowable flowcontrol value.
+ *
+ * @note the default is 1
+ *
+ * @param c connection instance
+ * @param max the max allowable flowcontrol value (1 or 2)
+ */
+int32_t qb_ipcc_fc_enable_max_set(qb_ipcc_connection_t * c, uint32_t max);
+
+/**
* Send a message.
*
* @param c connection instance
diff --git a/include/qb/qbipcs.h b/include/qb/qbipcs.h
index eef90d2..aa8ce77 100644
--- a/include/qb/qbipcs.h
+++ b/include/qb/qbipcs.h
@@ -47,6 +47,7 @@ enum qb_ipcs_rate_limit {
QB_IPCS_RATE_NORMAL,
QB_IPCS_RATE_SLOW,
QB_IPCS_RATE_OFF,
+ QB_IPCS_RATE_OFF_2,
};
struct qb_ipcs_connection;
diff --git a/lib/ipc_int.h b/lib/ipc_int.h
index 0676989..e05c053 100644
--- a/lib/ipc_int.h
+++ b/lib/ipc_int.h
@@ -107,6 +107,7 @@ struct qb_ipcc_connection {
struct qb_ipc_one_way event;
struct qb_ipcc_funcs funcs;
struct qb_ipc_request_header *receive_buf;
+ uint32_t fc_enable_max;
};
int32_t qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
diff --git a/lib/ipcc.c b/lib/ipcc.c
index be09631..b63c676 100644
--- a/lib/ipcc.c
+++ b/lib/ipcc.c
@@ -49,6 +49,7 @@ qb_ipcc_connect(const char *name, size_t max_msg_size)
c->request.max_msg_size = response.max_msg_size;
c->event.max_msg_size = response.max_msg_size;
c->receive_buf = malloc(response.max_msg_size);
+ c->fc_enable_max = 1;
if (c->receive_buf == NULL) {
res = -ENOMEM;
goto disconnect_and_cleanup;
@@ -97,7 +98,7 @@ qb_ipcc_send(struct qb_ipcc_connection * c, const void *msg_ptr, size_t msg_len)
res = c->funcs.fc_get(&c->request);
if (res < 0) {
return res;
- } else if (res > 0) {
+ } else if (res > 0 && res <= c->fc_enable_max) {
return -EAGAIN;
} else {
/*
@@ -121,6 +122,16 @@ qb_ipcc_send(struct qb_ipcc_connection * c, const void *msg_ptr, size_t msg_len)
return res;
}
+int32_t
+qb_ipcc_fc_enable_max_set(struct qb_ipcc_connection * c, uint32_t max)
+{
+ if (c == NULL || max > 2) {
+ return -EINVAL;
+ }
+ c->fc_enable_max = max;
+ return 0;
+}
+
ssize_t
qb_ipcc_sendv(struct qb_ipcc_connection * c, const struct iovec * iov,
size_t iov_len)
@@ -141,7 +152,7 @@ qb_ipcc_sendv(struct qb_ipcc_connection * c, const struct iovec * iov,
res = c->funcs.fc_get(&c->request);
if (res < 0) {
return res;
- } else if (res > 0) {
+ } else if (res > 0 && res <= c->fc_enable_max) {
return -EAGAIN;
} else {
/*
@@ -202,7 +213,7 @@ qb_ipcc_sendv_recv(qb_ipcc_connection_t * c,
res = c->funcs.fc_get(&c->request);
if (res < 0) {
return res;
- } else if (res > 0) {
+ } else if (res > 0 && res <= c->fc_enable_max) {
return -EAGAIN;
} else {
/*
diff --git a/lib/ipcs.c b/lib/ipcs.c
index cf014d4..b1d64c7 100644
--- a/lib/ipcs.c
+++ b/lib/ipcs.c
@@ -154,6 +154,7 @@ qb_ipcs_request_rate_limit(struct qb_ipcs_service *s,
break;
case QB_IPCS_RATE_SLOW:
case QB_IPCS_RATE_OFF:
+ case QB_IPCS_RATE_OFF_2:
s->poll_priority = QB_LOOP_LOW;
break;
default:
@@ -168,7 +169,13 @@ qb_ipcs_request_rate_limit(struct qb_ipcs_service *s,
c = qb_list_entry(pos, struct qb_ipcs_connection, list);
qb_ipcs_connection_ref(c);
- qb_ipcs_flowcontrol_set(c, (rl == QB_IPCS_RATE_OFF));
+ if (rl == QB_IPCS_RATE_OFF) {
+ qb_ipcs_flowcontrol_set(c, 1);
+ } else if (rl == QB_IPCS_RATE_OFF_2) {
+ qb_ipcs_flowcontrol_set(c, 2);
+ } else {
+ qb_ipcs_flowcontrol_set(c, QB_FALSE);
+ }
if (old_p != s->poll_priority) {
(void)_modify_dispatch_descriptor_(c);
}
--
1.7.7.3
12 years, 6 months
Map iteration + notify bug
by Jan Friesse
Hi (Angus),
I found problem with map and libqb. Attached is simplest reproducer
which I was able to create.
Result is following:
Iter test.key1 = 0x5a2a290 (1)
Freeing value
Notify (nil) 0x5a2a290==15090== Invalid read of size 4
==15090== at 0x400988: notify_fn (in /root/a.out)
==15090== by 0x4E47190: trie_notify (trie.c:297)
==15090== by 0x4E46C37: trie_node_destroy (trie.c:125)
==15090== by 0x4E46C90: trie_node_deref (trie.c:138)
==15090== by 0x4E4762E: trie_iter_next (trie.c:437)
==15090== by 0x4E44D30: qb_map_iter_next (map.c:82)
==15090== by 0x400B33: main (in /root/a.out)
==15090== Address 0x5a2a290 is 0 bytes inside a block of size 8 free'd
==15090== at 0x4C2695D: free (vg_replace_malloc.c:366)
==15090== by 0x400B20: main (in /root/a.out)
==15090==
old value = 1
Iter test.key2 = 0x5a2a2e0 (2)
Freeing value
Notify (nil) 0x5a2a2e0old value = 2
==15090==
==15090== HEAP SUMMARY:
==15090== in use at exit: 4,304 bytes in 25 blocks
==15090== total heap usage: 29 allocs, 4 frees, 4,800 bytes allocated
==15090==
==15090== LEAK SUMMARY:
==15090== definitely lost: 32 bytes in 1 blocks
==15090== indirectly lost: 4,272 bytes in 24 blocks
==15090== possibly lost: 0 bytes in 0 blocks
==15090== still reachable: 0 bytes in 0 blocks
==15090== suppressed: 0 bytes in 0 blocks
==15090== Rerun with --leak-check=full to see details of leaked memory
==15090==
==15090== For counts of detected and suppressed errors, rerun with: -v
==15090== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 6 from 6)
There should be NO invalid read of size ... Main problem seems to be
with fact, that delete callback is called after free in iter, but in
that time, pointer is already freed. Possible workaround may be to free
value only in callback, but it can be very hard (impossible) to realize.
Regards,
Honza
12 years, 6 months
[PATCH] Improve the stopwatch doxygen comments.
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbutil.h | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/include/qb/qbutil.h b/include/qb/qbutil.h
index 7757d98..fcc8550 100644
--- a/include/qb/qbutil.h
+++ b/include/qb/qbutil.h
@@ -129,22 +129,29 @@ char *qb_strerror_r(int errnum, char *buf, size_t buflen);
typedef struct qb_util_stopwatch qb_util_stopwatch_t;
/**
- * Create a Stop Watch (to time operations)
+ * Create a Stopwatch (to time operations)
*/
qb_util_stopwatch_t * qb_util_stopwatch_create(void);
/**
- * Free the stop watch
+ * Free the stopwatch
*/
void qb_util_stopwatch_free(qb_util_stopwatch_t *sw);
/**
- * Start the stop watch
+ * Start the stopwatch
+ *
+ * This also acts as a reset. Essentially it sets the
+ * starting time.
*/
void qb_util_stopwatch_start(qb_util_stopwatch_t *sw);
/**
- * Stop the stop watch
+ * Stop the stopwatch
+ *
+ * This just allows you to get the elapsed time. So
+ * you can call this multiple times. Do not call qb_util_stopwatch_start()
+ * unless you want to reset the stopwatch.
*/
void qb_util_stopwatch_stop(qb_util_stopwatch_t *sw);
--
1.7.7.3
12 years, 6 months