From db18c71ada41cb978fa61a1b7fcd18e2aa9b217c Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Sat, 14 Apr 2018 00:24:58 -0700 Subject: [PATCH] Fix random Segfaults on Ubuntu arm (#17523) Fix random Segfaults on Ubuntu arm --- src/pal/src/thread/context.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/pal/src/thread/context.cpp b/src/pal/src/thread/context.cpp index 0707f4c..12672e8 100644 --- a/src/pal/src/thread/context.cpp +++ b/src/pal/src/thread/context.cpp @@ -26,6 +26,8 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do #include "pal/context.h" #include "pal/debug.h" #include "pal/thread.hpp" +#include "pal/utils.h" +#include "pal/virtual.h" #include #include @@ -1438,8 +1440,29 @@ DBG_FlushInstructionCache( IN LPCVOID lpBaseAddress, IN SIZE_T dwSize) { - // Intrinsic should do the right thing across all platforms +#ifndef _ARM_ + // Intrinsic should do the right thing across all platforms (except Linux arm) __builtin___clear_cache((char *)lpBaseAddress, (char *)((INT_PTR)lpBaseAddress + dwSize)); +#else // _ARM_ + // On Linux/arm (at least on 3.10) we found that there is a problem with __do_cache_op (arch/arm/kernel/traps.c) + // implementing cacheflush syscall. cacheflush flushes only the first page in range [lpBaseAddress, lpBaseAddress + dwSize) + // and leaves other pages in undefined state which causes random tests failures (often due to SIGSEGV) with no particular pattern. + // + // As a workaround, we call __builtin___clear_cache on each page separately. + + const SIZE_T pageSize = GetVirtualPageSize(); + INT_PTR begin = (INT_PTR)lpBaseAddress; + const INT_PTR end = begin + dwSize; + + while (begin < end) + { + INT_PTR endOrNextPageBegin = ALIGN_UP(begin + 1, pageSize); + if (endOrNextPageBegin > end) + endOrNextPageBegin = end; + __builtin___clear_cache((char *)begin, (char *)endOrNextPageBegin); + begin = endOrNextPageBegin; + } +#endif // _ARM_ return TRUE; } -- 2.7.4