diff options
author | Conrad Meyer <cem@FreeBSD.org> | 2019-05-07 17:47:20 +0000 |
---|---|---|
committer | Conrad Meyer <cem@FreeBSD.org> | 2019-05-07 17:47:20 +0000 |
commit | 7d7db5298d505495426c2f0790707757fd7c6acb (patch) | |
tree | 6168ea2d5cc5ae447ebe8c6c3fdd7fe381bb879a /lib | |
parent | 5350e15d0d85c3ffb021adab9304b7e4b1ab7f08 (diff) | |
download | src-7d7db5298d505495426c2f0790707757fd7c6acb.tar.gz src-7d7db5298d505495426c2f0790707757fd7c6acb.zip |
device_printf: Use sbuf for more coherent prints on SMP
device_printf does multiple calls to printf allowing other console messages to
be inserted between the device name, and the rest of the message. This change
uses sbuf to compose to two into a single buffer, and prints it all at once.
It exposes an sbuf drain function (drain-to-printf) for common use.
Update documentation to match; some unit tests included.
Submitted by: jmg
Sponsored by: Dell EMC Isilon
Differential Revision: https://reviews.freebsd.org/D16690
Notes
Notes:
svn path=/head/; revision=347229
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libsbuf/Symbol.map | 1 | ||||
-rw-r--r-- | lib/libsbuf/tests/sbuf_core_test.c | 61 | ||||
-rw-r--r-- | lib/libsbuf/tests/sbuf_stdio_test.c | 57 |
3 files changed, 119 insertions, 0 deletions
diff --git a/lib/libsbuf/Symbol.map b/lib/libsbuf/Symbol.map index 7bbc4bf9f8f1..44839d19456a 100644 --- a/lib/libsbuf/Symbol.map +++ b/lib/libsbuf/Symbol.map @@ -37,5 +37,6 @@ FBSD_1.4 { FBSD_1.5 { sbuf_putbuf; + sbuf_printf_drain; }; diff --git a/lib/libsbuf/tests/sbuf_core_test.c b/lib/libsbuf/tests/sbuf_core_test.c index 8ac4984e6804..13a27933c20d 100644 --- a/lib/libsbuf/tests/sbuf_core_test.c +++ b/lib/libsbuf/tests/sbuf_core_test.c @@ -63,6 +63,9 @@ ATF_TC_BODY(sbuf_clear_test, tc) */ child_proc = atf_utils_fork(); if (child_proc == 0) { + ATF_REQUIRE_EQ_MSG(0, sbuf_finish(sb), "sbuf_finish failed: %s", + strerror(errno)); + sbuf_putbuf(sb); exit(0); } @@ -100,6 +103,34 @@ ATF_TC_BODY(sbuf_done_and_sbuf_finish_test, tc) sbuf_delete(sb); } +static int +drain_ret0(void *arg, const char *data, int len) +{ + + (void)arg; + (void)data; + (void)len; + + return (0); +} + +ATF_TC_WITHOUT_HEAD(sbuf_drain_ret0_test); +ATF_TC_BODY(sbuf_drain_ret0_test, tc) +{ + struct sbuf *sb; + + sb = sbuf_new_auto(); + + sbuf_set_drain(sb, drain_ret0, NULL); + + sbuf_cat(sb, test_string); + + ATF_CHECK_EQ_MSG(-1, sbuf_finish(sb), + "required to return error when drain func returns 0"); + ATF_CHECK_EQ_MSG(EDEADLK, errno, + "errno required to be EDEADLK when drain func returns 0"); +} + ATF_TC_WITHOUT_HEAD(sbuf_len_test); ATF_TC_BODY(sbuf_len_test, tc) { @@ -131,6 +162,34 @@ ATF_TC_BODY(sbuf_len_test, tc) sbuf_delete(sb); } +ATF_TC_WITHOUT_HEAD(sbuf_new_fixedlen); +ATF_TC_BODY(sbuf_new_fixedlen, tc) +{ + char buf[strlen(test_string) + 1]; + struct sbuf sb; + pid_t child_proc; + + sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); + + sbuf_cat(&sb, test_string); + + child_proc = atf_utils_fork(); + if (child_proc == 0) { + ATF_REQUIRE_EQ_MSG(0, sbuf_finish(&sb), "sbuf_finish failed: %s", + strerror(errno)); + + sbuf_putbuf(&sb); + exit(0); + } + atf_utils_wait(child_proc, 0, test_string, ""); + + sbuf_putc(&sb, ' '); + + ATF_CHECK_EQ_MSG(-1, sbuf_finish(&sb), "failed to return error on overflow"); + + sbuf_delete(&sb); +} + ATF_TC_WITHOUT_HEAD(sbuf_setpos_test); ATF_TC_BODY(sbuf_setpos_test, tc) { @@ -190,7 +249,9 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, sbuf_clear_test); ATF_TP_ADD_TC(tp, sbuf_done_and_sbuf_finish_test); + ATF_TP_ADD_TC(tp, sbuf_drain_ret0_test); ATF_TP_ADD_TC(tp, sbuf_len_test); + ATF_TP_ADD_TC(tp, sbuf_new_fixedlen); #if 0 /* TODO */ #ifdef HAVE_SBUF_CLEAR_FLAGS diff --git a/lib/libsbuf/tests/sbuf_stdio_test.c b/lib/libsbuf/tests/sbuf_stdio_test.c index 681b870a3434..74928d9d09ea 100644 --- a/lib/libsbuf/tests/sbuf_stdio_test.c +++ b/lib/libsbuf/tests/sbuf_stdio_test.c @@ -59,6 +59,60 @@ sbuf_vprintf_helper(struct sbuf *sb, const char * restrict format, ...) return (rc); } +ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_null_test); +ATF_TC_BODY(sbuf_printf_drain_null_test, tc) +{ + struct sbuf *sb; + char buf[2]; + pid_t child_proc; + + sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN); + ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s", + strerror(errno)); + + child_proc = atf_utils_fork(); + if (child_proc == 0) { + sbuf_set_drain(sb, sbuf_printf_drain, NULL); + + ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string), + "sbuf_cat failed"); + + ATF_CHECK_EQ(0, sbuf_finish(sb)); + exit(0); + } + atf_utils_wait(child_proc, 0, test_string, ""); + + sbuf_delete(sb); +} + +ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_test); +ATF_TC_BODY(sbuf_printf_drain_test, tc) +{ + struct sbuf *sb; + char buf[2]; + pid_t child_proc; + size_t cnt = 0; + + sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN); + ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s", + strerror(errno)); + + child_proc = atf_utils_fork(); + if (child_proc == 0) { + sbuf_set_drain(sb, sbuf_printf_drain, &cnt); + + ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string), + "sbuf_cat failed"); + + ATF_CHECK_EQ(0, sbuf_finish(sb)); + ATF_CHECK_EQ(strlen(test_string), cnt); + exit(0); + } + atf_utils_wait(child_proc, 0, test_string, ""); + + sbuf_delete(sb); +} + ATF_TC_WITHOUT_HEAD(sbuf_printf_test); ATF_TC_BODY(sbuf_printf_test, tc) { @@ -106,6 +160,7 @@ ATF_TC_BODY(sbuf_putbuf_test, tc) child_proc = atf_utils_fork(); if (child_proc == 0) { + ATF_CHECK_EQ(0, sbuf_finish(sb)); sbuf_putbuf(sb); exit(0); } @@ -152,6 +207,8 @@ ATF_TC_BODY(sbuf_vprintf_test, tc) ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, sbuf_printf_drain_null_test); + ATF_TP_ADD_TC(tp, sbuf_printf_drain_test); ATF_TP_ADD_TC(tp, sbuf_printf_test); ATF_TP_ADD_TC(tp, sbuf_putbuf_test); ATF_TP_ADD_TC(tp, sbuf_vprintf_test); |