diff options
Diffstat (limited to 'indra/llcommon')
40 files changed, 818 insertions, 360 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/fsyspath.h b/indra/llcommon/fsyspath.h index 1b4aec09b4..e9c96edce3 100644 --- a/indra/llcommon/fsyspath.h +++ b/indra/llcommon/fsyspath.h @@ -68,7 +68,11 @@ public: } // shadow base-class string() method with UTF-8 aware method - std::string string() const { return super::u8string(); } + std::string string() const + { + auto u8 = super::u8string(); + return std::string(u8.begin(), u8.end()); + } // On Posix systems, where value_type is already char, this operator // std::string() method shadows the base class operator string_type() // method. But on Windows, where value_type is wchar_t, the base class 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/indra_constants.h b/indra/llcommon/indra_constants.h index d2de88ff0a..a0394da281 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -31,15 +31,15 @@ class LLUUID; -static const F32 REGION_WIDTH_METERS = 256.f; -static const S32 REGION_WIDTH_UNITS = 256; -static const U32 REGION_WIDTH_U32 = 256; +static constexpr F32 REGION_WIDTH_METERS = 256.f; +static constexpr S32 REGION_WIDTH_UNITS = 256; +static constexpr U32 REGION_WIDTH_U32 = 256; -const F32 REGION_HEIGHT_METERS = 4096.f; +constexpr F32 REGION_HEIGHT_METERS = 4096.f; -const F32 DEFAULT_AGENT_DEPTH = 0.45f; -const F32 DEFAULT_AGENT_WIDTH = 0.60f; -const F32 DEFAULT_AGENT_HEIGHT = 1.9f; +constexpr F32 DEFAULT_AGENT_DEPTH = 0.45f; +constexpr F32 DEFAULT_AGENT_WIDTH = 0.60f; +constexpr F32 DEFAULT_AGENT_HEIGHT = 1.9f; enum ETerrainBrushType { @@ -67,112 +67,112 @@ enum EMouseClickType{ // keys // Bit masks for various keyboard modifier keys. -const MASK MASK_NONE = 0x0000; -const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs -const MASK MASK_ALT = 0x0002; -const MASK MASK_SHIFT = 0x0004; -const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys -const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows -const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL; +constexpr MASK MASK_NONE = 0x0000; +constexpr MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs +constexpr MASK MASK_ALT = 0x0002; +constexpr MASK MASK_SHIFT = 0x0004; +constexpr MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys +constexpr MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows +constexpr MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL; // Special keys go into >128 -const KEY KEY_SPECIAL = 0x80; // special keys start here -const KEY KEY_RETURN = 0x81; -const KEY KEY_LEFT = 0x82; -const KEY KEY_RIGHT = 0x83; -const KEY KEY_UP = 0x84; -const KEY KEY_DOWN = 0x85; -const KEY KEY_ESCAPE = 0x86; -const KEY KEY_BACKSPACE =0x87; -const KEY KEY_DELETE = 0x88; -const KEY KEY_SHIFT = 0x89; -const KEY KEY_CONTROL = 0x8A; -const KEY KEY_ALT = 0x8B; -const KEY KEY_HOME = 0x8C; -const KEY KEY_END = 0x8D; -const KEY KEY_PAGE_UP = 0x8E; -const KEY KEY_PAGE_DOWN = 0x8F; -const KEY KEY_HYPHEN = 0x90; -const KEY KEY_EQUALS = 0x91; -const KEY KEY_INSERT = 0x92; -const KEY KEY_CAPSLOCK = 0x93; -const KEY KEY_TAB = 0x94; -const KEY KEY_ADD = 0x95; -const KEY KEY_SUBTRACT =0x96; -const KEY KEY_MULTIPLY =0x97; -const KEY KEY_DIVIDE = 0x98; -const KEY KEY_F1 = 0xA1; -const KEY KEY_F2 = 0xA2; -const KEY KEY_F3 = 0xA3; -const KEY KEY_F4 = 0xA4; -const KEY KEY_F5 = 0xA5; -const KEY KEY_F6 = 0xA6; -const KEY KEY_F7 = 0xA7; -const KEY KEY_F8 = 0xA8; -const KEY KEY_F9 = 0xA9; -const KEY KEY_F10 = 0xAA; -const KEY KEY_F11 = 0xAB; -const KEY KEY_F12 = 0xAC; - -const KEY KEY_PAD_UP = 0xC0; -const KEY KEY_PAD_DOWN = 0xC1; -const KEY KEY_PAD_LEFT = 0xC2; -const KEY KEY_PAD_RIGHT = 0xC3; -const KEY KEY_PAD_HOME = 0xC4; -const KEY KEY_PAD_END = 0xC5; -const KEY KEY_PAD_PGUP = 0xC6; -const KEY KEY_PAD_PGDN = 0xC7; -const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle -const KEY KEY_PAD_INS = 0xC9; -const KEY KEY_PAD_DEL = 0xCA; -const KEY KEY_PAD_RETURN = 0xCB; -const KEY KEY_PAD_ADD = 0xCC; // not used -const KEY KEY_PAD_SUBTRACT = 0xCD; // not used -const KEY KEY_PAD_MULTIPLY = 0xCE; // not used -const KEY KEY_PAD_DIVIDE = 0xCF; // not used - -const KEY KEY_BUTTON0 = 0xD0; -const KEY KEY_BUTTON1 = 0xD1; -const KEY KEY_BUTTON2 = 0xD2; -const KEY KEY_BUTTON3 = 0xD3; -const KEY KEY_BUTTON4 = 0xD4; -const KEY KEY_BUTTON5 = 0xD5; -const KEY KEY_BUTTON6 = 0xD6; -const KEY KEY_BUTTON7 = 0xD7; -const KEY KEY_BUTTON8 = 0xD8; -const KEY KEY_BUTTON9 = 0xD9; -const KEY KEY_BUTTON10 = 0xDA; -const KEY KEY_BUTTON11 = 0xDB; -const KEY KEY_BUTTON12 = 0xDC; -const KEY KEY_BUTTON13 = 0xDD; -const KEY KEY_BUTTON14 = 0xDE; -const KEY KEY_BUTTON15 = 0xDF; - -const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only. - -const S32 KEY_COUNT = 256; - - -const F32 DEFAULT_WATER_HEIGHT = 20.0f; +constexpr KEY KEY_SPECIAL = 0x80; // special keys start here +constexpr KEY KEY_RETURN = 0x81; +constexpr KEY KEY_LEFT = 0x82; +constexpr KEY KEY_RIGHT = 0x83; +constexpr KEY KEY_UP = 0x84; +constexpr KEY KEY_DOWN = 0x85; +constexpr KEY KEY_ESCAPE = 0x86; +constexpr KEY KEY_BACKSPACE =0x87; +constexpr KEY KEY_DELETE = 0x88; +constexpr KEY KEY_SHIFT = 0x89; +constexpr KEY KEY_CONTROL = 0x8A; +constexpr KEY KEY_ALT = 0x8B; +constexpr KEY KEY_HOME = 0x8C; +constexpr KEY KEY_END = 0x8D; +constexpr KEY KEY_PAGE_UP = 0x8E; +constexpr KEY KEY_PAGE_DOWN = 0x8F; +constexpr KEY KEY_HYPHEN = 0x90; +constexpr KEY KEY_EQUALS = 0x91; +constexpr KEY KEY_INSERT = 0x92; +constexpr KEY KEY_CAPSLOCK = 0x93; +constexpr KEY KEY_TAB = 0x94; +constexpr KEY KEY_ADD = 0x95; +constexpr KEY KEY_SUBTRACT =0x96; +constexpr KEY KEY_MULTIPLY =0x97; +constexpr KEY KEY_DIVIDE = 0x98; +constexpr KEY KEY_F1 = 0xA1; +constexpr KEY KEY_F2 = 0xA2; +constexpr KEY KEY_F3 = 0xA3; +constexpr KEY KEY_F4 = 0xA4; +constexpr KEY KEY_F5 = 0xA5; +constexpr KEY KEY_F6 = 0xA6; +constexpr KEY KEY_F7 = 0xA7; +constexpr KEY KEY_F8 = 0xA8; +constexpr KEY KEY_F9 = 0xA9; +constexpr KEY KEY_F10 = 0xAA; +constexpr KEY KEY_F11 = 0xAB; +constexpr KEY KEY_F12 = 0xAC; + +constexpr KEY KEY_PAD_UP = 0xC0; +constexpr KEY KEY_PAD_DOWN = 0xC1; +constexpr KEY KEY_PAD_LEFT = 0xC2; +constexpr KEY KEY_PAD_RIGHT = 0xC3; +constexpr KEY KEY_PAD_HOME = 0xC4; +constexpr KEY KEY_PAD_END = 0xC5; +constexpr KEY KEY_PAD_PGUP = 0xC6; +constexpr KEY KEY_PAD_PGDN = 0xC7; +constexpr KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle +constexpr KEY KEY_PAD_INS = 0xC9; +constexpr KEY KEY_PAD_DEL = 0xCA; +constexpr KEY KEY_PAD_RETURN = 0xCB; +constexpr KEY KEY_PAD_ADD = 0xCC; // not used +constexpr KEY KEY_PAD_SUBTRACT = 0xCD; // not used +constexpr KEY KEY_PAD_MULTIPLY = 0xCE; // not used +constexpr KEY KEY_PAD_DIVIDE = 0xCF; // not used + +constexpr KEY KEY_BUTTON0 = 0xD0; +constexpr KEY KEY_BUTTON1 = 0xD1; +constexpr KEY KEY_BUTTON2 = 0xD2; +constexpr KEY KEY_BUTTON3 = 0xD3; +constexpr KEY KEY_BUTTON4 = 0xD4; +constexpr KEY KEY_BUTTON5 = 0xD5; +constexpr KEY KEY_BUTTON6 = 0xD6; +constexpr KEY KEY_BUTTON7 = 0xD7; +constexpr KEY KEY_BUTTON8 = 0xD8; +constexpr KEY KEY_BUTTON9 = 0xD9; +constexpr KEY KEY_BUTTON10 = 0xDA; +constexpr KEY KEY_BUTTON11 = 0xDB; +constexpr KEY KEY_BUTTON12 = 0xDC; +constexpr KEY KEY_BUTTON13 = 0xDD; +constexpr KEY KEY_BUTTON14 = 0xDE; +constexpr KEY KEY_BUTTON15 = 0xDF; + +constexpr KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only. + +constexpr S32 KEY_COUNT = 256; + + +constexpr F32 DEFAULT_WATER_HEIGHT = 20.0f; // Maturity ratings for simulators -const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG -const U8 SIM_ACCESS_PG = 13; -const U8 SIM_ACCESS_MATURE = 21; -const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only -const U8 SIM_ACCESS_DOWN = 254; -const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; +constexpr U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG +constexpr U8 SIM_ACCESS_PG = 13; +constexpr U8 SIM_ACCESS_MATURE = 21; +constexpr U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only +constexpr U8 SIM_ACCESS_DOWN = 254; +constexpr U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; // attachment constants -const U8 ATTACHMENT_ADD = 0x80; +constexpr U8 ATTACHMENT_ADD = 0x80; // god levels -const U8 GOD_MAINTENANCE = 250; -const U8 GOD_FULL = 200; -const U8 GOD_LIAISON = 150; -const U8 GOD_CUSTOMER_SERVICE = 100; -const U8 GOD_LIKE = 1; -const U8 GOD_NOT = 0; +constexpr U8 GOD_MAINTENANCE = 250; +constexpr U8 GOD_FULL = 200; +constexpr U8 GOD_LIAISON = 150; +constexpr U8 GOD_CUSTOMER_SERVICE = 100; +constexpr U8 GOD_LIKE = 1; +constexpr U8 GOD_NOT = 0; // "agent id" for things that should be done to ALL agents LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS; @@ -239,121 +239,123 @@ LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL; LL_COMMON_API extern const LLUUID BLANK_MATERIAL_ASSET_ID; // radius within which a chat message is fully audible -const F32 CHAT_NORMAL_RADIUS = 20.f; +constexpr F32 CHAT_NORMAL_RADIUS = 20.f; // media commands -const U32 PARCEL_MEDIA_COMMAND_STOP = 0; -const U32 PARCEL_MEDIA_COMMAND_PAUSE = 1; -const U32 PARCEL_MEDIA_COMMAND_PLAY = 2; -const U32 PARCEL_MEDIA_COMMAND_LOOP = 3; -const U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4; -const U32 PARCEL_MEDIA_COMMAND_URL = 5; -const U32 PARCEL_MEDIA_COMMAND_TIME = 6; -const U32 PARCEL_MEDIA_COMMAND_AGENT = 7; -const U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8; -const U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; -const U32 PARCEL_MEDIA_COMMAND_TYPE = 10; -const U32 PARCEL_MEDIA_COMMAND_SIZE = 11; -const U32 PARCEL_MEDIA_COMMAND_DESC = 12; -const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13; +constexpr U32 PARCEL_MEDIA_COMMAND_STOP = 0; +constexpr U32 PARCEL_MEDIA_COMMAND_PAUSE = 1; +constexpr U32 PARCEL_MEDIA_COMMAND_PLAY = 2; +constexpr U32 PARCEL_MEDIA_COMMAND_LOOP = 3; +constexpr U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4; +constexpr U32 PARCEL_MEDIA_COMMAND_URL = 5; +constexpr U32 PARCEL_MEDIA_COMMAND_TIME = 6; +constexpr U32 PARCEL_MEDIA_COMMAND_AGENT = 7; +constexpr U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8; +constexpr U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; +constexpr U32 PARCEL_MEDIA_COMMAND_TYPE = 10; +constexpr U32 PARCEL_MEDIA_COMMAND_SIZE = 11; +constexpr U32 PARCEL_MEDIA_COMMAND_DESC = 12; +constexpr U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13; const S32 CHAT_CHANNEL_DEBUG = S32_MAX; // agent constants -const U32 CONTROL_AT_POS_INDEX = 0; -const U32 CONTROL_AT_NEG_INDEX = 1; -const U32 CONTROL_LEFT_POS_INDEX = 2; -const U32 CONTROL_LEFT_NEG_INDEX = 3; -const U32 CONTROL_UP_POS_INDEX = 4; -const U32 CONTROL_UP_NEG_INDEX = 5; -const U32 CONTROL_PITCH_POS_INDEX = 6; -const U32 CONTROL_PITCH_NEG_INDEX = 7; -const U32 CONTROL_YAW_POS_INDEX = 8; -const U32 CONTROL_YAW_NEG_INDEX = 9; -const U32 CONTROL_FAST_AT_INDEX = 10; -const U32 CONTROL_FAST_LEFT_INDEX = 11; -const U32 CONTROL_FAST_UP_INDEX = 12; -const U32 CONTROL_FLY_INDEX = 13; -const U32 CONTROL_STOP_INDEX = 14; -const U32 CONTROL_FINISH_ANIM_INDEX = 15; -const U32 CONTROL_STAND_UP_INDEX = 16; -const U32 CONTROL_SIT_ON_GROUND_INDEX = 17; -const U32 CONTROL_MOUSELOOK_INDEX = 18; -const U32 CONTROL_NUDGE_AT_POS_INDEX = 19; -const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20; -const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21; -const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22; -const U32 CONTROL_NUDGE_UP_POS_INDEX = 23; -const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24; -const U32 CONTROL_TURN_LEFT_INDEX = 25; -const U32 CONTROL_TURN_RIGHT_INDEX = 26; -const U32 CONTROL_AWAY_INDEX = 27; -const U32 CONTROL_LBUTTON_DOWN_INDEX = 28; -const U32 CONTROL_LBUTTON_UP_INDEX = 29; -const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30; -const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31; -const U32 TOTAL_CONTROLS = 32; - -const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001 -const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002 -const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004 -const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008 -const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010 -const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020 -const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040 -const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080 -const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100 -const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200 - -const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400 -const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800 -const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000 - -const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000 -const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000 -const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000 -const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000 -const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000 -const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000 - -const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000 -const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000 -const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000 -const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000 -const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000 -const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000 -const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000 -const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000 - -const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000 - -const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000 -const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000 -const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000 -const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000 +constexpr U32 CONTROL_AT_POS_INDEX = 0; +constexpr U32 CONTROL_AT_NEG_INDEX = 1; +constexpr U32 CONTROL_LEFT_POS_INDEX = 2; +constexpr U32 CONTROL_LEFT_NEG_INDEX = 3; +constexpr U32 CONTROL_UP_POS_INDEX = 4; +constexpr U32 CONTROL_UP_NEG_INDEX = 5; +constexpr U32 CONTROL_PITCH_POS_INDEX = 6; +constexpr U32 CONTROL_PITCH_NEG_INDEX = 7; +constexpr U32 CONTROL_YAW_POS_INDEX = 8; +constexpr U32 CONTROL_YAW_NEG_INDEX = 9; +constexpr U32 CONTROL_FAST_AT_INDEX = 10; +constexpr U32 CONTROL_FAST_LEFT_INDEX = 11; +constexpr U32 CONTROL_FAST_UP_INDEX = 12; +constexpr U32 CONTROL_FLY_INDEX = 13; +constexpr U32 CONTROL_STOP_INDEX = 14; +constexpr U32 CONTROL_FINISH_ANIM_INDEX = 15; +constexpr U32 CONTROL_STAND_UP_INDEX = 16; +constexpr U32 CONTROL_SIT_ON_GROUND_INDEX = 17; +constexpr U32 CONTROL_MOUSELOOK_INDEX = 18; +constexpr U32 CONTROL_NUDGE_AT_POS_INDEX = 19; +constexpr U32 CONTROL_NUDGE_AT_NEG_INDEX = 20; +constexpr U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21; +constexpr U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22; +constexpr U32 CONTROL_NUDGE_UP_POS_INDEX = 23; +constexpr U32 CONTROL_NUDGE_UP_NEG_INDEX = 24; +constexpr U32 CONTROL_TURN_LEFT_INDEX = 25; +constexpr U32 CONTROL_TURN_RIGHT_INDEX = 26; +constexpr U32 CONTROL_AWAY_INDEX = 27; +constexpr U32 CONTROL_LBUTTON_DOWN_INDEX = 28; +constexpr U32 CONTROL_LBUTTON_UP_INDEX = 29; +constexpr U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30; +constexpr U32 CONTROL_ML_LBUTTON_UP_INDEX = 31; +constexpr U32 TOTAL_CONTROLS = 32; + +constexpr U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001 +constexpr U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002 +constexpr U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004 +constexpr U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008 +constexpr U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010 +constexpr U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020 +constexpr U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040 +constexpr U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080 +constexpr U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100 +constexpr U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200 + +constexpr U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400 +constexpr U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800 +constexpr U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000 + +constexpr U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000 +constexpr U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000 +constexpr U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000 +constexpr U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000 +constexpr U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000 +constexpr U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000 + +constexpr U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000 +constexpr U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000 +constexpr U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000 +constexpr U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000 +constexpr U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000 +constexpr U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000 +constexpr U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000 +constexpr U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000 + +constexpr U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000 + +constexpr U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000 +constexpr U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000 +constexpr U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000 +constexpr U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000 // move these up so that we can hide them in "State" for object updates // (for now) -const U32 AGENT_ATTACH_OFFSET = 4; -const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET; +constexpr U32 AGENT_ATTACH_OFFSET = 4; +constexpr U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET; // RN: this method swaps the upper and lower nibbles to maintain backward // compatibility with old objects that only used the upper nibble #define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4))) // DO NOT CHANGE THE SEQUENCE OF THIS LIST!! -const U8 CLICK_ACTION_NONE = 0; -const U8 CLICK_ACTION_TOUCH = 0; -const U8 CLICK_ACTION_SIT = 1; -const U8 CLICK_ACTION_BUY = 2; -const U8 CLICK_ACTION_PAY = 3; -const U8 CLICK_ACTION_OPEN = 4; -const U8 CLICK_ACTION_PLAY = 5; -const U8 CLICK_ACTION_OPEN_MEDIA = 6; -const U8 CLICK_ACTION_ZOOM = 7; -const U8 CLICK_ACTION_DISABLED = 8; -const U8 CLICK_ACTION_IGNORE = 9; +constexpr U8 CLICK_ACTION_NONE = 0; +constexpr U8 CLICK_ACTION_TOUCH = 0; +constexpr U8 CLICK_ACTION_SIT = 1; +constexpr U8 CLICK_ACTION_BUY = 2; +constexpr U8 CLICK_ACTION_PAY = 3; +constexpr U8 CLICK_ACTION_OPEN = 4; +constexpr U8 CLICK_ACTION_PLAY = 5; +constexpr U8 CLICK_ACTION_OPEN_MEDIA = 6; +constexpr U8 CLICK_ACTION_ZOOM = 7; +constexpr U8 CLICK_ACTION_DISABLED = 8; +constexpr U8 CLICK_ACTION_IGNORE = 9; // DO NOT CHANGE THE SEQUENCE OF THIS LIST!! +constexpr U32 BEACON_SHOW_MAP = 0x0001; +constexpr U32 BEACON_FOCUS_MAP = 0x0002; #endif diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 3d18864b80..57f5a112d9 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -282,7 +282,7 @@ public: LLRunner& getRunner() { return mRunner; } #ifdef LL_WINDOWS - virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { } + virtual bool reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { return false; } #endif public: 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/llcoros.cpp b/indra/llcommon/llcoros.cpp index 1539b48bd3..9e95d9c85f 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -310,26 +310,55 @@ namespace static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop) { - if (code == STATUS_MSC_EXCEPTION) + if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop)) + { + // Handled + return EXCEPTION_CONTINUE_SEARCH; + } + else if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on return EXCEPTION_CONTINUE_SEARCH; } else { - // handle it + // handle it, convert to std::exception return EXCEPTION_EXECUTE_HANDLER; } + + return EXCEPTION_CONTINUE_SEARCH; } -void sehandle(const LLCoros::callable_t& callable) +void cpphandle(const LLCoros::callable_t& callable, const std::string& name) { - __try + // SE and C++ can not coexists, thus two handlers + try { callable(); } + catch (const LLCoros::Stop& exc) + { + LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " + << exc.what() << LL_ENDL; + } + catch (const LLContinueError&) + { + // Any uncaught exception derived from LLContinueError will be caught + // here and logged. This coroutine will terminate but the rest of the + // viewer will carry on. + LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + } +} + +void sehandle(const LLCoros::callable_t& callable, const std::string& name) +{ + __try + { + // handle stop and continue exceptions first + cpphandle(callable, name); + } __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) { // convert to C++ styled exception @@ -340,16 +369,7 @@ void sehandle(const LLCoros::callable_t& callable) throw std::exception(integer_string); } } - -#else // ! LL_WINDOWS - -inline void sehandle(const LLCoros::callable_t& callable) -{ - callable(); -} - -#endif // ! LL_WINDOWS - +#endif // LL_WINDOWS } // anonymous namespace // Top-level wrapper around caller's coroutine callable. @@ -362,10 +382,14 @@ void LLCoros::toplevel(std::string name, callable_t callable) // set it as current mCurrent.reset(&corodata); +#ifdef LL_WINDOWS + // can not use __try directly, toplevel requires unwinding, thus use of a wrapper + sehandle(callable, name); +#else // LL_WINDOWS // run the code the caller actually wants in the coroutine try { - sehandle(callable); + callable(); } catch (const Stop& exc) { @@ -387,6 +411,7 @@ void LLCoros::toplevel(std::string name, callable_t callable) << name << LL_ENDL; LLCoros::instance().saveException(name, std::current_exception()); } +#endif // else LL_WINDOWS } //static diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index b38864688d..5205699b92 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -77,6 +77,15 @@ std::string LLDate::asRFC1123() const return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); } +std::string LLDate::toLocalDateString (std::string fmt) const +{ + LL_PROFILE_ZONE_SCOPED; + + time_t locSeconds = (time_t) mSecondsSinceEpoch; + struct tm * lt = localtime (&locSeconds); + return toHTTPDateString(lt, fmt); +} + std::string LLDate::toHTTPDateString (std::string fmt) const { LL_PROFILE_ZONE_SCOPED; diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 1a69a04232..34c8692f20 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -77,6 +77,7 @@ public: std::string asRFC1123() const; void toStream(std::ostream&) const; bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const; + std::string toLocalDateString(std::string fmt) const; std::string toHTTPDateString (std::string fmt) const; static std::string toHTTPDateString (tm * gmt, std::string fmt); /** diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index 2fbb26dc1a..232987da14 100644 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h @@ -171,13 +171,13 @@ constexpr U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + // recursion tail template <typename T> -inline auto llmax(T data) +constexpr auto llmax(T data) { return data; } template <typename T0, typename T1, typename... Ts> -inline auto llmax(T0 d0, T1 d1, Ts... rest) +constexpr auto llmax(T0 d0, T1 d1, Ts... rest) { auto maxrest = llmax(d1, rest...); return (d0 > maxrest)? d0 : maxrest; @@ -185,20 +185,20 @@ inline auto llmax(T0 d0, T1 d1, Ts... rest) // recursion tail template <typename T> -inline auto llmin(T data) +constexpr auto llmin(T data) { return data; } template <typename T0, typename T1, typename... Ts> -inline auto llmin(T0 d0, T1 d1, Ts... rest) +constexpr auto llmin(T0 d0, T1 d1, Ts... rest) { auto minrest = llmin(d1, rest...); return (d0 < minrest) ? d0 : minrest; } template <typename A, typename MIN, typename MAX> -inline A llclamp(A a, MIN minval, MAX maxval) +constexpr A llclamp(A a, MIN minval, MAX maxval) { A aminval{ static_cast<A>(minval) }, amaxval{ static_cast<A>(maxval) }; if ( a < aminval ) @@ -213,13 +213,13 @@ inline A llclamp(A a, MIN minval, MAX maxval) } template <class LLDATATYPE> -inline LLDATATYPE llclampf(LLDATATYPE a) +constexpr LLDATATYPE llclampf(LLDATATYPE a) { return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1)); } template <class LLDATATYPE> -inline LLDATATYPE llclampb(LLDATATYPE a) +constexpr LLDATATYPE llclampb(LLDATATYPE a) { return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255)); } diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 90c6ba309b..d834098994 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1604,11 +1604,11 @@ namespace LLError std::string LLUserWarningMsg::sLocalizedOutOfMemoryWarning; LLUserWarningMsg::Handler LLUserWarningMsg::sHandler; - void LLUserWarningMsg::show(const std::string& message) + void LLUserWarningMsg::show(const std::string& message, S32 error_code) { if (sHandler) { - sHandler(std::string(), message); + sHandler(std::string(), message, error_code); } } @@ -1616,7 +1616,7 @@ namespace LLError { if (sHandler && !sLocalizedOutOfMemoryTitle.empty()) { - sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning); + sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning, ERROR_BAD_ALLOC); } } @@ -1627,7 +1627,7 @@ namespace LLError "Second Life viewer couldn't access some of the files it needs and will be closed." "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and " "contact https://support.secondlife.com if issue persists after reinstall."; - sHandler("Missing Files", error_string); + sHandler("Missing Files", error_string, ERROR_MISSING_FILES); } void LLUserWarningMsg::setHandler(const LLUserWarningMsg::Handler &handler) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 8a143ff30a..41893a35e5 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -308,7 +308,16 @@ namespace LLError class LLUserWarningMsg { public: - typedef std::function<void(const std::string&, const std::string&)> Handler; + // error codes, tranlates to last_exec states like LAST_EXEC_OTHER_CRASH + typedef enum + { + ERROR_OTHER = 0, + ERROR_BAD_ALLOC = 1, + ERROR_MISSING_FILES = 2, + } eLastExecEvent; + + // tittle, message and error code to include in error marker file + typedef std::function<void(const std::string&, const std::string&, S32 error_code)> Handler; static void setHandler(const Handler&); static void setOutOfMemoryStrings(const std::string& title, const std::string& message); @@ -316,7 +325,7 @@ namespace LLError static void showOutOfMemory(); static void showMissingFiles(); // Genering error - static void show(const std::string&); + static void show(const std::string&, S32 error_code = -1); private: // needs to be preallocated before viewer runs out of memory 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 a783e18e49..c0b1a5c9e3 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 } }; @@ -638,6 +669,13 @@ public: { getCPUIDInfo(); uint64_t frequency = getSysctlInt64("hw.cpufrequency"); + if (!frequency) { + auto tbfrequency = getSysctlInt64("hw.tbfrequency"); + struct clockinfo clockrate; + auto clockrate_len = sizeof(clockrate); + if (!sysctlbyname("kern.clockrate", &clockrate, &clockrate_len, NULL, 0)) + frequency = tbfrequency * clockrate.hz; + } setInfo(eFrequency, (F64)frequency / (F64)1000000); } @@ -743,12 +781,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 @@ -793,20 +833,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; @@ -835,32 +1005,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"); @@ -868,7 +1031,7 @@ private: LLPI_SET_INFO_INT(eModel, "model"); - S32 family; + S32 family{}; if (!cpuinfo["cpu family"].empty() && LLStringUtil::convertToS32(cpuinfo["cpu family"], family)) { @@ -973,6 +1136,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/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 1c4ac5a7bf..0196a24b18 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -146,7 +146,7 @@ size_t LLQueuedThread::updateQueue(F32 max_time_ms) // schedule a call to threadedUpdate for every call to updateQueue if (!isQuitting()) { - mRequestQueue.post([=]() + mRequestQueue.post([=, this]() { LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update"); mIdleThread = false; @@ -474,7 +474,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req) #else using namespace std::chrono_literals; auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms; - mRequestQueue.post([=] + mRequestQueue.post([=, this] { LL_PROFILE_ZONE_NAMED("processRequest - retry"); if (LL::WorkQueue::TimePoint::clock::now() < retry_time) 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/llsdutil.h b/indra/llcommon/llsdutil.h index 38bbe19ddd..c31030c5ea 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -553,6 +553,61 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter } // namespace llsd +/***************************************************************************** + * 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.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 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/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 28e50b3d21..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 @@ -164,14 +169,14 @@ private: FROM mValue; public: - narrow(FROM value): mValue(value) {} + constexpr narrow(FROM value): mValue(value) {} /*---------------------- Narrowing unsigned to signed ----------------------*/ template <typename TO, typename std::enable_if<std::is_unsigned<FROM>::value && std::is_signed<TO>::value, bool>::type = true> - inline + constexpr operator TO() const { // The reason we skip the @@ -189,7 +194,7 @@ public: typename std::enable_if<! (std::is_unsigned<FROM>::value && std::is_signed<TO>::value), bool>::type = true> - inline + constexpr operator TO() const { // two different assert()s so we can tell which condition failed 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); diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index 6066e74fb5..c8ece616b2 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -17,6 +17,7 @@ // std headers // external library headers // other Linden headers +#include "llapp.h" #include "llcoros.h" #include LLCOROS_MUTEX_HEADER #include "llerror.h" @@ -102,19 +103,95 @@ std::string LL::WorkQueueBase::makeName(const std::string& name) return STRINGIZE("WorkQueue" << num); } +namespace +{ +#if LL_WINDOWS + + static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific + + U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop) + { + if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop)) + { + // Handled + return EXCEPTION_CONTINUE_SEARCH; + } + else if (code == STATUS_MSC_EXCEPTION) + { + // C++ exception, go on + return EXCEPTION_CONTINUE_SEARCH; + } + else + { + // handle it, convert to std::exception + return EXCEPTION_EXECUTE_HANDLER; + } + + return EXCEPTION_CONTINUE_SEARCH; + } + + void cpphandle(const LL::WorkQueueBase::Work& work) + { + // SE and C++ can not coexists, thus two handlers + try + { + work(); + } + catch (const LLContinueError&) + { + // Any uncaught exception derived from LLContinueError will be caught + // here and logged. This coroutine will terminate but the rest of the + // viewer will carry on. + LOG_UNHANDLED_EXCEPTION(STRINGIZE("LLContinue in work queue")); + } + } + + void sehandle(const LL::WorkQueueBase::Work& work) + { + __try + { + // handle stop and continue exceptions first + cpphandle(work); + } + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) + { + // convert to C++ styled exception + char integer_string[512]; + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + throw std::exception(integer_string); + } + } +#endif // LL_WINDOWS +} // anonymous namespace + void LL::WorkQueueBase::callWork(const Work& work) { LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + +#ifdef LL_WINDOWS + // can not use __try directly, toplevel requires unwinding, thus use of a wrapper + sehandle(work); +#else // LL_WINDOWS try { work(); } - catch (...) + catch (LLContinueError&) { - // No matter what goes wrong with any individual work item, the worker - // thread must go on! Log our own instance name with the exception. LOG_UNHANDLED_EXCEPTION(getKey()); } + catch (...) + { + // Stash any other kind of uncaught exception to be rethrown by main thread. + LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase " + << getKey() << LL_ENDL; + + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + main_queue->post( + // Bind the current exception, rethrow it in main loop. + [exc = std::current_exception()]() { std::rethrow_exception(exc); }); + } +#endif // else LL_WINDOWS } void LL::WorkQueueBase::error(const std::string& msg) |