MAJOR: channel: remove the BF_OUT_EMPTY flag
This flag was very problematic because it was composite in that both changes
to the pipe or to the buffer had to cause this flag to be updated, which is
not always simple (eg: there may not even be a channel attached to a buffer
at all).
There were not that many users of this flags, mostly setters. So the flag got
replaced with a macro which reports whether the channel is empty or not, by
checking both the pipe and the buffer.
One part of the change is sensible : the flag was also part of BF_MASK_STATIC,
which is used by process_session() to rescan all analysers in case the flag's
status changes. At first glance, none of the analysers seems to change its
mind base on this flag when it is subject to change, so it seems fine not to
add variation checks here. Otherwise it's possible that checking the buffer's
output size is more useful than checking the flag's replacement.
diff --git a/include/proto/channel.h b/include/proto/channel.h
index 6b5478d..83881ba 100644
--- a/include/proto/channel.h
+++ b/include/proto/channel.h
@@ -49,7 +49,7 @@
int buffer_insert_line2(struct channel *b, char *pos, const char *str, int len);
unsigned long long buffer_forward(struct channel *buf, unsigned long long bytes);
-/* Initialize all fields in the buffer. The BF_OUT_EMPTY flags is set. */
+/* Initialize all fields in the buffer. */
static inline void buffer_init(struct channel *buf)
{
buf->buf.o = 0;
@@ -60,13 +60,23 @@
buf->pipe = NULL;
buf->analysers = 0;
buf->cons = NULL;
- buf->flags = BF_OUT_EMPTY;
+ buf->flags = 0;
}
/*****************************************************************/
/* These functions are used to compute various buffer area sizes */
/*****************************************************************/
+/* Reports non-zero if the channel is empty, which means both its
+ * buffer and pipe are empty. The construct looks strange but is
+ * jump-less and much more efficient on both 32 and 64-bit than
+ * the boolean test.
+ */
+static inline unsigned int channel_is_empty(struct channel *c)
+{
+ return !(c->buf.o | (long)c->pipe);
+}
+
/* Return the number of reserved bytes in the buffer, which ensures that once
* all pending data are forwarded, the buffer still has global.tune.maxrewrite
* bytes free. The result is between 0 and global.maxrewrite, which is itself
@@ -151,14 +161,12 @@
/* Advances the buffer by <adv> bytes, which means that the buffer
* pointer advances, and that as many bytes from in are transferred
* to out. The caller is responsible for ensuring that adv is always
- * smaller than or equal to b->i. The BF_OUT_EMPTY flag is updated.
+ * smaller than or equal to b->i.
*/
static inline void b_adv(struct channel *b, unsigned int adv)
{
b->buf.i -= adv;
b->buf.o += adv;
- if (b->buf.o)
- b->flags &= ~BF_OUT_EMPTY;
b->buf.p = b_ptr(&b->buf, adv);
}
@@ -170,8 +178,6 @@
{
b->buf.i += adv;
b->buf.o -= adv;
- if (!b->buf.o && !b->pipe)
- b->flags |= BF_OUT_EMPTY;
b->buf.p = b_ptr(&b->buf, (int)-adv);
}
@@ -225,8 +231,6 @@
buf->buf.p = buffer_wrap_add(&buf->buf, buf->buf.p + buf->buf.i);
buf->buf.o += buf->buf.i;
buf->buf.i = 0;
- if (buf->buf.o)
- buf->flags &= ~BF_OUT_EMPTY;
}
/* Erase any content from buffer <buf> and adjusts flags accordingly. Note
@@ -239,9 +243,7 @@
buf->buf.i = 0;
buf->to_forward = 0;
buf->buf.p = buf->buf.data;
- buf->flags &= ~(BF_FULL | BF_OUT_EMPTY);
- if (!buf->pipe)
- buf->flags |= BF_OUT_EMPTY;
+ buf->flags &= ~BF_FULL;
}
/* Cut the "tail" of the buffer, which means strip it to the length of unsent
@@ -350,8 +352,6 @@
static inline void bo_skip(struct channel *buf, int len)
{
buf->buf.o -= len;
- if (!buf->buf.o && !buf->pipe)
- buf->flags |= BF_OUT_EMPTY;
if (buffer_len(&buf->buf) == 0)
buf->buf.p = buf->buf.data;
@@ -403,7 +403,7 @@
static inline int bo_getchr(struct channel *buf)
{
/* closed or empty + imminent close = -2; empty = -1 */
- if (unlikely(buf->flags & (BF_OUT_EMPTY|BF_SHUTW))) {
+ if (unlikely((buf->flags & BF_SHUTW) || channel_is_empty(buf))) {
if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW))
return -2;
return -1;
@@ -415,8 +415,8 @@
* buffer <b>, and moves <end> just after the end of <str>. <b>'s parameters
* (l, r, lr) are updated to be valid after the shift. the shift value
* (positive or negative) is returned. If there's no space left, the move is
- * not done. The function does not adjust ->o nor BF_OUT_EMPTY because
- * it does not make sense to use it on data scheduled to be sent.
+ * not done. The function does not adjust ->o because it does not make sense
+ * to use it on data scheduled to be sent.
*/
static inline int buffer_replace(struct channel *b, char *pos, char *end, const char *str)
{
diff --git a/include/types/channel.h b/include/types/channel.h
index cd16d9c..67016d1 100644
--- a/include/types/channel.h
+++ b/include/types/channel.h
@@ -70,7 +70,7 @@
#define BF_WRITE_ERROR 0x000800 /* unrecoverable error on consumer side */
#define BF_WRITE_ACTIVITY (BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_WRITE_ERROR)
-#define BF_OUT_EMPTY 0x001000 /* out and pipe are empty. Set by last change. */
+/* unused: 0x001000 */
#define BF_SHUTW 0x002000 /* consumer has already shut down */
#define BF_SHUTW_NOW 0x004000 /* the consumer must shut down for writes ASAP */
#define BF_AUTO_CLOSE 0x008000 /* producer can forward shutdown to other side */
@@ -129,7 +129,7 @@
#define BF_MASK_ANALYSER (BF_READ_ATTACHED|BF_READ_ACTIVITY|BF_READ_TIMEOUT|BF_ANA_TIMEOUT|BF_WRITE_ACTIVITY|BF_WAKE_ONCE)
/* Mask for static flags which cause analysers to be woken up when they change */
-#define BF_MASK_STATIC (BF_OUT_EMPTY|BF_FULL|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW)
+#define BF_MASK_STATIC (BF_FULL|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW)
/* Analysers (channel->analysers).