diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-09 13:04:41 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:37 +0200 |
commit | e4a8065910cd6b2e7e0448cc6431ca2906322389 (patch) | |
tree | 73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys/kern/subr_sbuf.c | |
parent | Update to FreeBSD head 2017-08-01 (diff) | |
download | rtems-libbsd-e4a8065910cd6b2e7e0448cc6431ca2906322389.tar.bz2 |
Update to FreeBSD head 2017-10-01
Git mirror commit b2f0376b45428f13151d229c5ae9d4d8f74acbd1.
Update #3472.
Diffstat (limited to 'freebsd/sys/kern/subr_sbuf.c')
-rw-r--r-- | freebsd/sys/kern/subr_sbuf.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/freebsd/sys/kern/subr_sbuf.c b/freebsd/sys/kern/subr_sbuf.c index 8dd11b07..951cb50c 100644 --- a/freebsd/sys/kern/subr_sbuf.c +++ b/freebsd/sys/kern/subr_sbuf.c @@ -75,6 +75,8 @@ static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); #define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) #define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION) #define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL) +#define SBUF_ISDRAINTOEOR(s) ((s)->s_flags & SBUF_DRAINTOEOR) +#define SBUF_DODRAINTOEOR(s) (SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s)) /* * Set / clear flags @@ -310,6 +312,7 @@ sbuf_clear(struct sbuf *s) SBUF_CLEARFLAG(s, SBUF_FINISHED); s->s_error = 0; s->s_len = 0; + s->s_rec_off = 0; s->s_sect_len = 0; } @@ -364,14 +367,18 @@ sbuf_drain(struct sbuf *s) KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); - len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len); - if (len < 0) { - s->s_error = -len; + if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0) + return (s->s_error = EDEADLK); + len = s->s_drain_func(s->s_drain_arg, s->s_buf, + SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len); + if (len <= 0) { + s->s_error = len ? -len : EDEADLK; return (s->s_error); } KASSERT(len > 0 && len <= s->s_len, ("Bad drain amount %d for sbuf %p", len, s)); s->s_len -= len; + s->s_rec_off -= len; /* * Fast path for the expected case where all the data was * drained. @@ -635,9 +642,9 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) break; /* Cannot print with the current available space. */ if (s->s_drain_func != NULL && s->s_len > 0) - error = sbuf_drain(s); - else - error = sbuf_extend(s, len - SBUF_FREESPACE(s)); + error = sbuf_drain(s); /* sbuf_drain() sets s_error. */ + else if (sbuf_extend(s, len - SBUF_FREESPACE(s)) != 0) + s->s_error = error = ENOMEM; } while (error == 0); /* @@ -654,8 +661,6 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) s->s_len += len; if (SBUF_ISSECTION(s)) s->s_sect_len += len; - if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s)) - s->s_error = ENOMEM; KASSERT(s->s_len < s->s_size, ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); @@ -837,6 +842,7 @@ sbuf_start_section(struct sbuf *s, ssize_t *old_lenp) ("s_sect_len != 0 when starting a section")); if (old_lenp != NULL) *old_lenp = -1; + s->s_rec_off = s->s_len; SBUF_SETFLAG(s, SBUF_INSECTION); } else { KASSERT(old_lenp != NULL, @@ -867,7 +873,7 @@ sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c) } len = s->s_sect_len; if (old_len == -1) { - s->s_sect_len = 0; + s->s_rec_off = s->s_sect_len = 0; SBUF_CLEARFLAG(s, SBUF_INSECTION); } else { s->s_sect_len += old_len; |