diff options
Diffstat (limited to 'indra/llcommon')
27 files changed, 386 insertions, 100 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index a504e71340..e8c51c4c8e 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,45 @@ 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) +elseif ($ENV{MSYSTEM_CARCH} MATCHES aarch64) +  target_include_directories(llcommon PUBLIC ${prefix_result}/../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/StackWalker.cpp b/indra/llcommon/StackWalker.cpp index e9ae1723fb..027df80df5 100644 --- a/indra/llcommon/StackWalker.cpp +++ b/indra/llcommon/StackWalker.cpp @@ -1100,6 +1100,14 @@ bool StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *con    s.AddrBStore.Mode = AddrModeFlat;    s.AddrStack.Offset = c.IntSp;    s.AddrStack.Mode = AddrModeFlat; +#elif _M_ARM64 +  imageType = IMAGE_FILE_MACHINE_ARM64; +  s.AddrPC.Offset = c.Pc; +  s.AddrPC.Mode = AddrModeFlat; +  s.AddrFrame.Offset = c.Fp; +  s.AddrFrame.Mode = AddrModeFlat; +  s.AddrStack.Offset = c.Sp; +  s.AddrStack.Mode = AddrModeFlat;  #else  #error "Platform not supported!"  #endif 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/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..8499655bfa 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -99,7 +99,11 @@ public:  #if LL_FASTTIMER_USE_RDTSC      static U32 getCPUClockCount32()      { +#if _M_ARM64 +        unsigned __int64 val = _ReadStatusReg(ARM64_PMCCNTR_EL0); +#else          unsigned __int64 val = __rdtsc(); +#endif          val = val >> 8;          return static_cast<U32>(val);      } @@ -107,7 +111,11 @@ public:      // return full timer value, *not* shifted by 8 bits      static U64 getCPUClockCount64()      { +#if _M_ARM64 +        return static_cast<U64>( _ReadStatusReg(ARM64_PMCCNTR_EL0) ); +#else          return static_cast<U64>( __rdtsc() ); +#endif      }  #else @@ -127,8 +135,22 @@ public:  #endif +#if (LL_DARWIN && defined(__arm64__)) + +    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__)) +#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 +181,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..268109e8b7 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 @@ -167,7 +169,11 @@  #define LL_TO_STRING_HELPER(x) #x  #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x) +#if _M_ARM64 +#define LL_TO_WSTRING_HELPER(x) L## #x +#else  #define LL_TO_WSTRING_HELPER(x) L#x +#endif  #define LL_TO_WSTRING(x) LL_TO_WSTRING_HELPER(x)  #define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg  #define LL_GLUE_IMPL(x, y) x##y 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..7f2276ca2a 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -439,13 +439,21 @@ static F64 calculate_cpu_frequency(U32 measure_msecs)      //// completed now (serialization)      //__asm cpuid      int cpu_info[4] = {-1}; +#if _M_ARM64 +    std::fill(cpu_info, cpu_info + 4, 0); +#else      __cpuid(cpu_info, 0); +#endif      // We ask the high-res timer for the start time      QueryPerformanceCounter((LARGE_INTEGER *) &starttime);      // Then we get the current cpu clock and store it +#if _M_ARM64 +    start = _ReadStatusReg(ARM64_PMCCNTR_EL0); +#else      start = __rdtsc(); +#endif      // Now we wart for some msecs      _Delay(measure_msecs); @@ -455,7 +463,11 @@ static F64 calculate_cpu_frequency(U32 measure_msecs)      QueryPerformanceCounter((LARGE_INTEGER *) &endtime);      // And also for the end cpu clock +#if _M_ARM64 +    end = _ReadStatusReg(ARM64_PMCCNTR_EL0); +#else      end = __rdtsc(); +#endif      // Now we can restore the default process and thread priorities      SetProcessAffinityMask(hProcess, dwProcessMask); @@ -495,17 +507,21 @@ private:          // the other three array elements. The CPU identification string is          // not in linear order. The code below arranges the information          // in a human readable form. +#if !_M_ARM64          int cpu_info[4] = {-1};          __cpuid(cpu_info, 0);          unsigned int ids = (unsigned int)cpu_info[0];          setConfig(eMaxID, (S32)ids); +#endif          char cpu_vendor[0x20];          memset(cpu_vendor, 0, sizeof(cpu_vendor)); +#if !_M_ARM64          *((int*)cpu_vendor) = cpu_info[1];          *((int*)(cpu_vendor+4)) = cpu_info[3];          *((int*)(cpu_vendor+8)) = cpu_info[2];          setInfo(eVendor, cpu_vendor); +#endif          std::string cmp_vendor(cpu_vendor);          bool is_amd = false;          if (cmp_vendor == "AuthenticAMD") @@ -513,6 +529,20 @@ private:              is_amd = true;          } +#if _M_ARM64 +        HKEY hKey; +        DWORD gotType; +        char inBuffer[48] = ""; +        if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey) == ERROR_SUCCESS) +        { +            if (!RegQueryValueExA(hKey, "ProcessorNameString", nullptr, &gotType, (PBYTE)(inBuffer), nullptr)) +            { +                if ((gotType == REG_SZ) && strlen(inBuffer)) +                    setInfo(eModel, inBuffer); +            } +            RegCloseKey(hKey); +        } +#else          // Get the information associated with each valid Id          for(unsigned int i=0; i<=ids; ++i)          { @@ -623,6 +653,7 @@ private:                  setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff);              }          } +#endif      }  }; @@ -751,12 +782,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 +834,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 +1006,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 +1032,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 +1137,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/llsdjson.cpp b/indra/llcommon/llsdjson.cpp index 655869a704..a4b45ed80d 100644 --- a/indra/llcommon/llsdjson.cpp +++ b/indra/llcommon/llsdjson.cpp @@ -35,7 +35,11 @@  #include "llerror.h"  #include "../llmath/llmath.h" +#if LL_WINDOWS +#include <boost/json.hpp> +#else  #include <boost/json/src.hpp> +#endif  //=========================================================================  LLSD LlsdFromJson(const boost::json::value& val) 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/llstring.cpp b/indra/llcommon/llstring.cpp index 07adf71d18..bb6d091a97 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -260,7 +260,7 @@ S32 utf16str_wstring_length(const llutf16string &utf16str, const S32 utf16_len)  {      S32 surrogate_pairs = 0;      // ... craziness to make gcc happy (llutf16string.c_str() is tweaked on linux): -    const U16 *const utf16_chars = &(*(utf16str.begin())); +    const auto *const utf16_chars = &(*(utf16str.begin()));      S32 i = 0;      while (i < utf16_len)      { diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index db716b1431..2e579a4d2d 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  { @@ -634,7 +635,11 @@ LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);  //  // This typedef may or may not be identical to std::wstring, depending on  // LL_WCHAR_T_NATIVE. +#if __FreeBSD__ +typedef std::basic_string<char16_t> llutf16string; +#else  typedef std::basic_string<U16> llutf16string; +#endif  // Considering wchar_t, llwchar and U16, there are three relevant cases:  #if LLWCHAR_IS_WCHAR_T         // every which way but Windows 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 4aae90626e..3fbc45baaf 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -505,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 @@ -589,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/llwin32headers.h b/indra/llcommon/llwin32headers.h index df433deb7a..32139821d5 100644 --- a/indra/llcommon/llwin32headers.h +++ b/indra/llcommon/llwin32headers.h @@ -29,6 +29,7 @@  #ifdef LL_WINDOWS  #include <windows.h> // Does not include winsock.h because WIN32_LEAN_AND_MEAN is defined +#include <ws2tcpip.h>  #include <winsock2.h> // Requires windows.h  #endif 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);  | 
