diff options
Diffstat (limited to 'indra/llcommon')
30 files changed, 595 insertions, 131 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index a504e71340..6c1e1ef64a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -8,7 +8,6 @@ include(bugsplat) include(Linking) include(Boost) include(LLSharedLibs) -include(Copy3rdPartyLibs) include(ZLIBNG) include(Tracy) @@ -157,6 +156,7 @@ set(llcommon_HEADER_FILES lleventdispatcher.h lleventfilter.h llevents.h + lleventtimer.h lleventemitter.h llexception.h llfasttimer.h @@ -181,6 +181,7 @@ set(llcommon_HEADER_FILES llliveappconfig.h lllivefile.h llmainthreadtask.h + llmake.h llmd5.h llmemory.h llmemorystream.h @@ -243,7 +244,9 @@ set(llcommon_HEADER_FILES llwin32headers.h llworkerthread.h hbxxh.h + is_approx_equal_fraction.h lockstatic.h + mutex.h stdtypes.h stringize.h threadpool.h @@ -282,7 +285,43 @@ target_link_libraries( target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(llcommon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(llcommon stage_third_party_libs) +if (CMAKE_OSX_ARCHITECTURES MATCHES arm64 OR CMAKE_SYSTEM_PROCESSOR MATCHES aarch64) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/sse2neon_installed OR NOT ${sse2neon_installed} EQUAL 0) + file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/include/sse2neon) + if (NOT EXISTS ${LIBS_PREBUILT_DIR}/include/sse2neon/sse2neon.h) + file(DOWNLOAD + https://raw.githubusercontent.com/DLTcollab/sse2neon/master/sse2neon.h + ${LIBS_PREBUILT_DIR}/include/sse2neon/sse2neon.h + ) + endif () + file(WRITE ${PREBUILD_TRACKING_DIR}/sse2neon_installed "0") + endif () + target_include_directories(llcommon PUBLIC ${LIBS_PREBUILT_DIR}/include/sse2neon) +endif () + +if (${LINUX_DISTRO} MATCHES debian OR (${LINUX_DISTRO} MATCHES ubuntu) OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed)) + target_include_directories(llcommon PUBLIC ${LIBS_PREBUILT_DIR}/include) +endif () + +if (NOT WINDOWS) + target_compile_options(${PROJECT_NAME} PUBLIC -Wno-deprecated-declarations) +endif () + +if (CMAKE_CXX_COMPILER_ID MATCHES GNU) + set_source_files_properties( + llapp.cpp + llsdutil.cpp + PROPERTIES COMPILE_FLAGS -Wno-stringop-truncation) + set_source_files_properties( + llevent.cpp + llfasttimer.cpp + PROPERTIES COMPILE_FLAGS -Wno-nonnull) +elseif (LINUX AND CMAKE_CXX_COMPILER_ID MATCHES Clang) + set_source_files_properties(llsys.cpp PROPERTIES + COMPILE_FLAGS -Wno-unused-but-set-variable) +endif () + +include(LibraryInstall) if (LL_TESTS) include(LLAddBuildTest) diff --git a/indra/llcommon/always_return.h b/indra/llcommon/always_return.h index a206471da5..b99eb49096 100644 --- a/indra/llcommon/always_return.h +++ b/indra/llcommon/always_return.h @@ -79,6 +79,22 @@ namespace LL DESIRED mDefault; }; + // specialize for AlwaysReturn<void> + template <> + struct AlwaysReturn<void> + { + public: + AlwaysReturn() {} + + // callable returns a type not convertible to DESIRED, return default + template <typename CALLABLE, typename... ARGS> + void operator()(CALLABLE&& callable, ARGS&&... args) + { + // discard whatever callable(args) returns + std::forward<CALLABLE>(callable)(std::forward<ARGS>(args)...); + } + }; + /** * always_return<T>(some_function, some_args...) calls * some_function(some_args...). It is guaranteed to return a value of type diff --git a/indra/llcommon/hbxxh.cpp b/indra/llcommon/hbxxh.cpp index 41d797a7e3..decf908bb6 100644 --- a/indra/llcommon/hbxxh.cpp +++ b/indra/llcommon/hbxxh.cpp @@ -34,7 +34,7 @@ // in your build, in which case the latter would be used instead. For ARM64 // builds, this would also automatically enable NEON vectorization. #define XXH_INLINE_ALL -#include "xxhash/xxhash.h" +#include <xxhash.h> #include "hbxxh.h" diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 01763c49aa..04aba817f8 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -230,7 +230,7 @@ bool LLVolatileAPRPool::isFull() bool _ll_apr_warn_status(apr_status_t status, const char* file, int line) { if(APR_SUCCESS == status) return false; -#if !LL_LINUX +#if !LL_LINUX && !__FreeBSD__ char buf[MAX_STRING]; /* Flawfinder: ignore */ apr_strerror(status, buf, sizeof(buf)); LL_WARNS("APR") << "APR: " << file << ":" << line << " " << buf << LL_ENDL; diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 693cd7c01f..13597d56a4 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -42,6 +42,7 @@ #include "llstring.h" #include "mutex.h" +#include <memory> struct apr_dso_handle_t; /** diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index c09cf7abd2..9672a3262b 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -29,6 +29,7 @@ #include "llassettype.h" #include "lldictionary.h" #include "llmemory.h" +#include "llsd.h" #include "llsingleton.h" ///---------------------------------------------------------------------------- @@ -246,3 +247,19 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) } return false; } + +LLSD LLAssetType::getTypeNames() +{ + LLSD type_names; + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (S32 type = AT_TEXTURE; type < AT_COUNT; ++type) + { + const AssetEntry *entry = dict->lookup((LLAssetType::EType) type); + // skip llassettype_bad_lookup + if (entry) + { + type_names.append(entry->mTypeName); + } + } + return type_names; +} diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 547c3f4329..17177d81c3 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -165,6 +165,8 @@ public: static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer + static LLSD getTypeNames(); + static const std::string BADLOOKUP; protected: diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp index c0154a569f..107fdc2b2d 100644 --- a/indra/llcommon/llexception.cpp +++ b/indra/llcommon/llexception.cpp @@ -15,7 +15,12 @@ #include "llexception.h" // STL headers // std headers +#include <iomanip> +#include <sstream> #include <typeinfo> +#if LL_WINDOWS +#include <excpt.h> +#endif // LL_WINDOWS // external library headers #include <boost/exception/diagnostic_information.hpp> #include <boost/exception/error_info.hpp> @@ -29,7 +34,6 @@ // On Windows, header-only implementation causes macro collisions -- use // prebuilt library #define BOOST_STACKTRACE_LINK -#include <excpt.h> #endif // LL_WINDOWS #include <boost/stacktrace.hpp> @@ -94,25 +98,47 @@ void annotate_exception_(boost::exception& exc) // For windows SEH exception handling we sometimes need a filter that will // separate C++ exceptions from C SEH exceptions -static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific +static constexpr U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific +static constexpr U32 STATUS_STACK_FULL = 0xC00000FD; -U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +void LL::seh::fill_stacktrace(std::string& stacktrace, U32 code) { - const auto stack = to_string(boost::stacktrace::stacktrace()); - LL_WARNS() << "SEH Exception handled (that probably shouldn't be): Code " << code - << "\n Stack trace: \n" - << stack << LL_ENDL; + // Sadly, despite its diagnostic importance, trying to capture a + // stacktrace when the stack is already blown only terminates us faster. + if (code == STATUS_STACK_FULL) + { + stacktrace = "(stack overflow, no traceback)"; + } + else + { + stacktrace = to_string(boost::stacktrace::stacktrace()); + } +} +U32 LL::seh::common_filter(U32 code, struct _EXCEPTION_POINTERS*) +{ if (code == STATUS_MSC_EXCEPTION) { - // C++ exception, go on + // C++ exception, don't stop at this handler return EXCEPTION_CONTINUE_SEARCH; } else { - // handle it + // This is a non-C++ exception, e.g. hardware check. + // Pass control into the handler block. return EXCEPTION_EXECUTE_HANDLER; } } +void LL::seh::rethrow(U32 code, const std::string& stacktrace) +{ + std::ostringstream out; + out << "Windows exception 0x" << std::hex << code; + if (! stacktrace.empty()) + { + out << '\n' << stacktrace; + } + LLTHROW(Windows_SEH_exception(out.str())); +} + #endif //LL_WINDOWS diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h index 68e609444e..f58a553eb3 100644 --- a/indra/llcommon/llexception.h +++ b/indra/llcommon/llexception.h @@ -12,6 +12,7 @@ #if ! defined(LL_LLEXCEPTION_H) #define LL_LLEXCEPTION_H +#include "always_return.h" #include <stdexcept> #include <boost/exception/exception.hpp> #include <boost/throw_exception.hpp> @@ -102,14 +103,115 @@ void crash_on_unhandled_exception_(const char*, int, const char*, const std::str log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT) void log_unhandled_exception_(const char*, int, const char*, const std::string&); +/***************************************************************************** +* Structured Exception Handling +*****************************************************************************/ +// this is used in platform-generic code -- define outside #if LL_WINDOWS +struct Windows_SEH_exception: public LLException +{ + Windows_SEH_exception(const std::string& what): LLException(what) {} +}; + +namespace LL +{ +namespace seh +{ + +#if LL_WINDOWS //------------------------------------------------------------- + +void fill_stacktrace(std::string& stacktrace, U32 code); + +// wrapper around caller's U32 filter(U32 code, struct _EXCEPTION_POINTERS*) +// filter function: capture a stacktrace, if possible, before forwarding the +// call to the caller's filter() function +template <typename FILTER> +U32 filter_(std::string& stacktrace, FILTER&& filter, + U32 code, struct _EXCEPTION_POINTERS* exptrs) +{ + // By the time the handler gets control, the stack has been unwound, + // so report the stack trace now at filter() time. + fill_stacktrace(stacktrace, code); + return std::forward<FILTER>(filter)(code, exptrs); +} + +template <typename TRYCODE, typename FILTER, typename HANDLER> +auto catcher_inner(std::string& stacktrace, + TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler) +{ + __try + { + return std::forward<TRYCODE>(trycode)(); + } + __except (filter_(stacktrace, + std::forward<FILTER>(filter), + GetExceptionCode(), GetExceptionInformation())) + { + return always_return<decltype(trycode())>( + std::forward<HANDLER>(handler), GetExceptionCode(), stacktrace); + } +} + +// triadic variant specifies try(), filter(U32, struct _EXCEPTION_POINTERS*), +// handler(U32, const std::string& stacktrace) +// stacktrace may or may not be available +template <typename TRYCODE, typename FILTER, typename HANDLER> +auto catcher(TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler) +{ + // Construct and destroy this stacktrace string in the outer function + // because we can't do either in the function with __try/__except. + std::string stacktrace; + return catcher_inner(stacktrace, + std::forward<TRYCODE>(trycode), + std::forward<FILTER>(filter), + std::forward<HANDLER>(handler)); +} -#if LL_WINDOWS +// common_filter() handles the typical case in which we want our handler +// clause to handle only Structured Exceptions rather than explicitly-thrown +// C++ exceptions +U32 common_filter(U32 code, struct _EXCEPTION_POINTERS*); + +// dyadic variant specifies try(), handler(U32, stacktrace), assumes common_filter() +template <typename TRYCODE, typename HANDLER> +auto catcher(TRYCODE&& trycode, HANDLER&& handler) +{ + return catcher(std::forward<TRYCODE>(trycode), + common_filter, + std::forward<HANDLER>(handler)); +} + +// monadic variant specifies try(), assumes default filter and handler +template <typename TRYCODE> +auto catcher(TRYCODE&& trycode) +{ + return catcher(std::forward<TRYCODE>(trycode), rethrow); +} + +[[noreturn]] void rethrow(U32 code, const std::string& stacktrace); + +#else // not LL_WINDOWS ----------------------------------------------------- + +template <typename TRYCODE, typename FILTER, typename HANDLER> +auto catcher(TRYCODE&& trycode, FILTER&&, HANDLER&&) +{ + return std::forward<TRYCODE>(trycode)(); +} + +template <typename TRYCODE, typename HANDLER> +auto catcher(TRYCODE&& trycode, HANDLER&&) +{ + return std::forward<TRYCODE>(trycode)(); +} + +template <typename TRYCODE> +auto catcher(TRYCODE&& trycode) +{ + return std::forward<TRYCODE>(trycode)(); +} -// SEH exception filtering for use in __try __except -// Separates C++ exceptions from C SEH exceptions -// Todo: might be good idea to do some kind of seh_to_msc_wrapper(function, ARGS&&); -U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop); +#endif // not LL_WINDOWS ----------------------------------------------------- -#endif //LL_WINDOWS +} // namespace LL::seh +} // namespace LL #endif /* ! defined(LL_LLEXCEPTION_H) */ diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 722743f453..7ceb57336e 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -43,7 +43,7 @@ #if LL_WINDOWS #include "lltimer.h" -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ #include <sys/time.h> #include <sched.h> #include "lltimer.h" diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 09fcf8a1af..a69a03e419 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -127,8 +127,22 @@ public: #endif +#if (LL_DARWIN && defined(__arm64__)) -#if (LL_LINUX) && !(defined(__i386__) || defined(__amd64__)) + static U32 getCPUClockCount64() + { + U64 t = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); + return t/1000; + } + + static U64 getCPUClockCount32() + { + return (U32) (getCPUClockCount64() >> 8); + } + +#endif + +#if (LL_LINUX && !(defined(__i386__) || defined(__amd64__))) // // Linux implementation of CPU clock - non-x86. // This is accurate but SLOW! Only use out of desperation. @@ -159,7 +173,7 @@ public: #endif // (LL_LINUX) && !(defined(__i386__) || defined(__amd64__)) -#if (LL_LINUX || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +#if (LL_LINUX || LL_DARWIN || __FreeBSD__) && (defined(__i386__) || defined(__amd64__)) // // Mac+Linux FAST x86 implementation of CPU clock static U32 getCPUClockCount32() diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index b616edfde7..d5802b9d95 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -52,7 +52,7 @@ class LLMutex ; #define LL_DEFAULT_HEAP_ALIGN 8 #elif LL_DARWIN #define LL_DEFAULT_HEAP_ALIGN 16 -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ #define LL_DEFAULT_HEAP_ALIGN 8 #endif @@ -71,7 +71,11 @@ LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); #define ll_assert_aligned(ptr,alignment) #endif +#if defined(__i386__) || defined(__x86_64__) || _M_X64 #include <xmmintrin.h> +#else +#include <sse2neon.h> +#endif template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address) { @@ -85,7 +89,7 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) (uintptr_t(address) + 0x3F) & ~0x3F); } -#if LL_LINUX || LL_DARWIN +#if LL_LINUX || LL_DARWIN || __FreeBSD__ #define LL_ALIGN_PREFIX(x) #define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x))) diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index b499a9ce10..e9f07f6fdf 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -32,9 +32,11 @@ #ifdef LL_LINUX #define __ENABLE_WSTRING #include <endian.h> +#elif defined(__FreeBSD__) +#include <sys/endian.h> #endif // LL_LINUX -#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__))) +#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(__FreeBSD__) && (_BYTE_ORDER == _LITTLE_ENDIAN))) #define LL_LITTLE_ENDIAN 1 #else #define LL_BIG_ENDIAN 1 @@ -77,7 +79,7 @@ #endif // Deal with minor differences on Unixy OSes. -#if LL_DARWIN || LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ // Different name, same functionality. #define stricmp strcasecmp #define strnicmp strncasecmp diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 912e596c3f..2800cc5608 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -176,13 +176,13 @@ public: // In general, our streambuf might contain a number of different // physical buffers; iterate over those. bool keepwriting = true; - for (const_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end()); + for (auto bufi = buffer_sequence_begin(bufs), bufend = buffer_sequence_end(bufs); bufi != bufend && keepwriting; ++bufi) { // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents // Although apr_file_write() accepts const void*, we // manipulate const char* so we can increment the pointer. - const char* remainptr = boost::asio::buffer_cast<const char*>(*bufi); + const char* remainptr = static_cast<const char*>((*bufi).data()); std::size_t remainlen = boost::asio::buffer_size(*bufi); while (remainlen) { @@ -377,14 +377,14 @@ public: // In general, the mutable_buffer_sequence returned by prepare() might // contain a number of different physical buffers; iterate over those. std::size_t tocommit(0); - for (mutable_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end()); + for (auto bufi = buffer_sequence_begin(bufs), bufend = buffer_sequence_end(bufs); bufi != bufend; ++bufi) { // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents std::size_t toread(boost::asio::buffer_size(*bufi)); apr_size_t gotten(toread); apr_status_t err = apr_file_read(mPipe, - boost::asio::buffer_cast<void*>(*bufi), + static_cast<void*>((*bufi).data()), &gotten); // EAGAIN is exactly what we want from a nonblocking pipe. // Rather than waiting for data, it should return immediately. @@ -691,10 +691,22 @@ LLProcess::LLProcess(const LLSDOrParams& params): // terminate with a null pointer argv.push_back(NULL); + // create an env vector for the child process + std::vector<const char*> envv; + + // Add environment value assignments. See above remarks about c_str(). + for (const std::string& env : params.envs) + { + envv.push_back(env.c_str()); + } + + // terminate with a null pointer + envv.push_back(NULL); + // Launch! The NULL would be the environment block, if we were passing // one. Hand-expand chkapr() macro so we can fill in the actual command // string instead of the variable names. - if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr, + if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], &envv[0], procattr, mPool))) { LLTHROW(LLProcessError(STRINGIZE(params << " failed"))); diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index cc2d6566fc..52b5e0f562 100644 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -38,7 +38,7 @@ #if LL_WINDOWS #include "llwin32headers.h" // for HANDLE -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ #if defined(Status) #undef Status #endif @@ -163,6 +163,7 @@ public: Params(): executable("executable"), args("args"), + envs("envs"), cwd("cwd"), autokill("autokill", true), attached("attached", true), @@ -180,6 +181,10 @@ public: * argument while assembling the command line. */ Multiple<std::string> args; + /** + * zero or more additional command-line environment values. + */ + Multiple<std::string> envs; /// current working directory, if need it changed Optional<std::string> cwd; /// implicitly kill child process on termination of parent, whether diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 2e94651083..56fd0fa7b3 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -751,12 +751,14 @@ private: : "0" (level)) #endif +#if __i386__ || __x86_64__ unsigned int eax, ebx, ecx, edx; __cpuid(0x1, eax, ebx, ecx, edx); if(feature_infos[0] != (S32)edx) { LL_WARNS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL; } +#endif // __i386__ || __x86_64__ #endif // LL_RELEASE_FOR_DOWNLOAD @@ -801,20 +803,150 @@ private: } }; +#elif __FreeBSD__ + +#include <sys/sysctl.h> +class LLProcessorInfoFreeBSDImpl : public LLProcessorInfoImpl +{ +public: + LLProcessorInfoFreeBSDImpl() + { + size_t len = 0; + using std::string; + + char cpu_brand_string[0x40]; + len = sizeof cpu_brand_string; + memset(cpu_brand_string, '\0', len); + sysctlbyname("hw.model", (void *)cpu_brand_string, &len, + NULL, 0); + cpu_brand_string[0x3f] = '\0'; + setInfo(eBrandName, cpu_brand_string); + + uint64_t cpu_frequency = 0; + len = sizeof cpu_frequency; + sysctlbyname("hw.clockrate", (void *)&cpu_frequency, &len, + NULL, 0); + setInfo(eFrequency, (F64)cpu_frequency); + + auto dmesgboot = LLFile::fopen("/var/run/dmesg.boot", "rb"); + std::ostringstream s; + if (dmesgboot) { + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while (fgets(line, MAX_STRING, dmesgboot)) { + line[strlen(line) - 1] = ' '; + s << line; + s << std::endl; + } + fclose(dmesgboot); + s << std::endl; + } + + auto dmesgboot_str = s.str(); + int decimal; + + auto idx1 = dmesgboot_str.find_first_of("\"") + 1; + auto idx2 = (idx1 != string::npos) + ? dmesgboot_str.find_first_of("\"", idx1) + : string::npos; + auto vendor = dmesgboot_str.substr(idx1, idx2 - idx1); + if (vendor.length() > 0) setInfo(eVendor, vendor.c_str()); + + idx1 = dmesgboot_str.find_first_of("=", idx2); + idx1 = dmesgboot_str.find_first_of("=", idx1 + 1) + 3; + idx2 = dmesgboot_str.find_first_of(" ", idx1); + auto family = dmesgboot_str.substr(idx1, idx2 - idx1); + std::istringstream(family) >> std::hex >> decimal; + setInfo(eFamily, decimal); + setInfo(eFamilyName, compute_CPUFamilyName(vendor.c_str(), + decimal, 0)); + + idx1 = dmesgboot_str.find_first_of("=", idx2) + 3; + idx2 = dmesgboot_str.find_first_of(" ", idx1); + auto model = dmesgboot_str.substr(idx1, idx2 - idx1); + std::istringstream(model) >> std::hex >> decimal; + setInfo(eModel, decimal); + + idx1 = dmesgboot_str.find_first_of("=", idx2) + 1; + idx2 = dmesgboot_str.find_first_of("\n", idx1); + auto stepping = dmesgboot_str.substr(idx1, idx2 - idx1); + setInfo(eStepping, std::stoi(stepping)); + + if (dmesgboot_str.find(",SSE,") != string::npos) + setExtension(cpu_feature_names[eSSE_Ext]); + + if (dmesgboot_str.find(",SSE2,") != string::npos) + setExtension(cpu_feature_names[eSSE2_Ext]); + + if (dmesgboot_str.find("<SSE3,") != string::npos) + setExtension(cpu_feature_names[eSSE3_Features]); + + if (dmesgboot_str.find(",SSSE3,") != string::npos) + setExtension(cpu_feature_names[eSSE3S_Features]); + + if (dmesgboot_str.find(",SSE4.1,") != string::npos) + setExtension(cpu_feature_names[eSSE4_1_Features]); + + if (dmesgboot_str.find(",SSE4.2,") != string::npos) + setExtension(cpu_feature_names[eSSE4_2_Features]); + + if (dmesgboot_str.find(",SSE4A,") != string::npos) + setExtension(cpu_feature_names[eSSE4a_Features]); + } + + virtual ~LLProcessorInfoFreeBSDImpl() {} +}; + #elif LL_LINUX + +// *NOTE:Mani - eww, macros! srry. +#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \ + if (!cpuinfo[cpuinfo_id].empty()) \ + { setInfo(llpi_id, cpuinfo[cpuinfo_id]);} + +#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \ + {\ + S32 result; \ + if (!cpuinfo[cpuinfo_id].empty() \ + && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \ + { setInfo(llpi_id, result);} \ + } + const char CPUINFO_FILE[] = "/proc/cpuinfo"; -class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl -{ +class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl { public: - LLProcessorInfoLinuxImpl() - { + LLProcessorInfoLinuxImpl() { get_proc_cpuinfo(); } virtual ~LLProcessorInfoLinuxImpl() {} + private: + F64 getCPUMaxMHZ() + { + // Nicky: We just look into cpu0. In theory we could iterate over all cores + // "/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq" + // But those should not fluctuate that much? + std::ifstream fIn { "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" }; + + if( !fIn.is_open() ) + return 0.0; + + std::string strLine; + fIn >> strLine; + if( strLine.empty() ) + return 0.0l; + + F64 mhz {}; + if( !LLStringUtil::convertToF64(strLine, mhz ) ) + return 0.0; + + mhz = mhz / 1000.0; + return mhz; + } + void get_proc_cpuinfo() { std::map< std::string, std::string > cpuinfo; @@ -843,32 +975,25 @@ private: std::string llinename(linename); LLStringUtil::toLower(llinename); std::string lineval( spacespot + 1, nlspot ); - cpuinfo[ llinename ] = lineval; + cpuinfo[ llinename ] = lineval; } fclose(cpuinfo_fp); } -# if LL_X86 -// *NOTE:Mani - eww, macros! srry. -#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \ - if (!cpuinfo[cpuinfo_id].empty()) \ - { setInfo(llpi_id, cpuinfo[cpuinfo_id]);} - -#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \ - {\ - S32 result; \ - if (!cpuinfo[cpuinfo_id].empty() \ - && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \ - { setInfo(llpi_id, result);} \ + F64 mhzFromSys = getCPUMaxMHZ(); + F64 mhzFromProc {}; + if( !LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhzFromProc ) ) + mhzFromProc = 0.0; + if (mhzFromSys > 1.0 && mhzFromSys > mhzFromProc ) + { + setInfo( eFrequency, mhzFromSys ); } - - F64 mhz; - if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) - && 200.0 < mhz && mhz < 10000.0) + else if ( 200.0 < mhzFromProc && mhzFromProc < 10000.0) { - setInfo(eFrequency,(F64)(mhz)); + setInfo(eFrequency,(F64)(mhzFromProc)); } +# if LL_X86 LLPI_SET_INFO_STRING(eBrandName, "model name"); LLPI_SET_INFO_STRING(eVendor, "vendor_id"); @@ -876,7 +1001,7 @@ private: LLPI_SET_INFO_INT(eModel, "model"); - S32 family; + S32 family{}; if (!cpuinfo["cpu family"].empty() && LLStringUtil::convertToS32(cpuinfo["cpu family"], family)) { @@ -981,6 +1106,9 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) #elif LL_DARWIN static LLProcessorInfoDarwinImpl the_impl; mImpl = &the_impl; +#elif __FreeBSD__ + static LLProcessorInfoFreeBSDImpl the_impl; + mImpl = &the_impl; #else static LLProcessorInfoLinuxImpl the_impl; mImpl = &the_impl; diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 37af366a20..68a7bf0adf 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -37,7 +37,7 @@ #include <boost/iostreams/device/array.hpp> #include <boost/iostreams/stream.hpp> -#ifdef LL_USESYSTEMLIBS +#if 1 # include <zlib.h> #else # include "zlib-ng/zlib.h" // for davep's dirty little zip functions diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 6396caf8d5..ce416baa04 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -35,7 +35,7 @@ extern "C" { -#ifdef LL_USESYSTEMLIBS +#if 1 # include <expat.h> #else # include "expat/expat.h" diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index dbd89118c9..9fa27cee78 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -35,7 +35,7 @@ # include "llwin32headers.h" // for htonl #elif LL_LINUX # include <netinet/in.h> -#elif LL_DARWIN +#elif LL_DARWIN || __FreeBSD__ # include <arpa/inet.h> #endif @@ -160,7 +160,7 @@ LLSD ll_binary_from_string(const LLSD& sd) char* ll_print_sd(const LLSD& sd) { const U32 bufferSize = 10 * 1024; - static char buffer[bufferSize]; + static char buffer[bufferSize + 1]; std::ostringstream stream; //stream.rdbuf()->pubsetbuf(buffer, bufferSize); stream << LLSDOStreamer<LLSDXMLFormatter>(sd); @@ -182,7 +182,7 @@ char* ll_pretty_print_sd_ptr(const LLSD* sd) char* ll_pretty_print_sd(const LLSD& sd) { const U32 bufferSize = 100 * 1024; - static char buffer[bufferSize]; + static char buffer[bufferSize + 1]; std::ostringstream stream; //stream.rdbuf()->pubsetbuf(buffer, bufferSize); stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY); diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 38bbe19ddd..497c0ad3eb 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -553,6 +553,100 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter } // namespace llsd +/***************************************************************************** +* LLSDParam<std::vector<T>> +*****************************************************************************/ +// Given an LLSD array, return a const std::vector<T>&, where T is a type +// supported by LLSDParam. Bonus: if the LLSD value is actually a scalar, +// return a single-element vector containing the converted value. +template <typename T> +class LLSDParam<std::vector<T>>: public LLSDParamBase +{ +public: + LLSDParam(const LLSD& array) + { + // treat undefined "array" as empty vector + if (array.isDefined()) + { + // what if it's a scalar? + if (! array.isArray()) + { + v.push_back(LLSDParam<T>(array)); + } + else // really is an array + { + // reserve space for the array entries + v.reserve(array.size()); + for (const auto& item : llsd::inArray(array)) + { + v.push_back(LLSDParam<T>(item)); + } + } + } + } + + operator const std::vector<T>&() const { return v; } + +private: + std::vector<T> v; +}; + + +/***************************************************************************** + * toArray(), toMap() + *****************************************************************************/ +namespace llsd +{ + +// For some T convertible to LLSD, given std::vector<T> myVec, +// toArray(myVec) returns an LLSD array whose entries correspond to the +// items in myVec. +// For some U convertible to LLSD, given function U xform(const T&), +// toArray(myVec, xform) returns an LLSD array whose every entry is +// xform(item) of the corresponding item in myVec. +// toArray() actually works with any container<C> usable with range +// 'for', not just std::vector. +// (Once we get C++20 we can use std::identity instead of this default lambda.) +template<typename C, typename FUNC> +LLSD toArray(const C& container, FUNC&& func = [](const auto& arg) { return arg; }) +{ + LLSD array; + for (const auto& item : container) + { + array.append(std::forward<FUNC>(func)(item)); + } + return array; +} + +// For some T convertible to LLSD, given std::map<std::string, T> myMap, +// toMap(myMap) returns an LLSD map whose entries correspond to the +// (key, value) pairs in myMap. +// For some U convertible to LLSD, given function +// std::pair<std::string, U> xform(const std::pair<std::string, T>&), +// toMap(myMap, xform) returns an LLSD map whose every entry is +// xform(pair) of the corresponding (key, value) pair in myMap. +// toMap() actually works with any container usable with range 'for', not +// just std::map. It need not even be an associative container, as long as +// you pass an xform function that returns std::pair<std::string, U>. +// (Once we get C++20 we can use std::identity instead of this default lambda.) +template<typename C, typename FUNC> +LLSD toMap(const C& container, FUNC&& func = [](const auto& arg) { return arg; }) +{ + LLSD map; + for (const auto& pair : container) + { + const auto& [key, value] = std::forward<FUNC>(func)(pair); + map[key] = value; + } + return map; +} + +} // namespace llsd + +/***************************************************************************** + * boost::hash<LLSD> + *****************************************************************************/ + // Specialization for generating a hash value from an LLSD block. namespace boost { diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index db716b1431..7a8edc176d 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -53,6 +53,7 @@ class LLSD; #if LL_DARWIN || LL_LINUX // Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already) #include <cstring> +#include <memory> namespace std { diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 3f33ad61c5..5c35aeb476 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -33,7 +33,7 @@ #include "llsys.h" #include <iostream> -#ifdef LL_USESYSTEMLIBS +#if 1 # include <zlib.h> #else # include "zlib-ng/zlib.h" @@ -83,8 +83,13 @@ using namespace llsd; # include <sys/sysinfo.h> # include <stdexcept> const char MEMINFO_FILE[] = "/proc/meminfo"; +#ifdef __GNU__ # include <gnu/libc-version.h> #endif +#elif __FreeBSD__ +# include <sys/sysctl.h> +# include <sys/utsname.h> +#endif LLCPUInfo gSysCPU; LLMemoryInfo gSysMemory; @@ -340,6 +345,8 @@ LLOSInfo::LLOSInfo() : mOSString = mOSStringSimple; } +#ifdef __GNU__ + const char OS_VERSION_MATCH_EXPRESSION[] = "([0-9]+)\\.([0-9]+)(\\.([0-9]+))?"; boost::regex os_version_parse(OS_VERSION_MATCH_EXPRESSION); boost::smatch matched; @@ -403,6 +410,8 @@ LLOSInfo::LLOSInfo() : LL_WARNS("AppInit") << "glibc version '" << glibc_version << "' cannot be parsed to three numbers; using all zeros" << LL_ENDL; } +#endif // __GNU__ + #else struct utsname un; @@ -429,6 +438,13 @@ LLOSInfo::LLOSInfo() : if (simple.length() > 0) mOSStringSimple = simple; } + else if (ostype == "FreeBSD") + { + // Only care about major and minor FreeBSD versions, truncate at first '-' + std::string simple = mOSStringSimple.substr(0, mOSStringSimple.find_first_of("-", 0)); + if (simple.length() > 0) + mOSStringSimple = simple; + } } else { @@ -504,57 +520,46 @@ const S32 LLOSInfo::getOSBitness() const return mOSBitness; } -//static -U32 LLOSInfo::getProcessVirtualSizeKB() -{ - U32 virtual_size = 0; -#if LL_LINUX -# define STATUS_SIZE 2048 - LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); - if (status_filep) - { - S32 numRead = 0; - char buff[STATUS_SIZE]; /* Flawfinder: ignore */ +namespace { - size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep); - buff[nbytes] = '\0'; + U32 readFromProcStat( std::string entryName ) + { + U32 val{}; +#if LL_LINUX + constexpr U32 STATUS_SIZE = 2048; - // All these guys return numbers in KB - char *memp = strstr(buff, "VmSize:"); - if (memp) + LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); + if (status_filep) { - numRead += sscanf(memp, "%*s %u", &virtual_size); + char buff[STATUS_SIZE]; /* Flawfinder: ignore */ + + size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep); + buff[nbytes] = '\0'; + + // All these guys return numbers in KB + char *memp = strstr(buff, entryName.c_str()); + if (memp) + { + (void) sscanf(memp, "%*s %u", &val); + } + fclose(status_filep); } - fclose(status_filep); - } #endif - return virtual_size; + return val; + } + } //static -U32 LLOSInfo::getProcessResidentSizeKB() +U32 LLOSInfo::getProcessVirtualSizeKB() { - U32 resident_size = 0; -#if LL_LINUX - LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); - if (status_filep != NULL) - { - S32 numRead = 0; - char buff[STATUS_SIZE]; /* Flawfinder: ignore */ - - size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep); - buff[nbytes] = '\0'; + return readFromProcStat( "VmSize:" ); +} - // All these guys return numbers in KB - char *memp = strstr(buff, "VmRSS:"); - if (memp) - { - numRead += sscanf(memp, "%*s %u", &resident_size); - } - fclose(status_filep); - } -#endif - return resident_size; +//static +U32 LLOSInfo::getProcessResidentSizeKB() +{ + return readFromProcStat( "VmRSS:" ); } //static @@ -765,13 +770,17 @@ static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB) } #endif -#if LL_DARWIN +#if LL_DARWIN || __FreeBSD__ // static U32Kilobytes LLMemoryInfo::getHardwareMemSize() { // This might work on Linux as well. Someone check... uint64_t phys = 0; +#if LL_DARWIN int mib[2] = { CTL_HW, HW_MEMSIZE }; +#else + int mib[2] = { CTL_HW, HW_PHYSMEM }; +#endif size_t len = sizeof(phys); sysctl(mib, 2, &phys, &len, NULL, 0); @@ -785,7 +794,7 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const #if LL_WINDOWS return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger())); -#elif LL_DARWIN +#elif LL_DARWIN || __FreeBSD__ return getHardwareMemSize(); #elif LL_LINUX diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 827b0dc048..c8ff4dd98a 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -130,7 +130,7 @@ public: void stream(std::ostream& s) const; ///< output text info to s U32Kilobytes getPhysicalMemoryKB() const; -#if LL_DARWIN +#if LL_DARWIN || __FreeBSD__ static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib. #endif diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 034e3f7897..85fcbbacac 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -452,7 +452,11 @@ ElementT LLThreadSafeQueue<ElementT, QueueT>::pop(void) // so we can finish draining the queue. pop_result popped = pop_(lock1, value); if (popped == POPPED) +#if LL_LINUX + return value; +#else return std::move(value); +#endif // Once the queue is DONE, there will never be any more coming. if (popped == DONE) diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index f36d223100..4e15ae29a9 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -35,7 +35,7 @@ #if LL_WINDOWS # include "llwin32headers.h" -#elif LL_LINUX || LL_DARWIN +#elif LL_LINUX || LL_DARWIN || __FreeBSD__ # include <errno.h> # include <sys/time.h> #else @@ -115,7 +115,7 @@ void ms_sleep(U32 ms) #endif -#elif LL_LINUX || LL_DARWIN +#elif LL_LINUX || LL_DARWIN || __FreeBSD__ static void _sleep_loop(struct timespec& thiswait) { struct timespec nextwait; @@ -233,7 +233,7 @@ F64 calc_clock_frequency() #endif // LL_WINDOWS -#if LL_LINUX || LL_DARWIN +#if LL_LINUX || LL_DARWIN || __FreeBSD__ // Both Linux and Mac use gettimeofday for accurate time F64 calc_clock_frequency() { diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index b9bd27aa17..3fbc45baaf 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -174,14 +174,6 @@ void LLUUID::toString(std::string& out) const (U8)(mData[15])); } -// *TODO: deprecate -void LLUUID::toString(char* out) const -{ - std::string buffer; - toString(buffer); - strcpy(out, buffer.c_str()); /* Flawfinder: ignore */ -} - void LLUUID::toCompressedString(std::string& out) const { char bytes[UUID_BYTES + 1]; @@ -190,13 +182,6 @@ void LLUUID::toCompressedString(std::string& out) const out.assign(bytes, UUID_BYTES); } -// *TODO: deprecate -void LLUUID::toCompressedString(char* out) const -{ - memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */ - out[UUID_BYTES] = '\0'; -} - std::string LLUUID::getString() const { return asString(); @@ -520,7 +505,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id) #include <net/if.h> #include <net/if_types.h> #include <net/if_dl.h> -#include <net/route.h> +//#include <net/route.h> #include <ifaddrs.h> // static @@ -604,7 +589,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id) #define HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> -#if !LL_DARWIN +#if !LL_DARWIN && !__FreeBSD__ #include <linux/sockios.h> #endif #endif diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index bd4edc7993..ca1cf03c4d 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -103,9 +103,7 @@ public: friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid); friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid); - void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0) void toString(std::string& out) const; - void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0) void toCompressedString(std::string& out) const; std::string asString() const; diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index f1e4c2bc78..78d5e50e4b 100644 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h @@ -29,6 +29,7 @@ #include <cassert> #include <cfloat> #include <climits> +#include <cstddef> #include <limits> #include <type_traits> @@ -71,7 +72,7 @@ typedef unsigned __int64 U64; #else typedef long long int S64; typedef long long unsigned int U64; -#if LL_DARWIN || LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ #define S64L(a) (a##LL) #define U64L(a) (a##ULL) #endif @@ -113,6 +114,10 @@ typedef U32 TPACKETID; #define FALSE (0) #endif +#if __FreeBSD__ +#undef NULL +#endif + #ifndef NULL #define NULL (0) #endif diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index fa48bcdefd..3fb25b4cef 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -35,7 +35,7 @@ // causes Windows abdominal pain such that it later fails code-signing in some // mysterious way. Entirely suppressing these LLLeap tests pushes the failure // rate MUCH lower. Can we re-enable them with a smaller data size on Windows? -const size_t BUFFERED_LENGTH = 100*1024; +const size_t BUFFERED_LENGTH = 1023*1024; #else // not Windows const size_t BUFFERED_LENGTH = 1023*1024; // try wrangling just under a megabyte of data diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index b18712b8e9..b68c63a15f 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -377,7 +377,7 @@ namespace tut { F32 value; std::string str_val("2147483647"); //0x7FFFFFFF - ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647); + ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647.f); str_val = "0"; ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0); @@ -399,7 +399,7 @@ namespace tut { F64 value; std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF - ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL); + ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807.); str_val = "0"; ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F); |