From: Cyrill Gorcunov <gorcunov@gmail.com> To: tarantool-patches@freelists.org Cc: gorcunov@gmail.com, vdavydov.dev@gmail.com Subject: [rfc 3/4] core/fiber: Put static watermark into stack to track its usage Date: Sat, 02 Mar 2019 15:55:27 +0300 [thread overview] Message-ID: <20190302130034.050488016@gmail.com> (raw) In-Reply-To: <20190302125524.279852704@gmail.com> [-- Attachment #1: fiber-stack-wmark --] [-- Type: text/plain, Size: 4778 bytes --] We want to detect a situation where task in fiber is too eager for stack and close to its exhausting. For this sake upon stack creation we put 8 marks on last stack page with step of 128 bytes. Such params allows us to fill ~1/4 of a page, which does seem reasonable but we might change this params with time. Since the watermark position is permanent and some task is close to stack limit we print about the situation once to not spam a user much and stop putting the mark on recycling. Closes #3418 --- src/lib/core/fiber.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/core/fiber.h | 2 2 files changed, 107 insertions(+) Index: tarantool.git/src/lib/core/fiber.c =================================================================== --- tarantool.git.orig/src/lib/core/fiber.c +++ tarantool.git/src/lib/core/fiber.c @@ -104,6 +104,28 @@ static const struct fiber_attr fiber_att .flags = FIBER_DEFAULT_FLAGS }; +/* + * Random values generated with uuid. + * Try to fit a cache line. + */ +static const uint64_t poison_pool[] = { + 0x74f31d37285c4c37, 0xb10269a05bf10c29, + 0x0994d845bd284e0f, 0x9ffd4f7129c184df, + 0x357151e6711c4415, 0x8c5e5f41aafe6f28, + 0x6917dd79e78049d5, 0xba61957c65ca2465, +}; + +/* + * We poison by 8 bytes as it natural for stack + * step on x86-64. Also 128 byte gap between + * poison values should cover a common cases. + */ +#define POISON_SIZE (sizeof(poison_pool) / sizeof(poison_pool[0])) +#define POISON_GAP (128 + sizeof(poison_pool[0])) +#define POISON_OFF (POISON_GAP / sizeof(poison_pool[0])) + +static void fiber_wmark_recycle(struct fiber *fiber); + void fiber_attr_create(struct fiber_attr *fiber_attr) { @@ -624,6 +646,7 @@ fiber_recycle(struct fiber *fiber) /* no pending wakeup */ assert(rlist_empty(&fiber->state)); bool has_custom_stack = fiber->flags & FIBER_CUSTOM_STACK; + fiber_wmark_recycle(fiber); fiber_reset(fiber); fiber->name[0] = '\0'; fiber->f = NULL; @@ -710,6 +733,85 @@ page_align_up(void *ptr) return page_align_down(ptr + page_size - 1); } +static bool +stack_has_wmark(void *addr) +{ + const uint64_t *src = poison_pool; + const uint64_t *dst = addr; + size_t i; + + for (i = 0; i < POISON_SIZE; i++) { + if (*dst != src[i]) + return false; + dst += POISON_OFF; + } + + return true; +} + +static void +stack_put_wmark(void *addr) +{ + const uint64_t *src = poison_pool; + uint64_t *dst = addr; + size_t i; + + for (i = 0; i < POISON_SIZE; i++) { + *dst = src[i]; + dst += POISON_OFF; + } +} + +static void +fiber_wmark_recycle(struct fiber *fiber) +{ + static bool overflow_warned = false; + + if (fiber->stack == NULL || fiber->flags & FIBER_CUSTOM_STACK) + return; + + /* + * We are watching for stack overflow in one shot way: + * firstly to not spam a user with messages and secondly + * to relax system from additional operations while our + * watermark is not dynamic. + */ + if (overflow_warned) + return; + + if (!stack_has_wmark(fiber->stack_wmark_ofl)) { + if (!overflow_warned) { + say_warn("fiber %d is close to a stack limit", + fiber->name, fiber->fid); + overflow_warned = true; + } + } +} + +static void +fiber_wmark_init(struct fiber *fiber) +{ + /* + * No tracking on custom stacks + * in a sake of simplicity. + */ + if (fiber->flags & FIBER_CUSTOM_STACK) { + fiber->stack_wmark_ofl = NULL; + return; + } + + /* + * Initially we arm last page of a stack + * to catch if we're getting close to + * stack exhausting. + */ + if (stack_direction < 0) + fiber->stack_wmark_ofl = fiber->stack; + else + fiber->stack_wmark_ofl = fiber->stack + fiber->stack_size - page_size; + stack_put_wmark(fiber->stack_wmark_ofl); +} + static int fiber_stack_create(struct fiber *fiber, size_t stack_size) { @@ -757,6 +859,7 @@ fiber_stack_create(struct fiber *fiber, madvise(fiber->stack, fiber->stack_size, MADV_DONTNEED); #endif + fiber_wmark_init(fiber); mprotect(guard, page_size, PROT_NONE); return 0; } @@ -926,8 +1029,10 @@ cord_create(struct cord *cord, const cha /* Record stack extents */ tt_pthread_attr_getstack(cord->id, &cord->sched.stack, &cord->sched.stack_size); + cord->sched.stack_wmark_ofl = cord->sched.stack; #else cord->sched.stack = NULL; + cord->sched.stack_wmark_ofl = NULL; cord->sched.stack_size = 0; #endif } Index: tarantool.git/src/lib/core/fiber.h =================================================================== --- tarantool.git.orig/src/lib/core/fiber.h +++ tarantool.git/src/lib/core/fiber.h @@ -348,6 +348,8 @@ struct fiber { struct slab *stack_slab; /** Coro stack addr. */ void *stack; + /** Stack watermark addr for overflow detection. */ + void *stack_wmark_ofl; /** Coro stack size. */ size_t stack_size; /** Valgrind stack id. */
next prev parent reply other threads:[~2019-03-02 12:55 UTC|newest] Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-03-02 12:55 [rfc 0/4] fiber/stack: Increase stack size and shrink rss usage Cyrill Gorcunov 2019-03-02 12:55 ` [rfc 1/4] core/fiber: Increase default stack size Cyrill Gorcunov 2019-03-02 12:55 ` [rfc 2/4] core/fiber: Mark stack as unneeded on creation Cyrill Gorcunov 2019-03-02 12:55 ` Cyrill Gorcunov [this message] 2019-03-05 8:08 ` [tarantool-patches] [rfc 3/4] core/fiber: Put static watermark into stack to track its usage Konstantin Osipov 2019-03-05 8:17 ` Cyrill Gorcunov 2019-03-05 8:10 ` Konstantin Osipov 2019-03-05 8:14 ` Cyrill Gorcunov 2019-03-05 19:17 ` Cyrill Gorcunov 2019-03-05 8:20 ` Konstantin Osipov 2019-03-05 8:27 ` Cyrill Gorcunov 2019-03-02 12:55 ` [rfc 4/4] core/fiber: Shrink stack when recycling Cyrill Gorcunov 2019-03-05 8:30 ` [tarantool-patches] " Konstantin Osipov 2019-03-05 8:41 ` Cyrill Gorcunov 2019-03-05 9:32 ` [tarantool-patches] " Konstantin Osipov
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=20190302130034.050488016@gmail.com \ --to=gorcunov@gmail.com \ --cc=tarantool-patches@freelists.org \ --cc=vdavydov.dev@gmail.com \ --subject='Re: [rfc 3/4] core/fiber: Put static watermark into stack to track its usage' \ /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