Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: kostja@tarantool.org
Subject: [tarantool-patches] [PATCH 1/1] core: introduce tt_static_sized_buf()
Date: Sat, 27 Apr 2019 00:44:42 +0300	[thread overview]
Message-ID: <687f8dc3342a3e9b6d8138837646837d60e63ed8.1556315009.git.v.shpilevoy@tarantool.org> (raw)

Currently Tarantool has a global thread local array of 4 static
buffers, each 1028 bytes. It provides an API tt_static_buf()
allowing to return them one by one in a cycle. But sometimes it
is needed to obtain a bit bigger buffer. For example, to store
a UDP packet - ~1.5Kb. Technically these 4 static buffers are an
array of ~4Kb and nothing prevents from allowing to take several
contiguous buffers at once to store 'big' data.

This commit introduces function tt_static_sized_buf() allowing
to take up to 1028 * 4 bytes at once. It rotates the buffer index
in the same way as tt_static_buf() does.

A main motivation for this commit is a wish to use a single
global out-of-stack buffer to read UDP packets into it in the
SWIM library, and on the other hand do not pad out BSS section
with a new SWIM-special static buffer. Now SWIM uses stack for
this and in the incoming cryptography SWIM component it will need
more.
---
Branch: https://github.com/tarantool/tarantool/tree/gerold103/tt_static_sized_buf

 src/trivia/util.h        | 33 +++++++++++++++-
 test/unit/CMakeLists.txt |  3 ++
 test/unit/misc.c         | 83 ++++++++++++++++++++++++++++++++++++++++
 test/unit/misc.result    | 28 ++++++++++++++
 4 files changed, 145 insertions(+), 2 deletions(-)
 create mode 100644 test/unit/misc.c
 create mode 100644 test/unit/misc.result

diff --git a/src/trivia/util.h b/src/trivia/util.h
index d17badff3..351e92c7b 100644
--- a/src/trivia/util.h
+++ b/src/trivia/util.h
@@ -490,8 +490,11 @@ extern __thread char tt_static_buf_storage[TT_STATIC_BUF_COUNT]
 extern __thread int tt_static_buf_i;
 
 /**
- * Return a thread-local statically allocated temporary buffer of size
- * \a TT_STATIC_BUF_LEN
+ * Return a thread-local statically allocated temporary buffer of
+ * size @a TT_STATIC_BUF_LEN. The buffers are rotated on each call
+ * of this function in a cycle. It allows to use multiple static
+ * buffers sequentially to store several different temporary data
+ * parts.
  */
 static inline char *
 tt_static_buf(void)
@@ -500,6 +503,32 @@ tt_static_buf(void)
 	return tt_static_buf_storage[tt_static_buf_i];
 }
 
+/**
+ * Return a thread-local statically allocated temporary buffer
+ * with at least @a size continuous bytes. @a size should not
+ * be bigger than total size of all tt static buffers. This call
+ * also rotates static buffer index with respect to the allocated
+ * block count.
+ */
+static inline char *
+tt_static_sized_buf(int size)
+{
+	assert(size <= TT_STATIC_BUF_COUNT * TT_STATIC_BUF_LEN);
+	if (size <= TT_STATIC_BUF_LEN)
+		return tt_static_buf();
+	int block_count = size / TT_STATIC_BUF_LEN +
+			  ((size % TT_STATIC_BUF_LEN) != 0);
+	assert(block_count <= TT_STATIC_BUF_COUNT);
+	int block_first = (tt_static_buf_i + 1) % TT_STATIC_BUF_COUNT;
+	int block_last = block_first + block_count - 1;
+	if (block_last < TT_STATIC_BUF_COUNT) {
+		tt_static_buf_i = block_last;
+		return tt_static_buf_storage[block_first];
+	}
+	tt_static_buf_i = block_count - 1;
+	return tt_static_buf_storage[0];
+}
+
 /**
  * Return a null-terminated string for \a str of length \a len
  */
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 368ceb649..9aa9364e6 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -216,6 +216,9 @@ target_link_libraries(sio.test unit core)
 add_executable(crypto.test crypto.c)
 target_link_libraries(crypto.test crypto unit)
 
+add_executable(misc.test misc.c)
+target_link_libraries(misc.test misc unit core)
+
 add_executable(swim.test swim.c swim_test_transport.c swim_test_ev.c
                swim_test_utils.c ${PROJECT_SOURCE_DIR}/src/version.c)
 target_link_libraries(swim.test unit swim)
diff --git a/test/unit/misc.c b/test/unit/misc.c
new file mode 100644
index 000000000..4d025c201
--- /dev/null
+++ b/test/unit/misc.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "trivia/util.h"
+#include "unit.h"
+
+static inline void
+check_static_sized_buf(int size, int first_pos, int last_pos)
+{
+	char *b = tt_static_sized_buf(size);
+	is(b, tt_static_buf_storage[first_pos], "allocated %d from %d",
+	   size, first_pos);
+	is(tt_static_buf_i, last_pos, "to %d", last_pos);
+}
+
+static void
+test_static_buffers(void)
+{
+	header();
+	plan(21);
+
+	check_static_sized_buf(10, 0, 0);
+	check_static_sized_buf(TT_STATIC_BUF_LEN, 1, 1);
+	check_static_sized_buf(TT_STATIC_BUF_LEN, 2, 2);
+	check_static_sized_buf(TT_STATIC_BUF_LEN + 1, 0, 1);
+
+	is(tt_static_buf(), tt_static_buf_storage[2],
+	   "not sized buf() takes 2");
+	check_static_sized_buf(10, 3, 3);
+
+	check_static_sized_buf(TT_STATIC_BUF_LEN * 2, 0, 1);
+	check_static_sized_buf(TT_STATIC_BUF_LEN * 2, 2, 3);
+	is(tt_static_buf(), tt_static_buf_storage[0],
+	   "sized_buf() and buf() use the same counter");
+	is(tt_static_buf_i, 0, "buf() occupied 0 after sized_buf() "\
+	   "had occupied 3");
+
+	check_static_sized_buf(TT_STATIC_BUF_LEN * TT_STATIC_BUF_COUNT, 0, 3);
+	check_static_sized_buf(0, 0, 0);
+
+	check_plan();
+	footer();
+}
+
+int
+main(void)
+{
+	header();
+	plan(1);
+
+	test_static_buffers();
+
+	int rc = check_plan();
+	footer();
+	return rc;
+}
diff --git a/test/unit/misc.result b/test/unit/misc.result
new file mode 100644
index 000000000..12341fdee
--- /dev/null
+++ b/test/unit/misc.result
@@ -0,0 +1,28 @@
+	*** main ***
+1..1
+	*** test_static_buffers ***
+    1..21
+    ok 1 - allocated 10 from 0
+    ok 2 - to 0
+    ok 3 - allocated 1028 from 1
+    ok 4 - to 1
+    ok 5 - allocated 1028 from 2
+    ok 6 - to 2
+    ok 7 - allocated 1029 from 0
+    ok 8 - to 1
+    ok 9 - not sized buf() takes 2
+    ok 10 - allocated 10 from 3
+    ok 11 - to 3
+    ok 12 - allocated 2056 from 0
+    ok 13 - to 1
+    ok 14 - allocated 2056 from 2
+    ok 15 - to 3
+    ok 16 - sized_buf() and buf() use the same counter
+    ok 17 - buf() occupied 0 after sized_buf() had occupied 3
+    ok 18 - allocated 4112 from 0
+    ok 19 - to 3
+    ok 20 - allocated 0 from 0
+    ok 21 - to 0
+ok 1 - subtests
+	*** test_static_buffers: done ***
+	*** main: done ***
-- 
2.20.1 (Apple Git-117)

             reply	other threads:[~2019-04-26 21:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-26 21:44 Vladislav Shpilevoy [this message]
2019-04-27 21:18 ` [tarantool-patches] " Konstantin Osipov
2019-04-28 16:56   ` Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=687f8dc3342a3e9b6d8138837646837d60e63ed8.1556315009.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH 1/1] core: introduce tt_static_sized_buf()' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox