summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt11
-rw-r--r--indra/llcommon/llalignedarray.h10
-rw-r--r--indra/llcommon/llcoros.cpp91
-rw-r--r--indra/llcommon/llcoros.h33
-rw-r--r--indra/llcommon/llerror.cpp2
-rw-r--r--indra/llcommon/llmemory.cpp8
-rw-r--r--indra/llcommon/llprocessor.cpp139
-rw-r--r--indra/llcommon/llprocessor.h5
-rw-r--r--indra/llcommon/llrefcount.cpp2
-rw-r--r--indra/llcommon/llsdserialize.cpp121
-rw-r--r--indra/llcommon/llsdserialize.h6
-rw-r--r--indra/llcommon/llsys.cpp90
-rw-r--r--indra/llcommon/llsys.h12
-rw-r--r--indra/llcommon/llsys_objc.h33
-rw-r--r--indra/llcommon/llsys_objc.mm64
-rw-r--r--indra/llcommon/lluuid.cpp30
-rw-r--r--indra/llcommon/lluuid.h8
-rw-r--r--indra/llcommon/threadpool.cpp1
-rw-r--r--indra/llcommon/threadpool.h4
-rw-r--r--indra/llcommon/workqueue.h8
20 files changed, 498 insertions, 180 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 59aa731af2..df65828d02 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -266,6 +266,11 @@ set(llcommon_HEADER_FILES
workqueue.h
StackWalker.h
)
+
+if (DARWIN)
+ list(APPEND llcommon_HEADER_FILES llsys_objc.h)
+ list(APPEND llcommon_SOURCE_FILES llsys_objc.mm)
+endif (DARWIN)
set_source_files_properties(${llcommon_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -313,12 +318,6 @@ target_link_libraries(
${TRACY_LIBRARY}
)
-if (DARWIN)
- include(CMakeFindFrameworks)
- find_library(CARBON_LIBRARY Carbon)
- target_link_libraries(llcommon ${CARBON_LIBRARY})
-endif (DARWIN)
-
add_dependencies(llcommon stage_third_party_libs)
if (LL_TESTS)
diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h
index b68e9e0f82..da9d98c16c 100644
--- a/indra/llcommon/llalignedarray.h
+++ b/indra/llcommon/llalignedarray.h
@@ -116,14 +116,20 @@ void LLAlignedArray<T, alignment>::resize(U32 size)
template <class T, U32 alignment>
T& LLAlignedArray<T, alignment>::operator[](int idx)
{
- llassert(idx < mElementCount);
+ if(idx >= mElementCount || idx < 0)
+ {
+ LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL;
+ }
return mArray[idx];
}
template <class T, U32 alignment>
const T& LLAlignedArray<T, alignment>::operator[](int idx) const
{
- llassert(idx < mElementCount);
+ if (idx >= mElementCount || idx < 0)
+ {
+ LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL;
+ }
return mArray[idx];
}
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index c2d353b0fc..70d8dfc8b9 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -35,6 +35,7 @@
// STL headers
// std headers
#include <atomic>
+#include <stdexcept>
// external library headers
#include <boost/bind.hpp>
#include <boost/fiber/fiber.hpp>
@@ -214,6 +215,22 @@ std::string LLCoros::logname()
return data.mName.empty()? data.getKey() : data.mName;
}
+void LLCoros::saveException(const std::string& name, std::exception_ptr exc)
+{
+ mExceptionQueue.emplace(name, exc);
+}
+
+void LLCoros::rethrow()
+{
+ if (! mExceptionQueue.empty())
+ {
+ ExceptionData front = mExceptionQueue.front();
+ mExceptionQueue.pop();
+ LL_WARNS("LLCoros") << "Rethrowing exception from coroutine " << front.name << LL_ENDL;
+ std::rethrow_exception(front.exception);
+ }
+}
+
void LLCoros::setStackSize(S32 stacksize)
{
LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
@@ -271,25 +288,15 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
return name;
}
+namespace
+{
+
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name)
+U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
- // C++ exceptions were logged in toplevelTryWrapper, but not SEH
- // log SEH exceptions here, to make sure it gets into bugsplat's
- // report and because __try won't allow std::string operations
- if (code != STATUS_MSC_EXCEPTION)
- {
- LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL;
- }
- // Handle bugsplat here, since GetExceptionInformation() can only be
- // called from within filter for __except(filter), not from __except's {}
- // Bugsplat should get all exceptions, C++ and SEH
- LLApp::instance()->reportCrashToBugsplat(exception_infop);
-
- // Only convert non C++ exceptions.
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
@@ -302,29 +309,38 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop,
}
}
-void LLCoros::winlevel(const std::string& name, const callable_t& callable)
+void sehandle(const LLCoros::callable_t& callable)
{
__try
{
- toplevelTryWrapper(name, callable);
+ callable();
}
- __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name))
+ __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
- // convert to C++ styled exception for handlers other than bugsplat
+ // convert to C++ styled exception
// Note: it might be better to use _se_set_translator
// if you want exception to inherit full callstack
- //
- // in case of bugsplat this will get to exceptionTerminateHandler and
- // looks like fiber will terminate application after that
char integer_string[512];
- sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode());
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
throw std::exception(integer_string);
}
}
-#endif
+#else // ! LL_WINDOWS
+
+inline void sehandle(const LLCoros::callable_t& callable)
+{
+ callable();
+}
-void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable)
+#endif // ! LL_WINDOWS
+
+} // anonymous namespace
+
+// Top-level wrapper around caller's coroutine callable.
+// Normally we like to pass strings and such by const reference -- but in this
+// case, we WANT to copy both the name and the callable to our local stack!
+void LLCoros::toplevel(std::string name, callable_t callable)
{
// keep the CoroData on this top-level function's stack frame
CoroData corodata(name);
@@ -334,12 +350,12 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call
// run the code the caller actually wants in the coroutine
try
{
- callable();
+ sehandle(callable);
}
catch (const Stop& exc)
{
LL_INFOS("LLCoros") << "coroutine " << name << " terminating because "
- << exc.what() << LL_ENDL;
+ << exc.what() << LL_ENDL;
}
catch (const LLContinueError&)
{
@@ -350,27 +366,14 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call
}
catch (...)
{
- // Any OTHER kind of uncaught exception will cause the viewer to
- // crash, hopefully informatively.
- LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
- // to not modify callstack
- throw;
+ // Stash any OTHER kind of uncaught exception in the rethrow() queue
+ // to be rethrown by the main fiber.
+ LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine "
+ << name << LL_ENDL;
+ LLCoros::instance().saveException(name, std::current_exception());
}
}
-// Top-level wrapper around caller's coroutine callable.
-// Normally we like to pass strings and such by const reference -- but in this
-// case, we WANT to copy both the name and the callable to our local stack!
-void LLCoros::toplevel(std::string name, callable_t callable)
-{
-#if LL_WINDOWS
- // Can not use __try in functions that require unwinding, so use one more wrapper
- winlevel(name, callable);
-#else
- toplevelTryWrapper(name, callable);
-#endif
-}
-
//static
void LLCoros::checkStop()
{
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index a94cfca19f..966ce03296 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -38,6 +38,8 @@
#include "llinstancetracker.h"
#include <boost/function.hpp>
#include <string>
+#include <exception>
+#include <queue>
// e.g. #include LLCOROS_MUTEX_HEADER
#define LLCOROS_MUTEX_HEADER <boost/fiber/mutex.hpp>
@@ -156,6 +158,19 @@ public:
* LLCoros::launch()).
*/
static std::string getName();
+
+ /**
+ * rethrow() is called by the thread's main fiber to propagate an
+ * exception from any coroutine into the main fiber, where it can engage
+ * the normal unhandled-exception machinery, up to and including crash
+ * reporting.
+ *
+ * LLCoros maintains a queue of otherwise-uncaught exceptions from
+ * terminated coroutines. Each call to rethrow() pops the first of those
+ * and rethrows it. When the queue is empty (normal case), rethrow() is a
+ * no-op.
+ */
+ void rethrow();
/**
* This variation returns a name suitable for log messages: the explicit
@@ -292,13 +307,23 @@ public:
private:
std::string generateDistinctName(const std::string& prefix) const;
-#if LL_WINDOWS
- void winlevel(const std::string& name, const callable_t& callable);
-#endif
- void toplevelTryWrapper(const std::string& name, const callable_t& callable);
void toplevel(std::string name, callable_t callable);
struct CoroData;
static CoroData& get_CoroData(const std::string& caller);
+ void saveException(const std::string& name, std::exception_ptr exc);
+
+ struct ExceptionData
+ {
+ ExceptionData(const std::string& nm, std::exception_ptr exc):
+ name(nm),
+ exception(exc)
+ {}
+ // name of coroutine that originally threw this exception
+ std::string name;
+ // the thrown exception
+ std::exception_ptr exception;
+ };
+ std::queue<ExceptionData> mExceptionQueue;
S32 mStackSize;
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 919d2dabc4..56fb7c21ca 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -943,7 +943,7 @@ namespace LLError
for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a)
{
const LLSD& entry = *a;
- if (entry.isMap() && !entry.emptyMap())
+ if (entry.isMap() && entry.size() != 0)
{
ELevel level = decodeLevel(entry["level"]);
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 849867586a..d6ae1284d3 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -212,11 +212,9 @@ U64 LLMemory::getCurrentRSS()
mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
{
-// residentSize = basicInfo.resident_size;
- // Although this method is defined to return the "resident set size,"
- // in fact what callers want from it is the total virtual memory
- // consumed by the application.
- residentSize = basicInfo.virtual_size;
+ residentSize = basicInfo.resident_size;
+ // 64-bit macos apps allocate 32 GB or more at startup, and this is reflected in virtual_size.
+ // basicInfo.virtual_size is not what we want.
}
else
{
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 818df07bb2..4a1a81f083 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -118,7 +118,11 @@ namespace
eMONTIOR_MWAIT=33,
eCPLDebugStore=34,
eThermalMonitor2=35,
- eAltivec=36
+ eAltivec=36,
+ eSSE3S_Features = 37,
+ eSSE4_1_Features = 38,
+ eSSE4_2_Features = 39,
+ eSSE4a_Features = 40,
};
const char* cpu_feature_names[] =
@@ -161,7 +165,11 @@ namespace
"CPL Qualified Debug Store",
"Thermal Monitor 2",
- "Altivec"
+ "Altivec",
+ "SSE3S Instructions",
+ "SSE4.1 Instructions",
+ "SSE4.2 Instructions",
+ "SSE4a Instructions",
};
std::string intel_CPUFamilyName(int composed_family)
@@ -250,6 +258,31 @@ public:
return hasExtension(cpu_feature_names[eSSE2_Ext]);
}
+ bool hasSSE3() const
+ {
+ return hasExtension(cpu_feature_names[eSSE3_Features]);
+ }
+
+ bool hasSSE3S() const
+ {
+ return hasExtension(cpu_feature_names[eSSE3S_Features]);
+ }
+
+ bool hasSSE41() const
+ {
+ return hasExtension(cpu_feature_names[eSSE4_1_Features]);
+ }
+
+ bool hasSSE42() const
+ {
+ return hasExtension(cpu_feature_names[eSSE4_2_Features]);
+ }
+
+ bool hasSSE4a() const
+ {
+ return hasExtension(cpu_feature_names[eSSE4a_Features]);
+ }
+
bool hasAltivec() const
{
return hasExtension("Altivec");
@@ -473,6 +506,12 @@ private:
*((int*)(cpu_vendor+4)) = cpu_info[3];
*((int*)(cpu_vendor+8)) = cpu_info[2];
setInfo(eVendor, cpu_vendor);
+ std::string cmp_vendor(cpu_vendor);
+ bool is_amd = false;
+ if (cmp_vendor == "AuthenticAMD")
+ {
+ is_amd = true;
+ }
// Get the information associated with each valid Id
for(unsigned int i=0; i<=ids; ++i)
@@ -504,6 +543,7 @@ private:
if(cpu_info[2] & 0x8)
{
+ // intel specific SSE3 suplements
setExtension(cpu_feature_names[eMONTIOR_MWAIT]);
}
@@ -516,7 +556,22 @@ private:
{
setExtension(cpu_feature_names[eThermalMonitor2]);
}
-
+
+ if (cpu_info[2] & 0x200)
+ {
+ setExtension(cpu_feature_names[eSSE3S_Features]);
+ }
+
+ if (cpu_info[2] & 0x80000)
+ {
+ setExtension(cpu_feature_names[eSSE4_1_Features]);
+ }
+
+ if (cpu_info[2] & 0x100000)
+ {
+ setExtension(cpu_feature_names[eSSE4_2_Features]);
+ }
+
unsigned int feature_info = (unsigned int) cpu_info[3];
for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
{
@@ -543,8 +598,17 @@ private:
__cpuid(cpu_info, i);
// Interpret CPU brand string and cache information.
- if (i == 0x80000002)
- memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info));
+ if (i == 0x80000001)
+ {
+ if (is_amd)
+ {
+ setExtension(cpu_feature_names[eSSE4a_Features]);
+ }
+ }
+ else if (i == 0x80000002)
+ {
+ memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info));
+ }
else if (i == 0x80000003)
memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info));
else if (i == 0x80000004)
@@ -690,6 +754,41 @@ private:
uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits");
S32 *ext_feature_infos = (S32*)(&ext_feature_info);
setConfig(eExtFeatureBits, ext_feature_infos[0]);
+
+
+ char cpu_features[1024];
+ len = sizeof(cpu_features);
+ memset(cpu_features, 0, len);
+ sysctlbyname("machdep.cpu.features", (void*)cpu_features, &len, NULL, 0);
+
+ std::string cpu_features_str(cpu_features);
+ cpu_features_str = " " + cpu_features_str + " ";
+
+ if (cpu_features_str.find(" SSE3 ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE3_Features]);
+ }
+
+ if (cpu_features_str.find(" SSSE3 ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE3S_Features]);
+ }
+
+ if (cpu_features_str.find(" SSE4.1 ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE4_1_Features]);
+ }
+
+ if (cpu_features_str.find(" SSE4.2 ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE4_2_Features]);
+ }
+
+ if (cpu_features_str.find(" SSE4A ") != std::string::npos)
+ {
+ // Not supposed to happen?
+ setExtension(cpu_feature_names[eSSE4a_Features]);
+ }
}
};
@@ -800,6 +899,31 @@ private:
{
setExtension(cpu_feature_names[eSSE2_Ext]);
}
+
+ if (flags.find(" pni ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE3_Features]);
+ }
+
+ if (flags.find(" ssse3 ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE3S_Features]);
+ }
+
+ if (flags.find(" sse4_1 ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE4_1_Features]);
+ }
+
+ if (flags.find(" sse4_2 ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE4_2_Features]);
+ }
+
+ if (flags.find(" sse4a ") != std::string::npos)
+ {
+ setExtension(cpu_feature_names[eSSE4a_Features]);
+ }
# endif // LL_X86
}
@@ -860,6 +984,11 @@ LLProcessorInfo::~LLProcessorInfo() {}
F64MegahertzImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); }
bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
+bool LLProcessorInfo::hasSSE3() const { return mImpl->hasSSE3(); }
+bool LLProcessorInfo::hasSSE3S() const { return mImpl->hasSSE3S(); }
+bool LLProcessorInfo::hasSSE41() const { return mImpl->hasSSE41(); }
+bool LLProcessorInfo::hasSSE42() const { return mImpl->hasSSE42(); }
+bool LLProcessorInfo::hasSSE4a() const { return mImpl->hasSSE4a(); }
bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }
std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); }
std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); }
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index b77eb22c3a..1a473ddc97 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -54,6 +54,11 @@ public:
F64MegahertzImplicit getCPUFrequency() const;
bool hasSSE() const;
bool hasSSE2() const;
+ bool hasSSE3() const;
+ bool hasSSE3S() const;
+ bool hasSSE41() const;
+ bool hasSSE42() const;
+ bool hasSSE4a() const;
bool hasAltivec() const;
std::string getCPUFamilyName() const;
std::string getCPUBrandName() const;
diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp
index 5cbd346411..6852b5536a 100644
--- a/indra/llcommon/llrefcount.cpp
+++ b/indra/llcommon/llrefcount.cpp
@@ -30,7 +30,7 @@
#include "llerror.h"
// maximum reference count before sounding memory leak alarm
-const S32 gMaxRefCount = 65536;
+const S32 gMaxRefCount = S32_MAX;
LLRefCount::LLRefCount(const LLRefCount& other)
: mRef(0)
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 8b4a0ee6d8..a510b73096 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -34,6 +34,9 @@
#include <iostream>
#include "apr_base64.h"
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/stream.hpp>
+
#ifdef LL_USESYSTEMLIBS
# include <zlib.h>
#else
@@ -2128,7 +2131,9 @@ std::string zip_llsd(LLSD& data)
{ //copy result into output
if (strm.avail_out >= CHUNK)
{
- free(output);
+ deflateEnd(&strm);
+ if(output)
+ free(output);
LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
}
@@ -2151,7 +2156,9 @@ std::string zip_llsd(LLSD& data)
}
else
{
- free(output);
+ deflateEnd(&strm);
+ if(output)
+ free(output);
LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
}
@@ -2162,7 +2169,8 @@ std::string zip_llsd(LLSD& data)
std::string result((char*) output, size);
deflateEnd(&strm);
- free(output);
+ if(output)
+ free(output);
return result;
}
@@ -2172,53 +2180,66 @@ std::string zip_llsd(LLSD& data)
// and deserializes from that copy using LLSDSerialize
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size)
{
+ std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]);
+ if (!in)
+ {
+ return ZR_MEM_ERROR;
+ }
+ is.read((char*) in.get(), size);
+
+ return unzip_llsd(data, in.get(), size);
+}
+
+LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size)
+{
U8* result = NULL;
U32 cur_size = 0;
z_stream strm;
- const U32 CHUNK = 65536;
+ constexpr U32 CHUNK = 1024 * 512;
- U8 *in = new(std::nothrow) U8[size];
- if (!in)
+ static thread_local std::unique_ptr<U8[]> out;
+ if (!out)
{
- return ZR_MEM_ERROR;
+ out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]);
}
- is.read((char*) in, size);
-
- U8 out[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = size;
- strm.next_in = in;
+ strm.next_in = const_cast<U8*>(in);
S32 ret = inflateInit(&strm);
do
{
strm.avail_out = CHUNK;
- strm.next_out = out;
+ strm.next_out = out.get();
ret = inflate(&strm, Z_NO_FLUSH);
- if (ret == Z_STREAM_ERROR)
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ case Z_DATA_ERROR:
{
inflateEnd(&strm);
free(result);
- delete [] in;
return ZR_DATA_ERROR;
}
-
- switch (ret)
+ case Z_STREAM_ERROR:
+ case Z_BUF_ERROR:
{
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR;
- case Z_DATA_ERROR:
+ inflateEnd(&strm);
+ free(result);
+ return ZR_BUFFER_ERROR;
+ }
+
case Z_MEM_ERROR:
+ {
inflateEnd(&strm);
free(result);
- delete [] in;
return ZR_MEM_ERROR;
- break;
+ }
}
U32 have = CHUNK-strm.avail_out;
@@ -2231,17 +2252,15 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
{
free(result);
}
- delete[] in;
return ZR_MEM_ERROR;
}
result = new_result;
- memcpy(result+cur_size, out, have);
+ memcpy(result+cur_size, out.get(), have);
cur_size += have;
- } while (ret == Z_OK);
+ } while (ret == Z_OK && ret != Z_STREAM_END);
inflateEnd(&strm);
- delete [] in;
if (ret != Z_STREAM_END)
{
@@ -2251,37 +2270,11 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
//result now points to the decompressed LLSD block
{
- std::istringstream istr;
- // Since we are using this for meshes, data we are dealing with tend to be large.
- // So string can potentially fail to allocate, make sure this won't cause problems
- try
- {
- std::string res_str((char*)result, cur_size);
-
- std::string deprecated_header("<? LLSD/Binary ?>");
-
- if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
- {
- res_str = res_str.substr(deprecated_header.size() + 1, cur_size);
- }
- cur_size = res_str.size();
-
- istr.str(res_str);
- }
-#ifdef LL_WINDOWS
- catch (std::length_error)
- {
- free(result);
- return ZR_SIZE_ERROR;
- }
-#endif
- catch (std::bad_alloc&)
- {
- free(result);
- return ZR_MEM_ERROR;
- }
+ char* result_ptr = strip_deprecated_header((char*)result, cur_size);
- if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH))
+ boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size);
+
+ if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))
{
free(result);
return ZR_PARSE_ERROR;
@@ -2395,4 +2388,22 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
return result;
}
+char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size)
+{
+ const char* deprecated_header = "<? LLSD/Binary ?>";
+ constexpr size_t deprecated_header_size = 17;
+
+ if (cur_size > deprecated_header_size
+ && memcmp(in, deprecated_header, deprecated_header_size) == 0)
+ {
+ in = in + deprecated_header_size;
+ cur_size = cur_size - deprecated_header_size;
+ if (header_size)
+ {
+ *header_size = deprecated_header_size + 1;
+ }
+ }
+
+ return in;
+}
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index d6079fd9fa..d33d2b6f34 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -858,9 +858,12 @@ public:
ZR_SIZE_ERROR,
ZR_DATA_ERROR,
ZR_PARSE_ERROR,
+ ZR_BUFFER_ERROR,
+ ZR_VERSION_ERROR
} EZipRresult;
// return OK or reason for failure
static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size);
+ static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size);
};
//dirty little zip functions -- yell at davep
@@ -868,4 +871,7 @@ LL_COMMON_API std::string zip_llsd(LLSD& data);
LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size);
+
+// returns a pointer to the array or past the array if the deprecated header exists
+LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr);
#endif // LL_LLSDSERIALIZE_H
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 9b6bb3826c..a8b5c7b3a8 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -64,6 +64,7 @@ using namespace llsd;
# include <psapi.h> // GetPerformanceInfo() et al.
# include <VersionHelpers.h>
#elif LL_DARWIN
+# include "llsys_objc.h"
# include <errno.h>
# include <sys/sysctl.h>
# include <sys/utsname.h>
@@ -74,12 +75,6 @@ using namespace llsd;
# include <mach/mach_host.h>
# include <mach/task.h>
# include <mach/task_info.h>
-
-// disable warnings about Gestalt calls being deprecated
-// until Apple get's on the ball and provides an alternative
-//
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
#elif LL_LINUX
# include <errno.h>
# include <sys/utsname.h>
@@ -278,12 +273,9 @@ LLOSInfo::LLOSInfo() :
{
const char * DARWIN_PRODUCT_NAME = "Mac OS X";
- SInt32 major_version, minor_version, bugfix_version;
- OSErr r1 = Gestalt(gestaltSystemVersionMajor, &major_version);
- OSErr r2 = Gestalt(gestaltSystemVersionMinor, &minor_version);
- OSErr r3 = Gestalt(gestaltSystemVersionBugFix, &bugfix_version);
+ S32 major_version, minor_version, bugfix_version = 0;
- if((r1 == noErr) && (r2 == noErr) && (r3 == noErr))
+ if (LLGetDarwinOSInfo(major_version, minor_version, bugfix_version))
{
mMajorVer = major_version;
mMinorVer = minor_version;
@@ -597,6 +589,11 @@ LLCPUInfo::LLCPUInfo()
// proc.WriteInfoTextFile("procInfo.txt");
mHasSSE = proc.hasSSE();
mHasSSE2 = proc.hasSSE2();
+ mHasSSE3 = proc.hasSSE3();
+ mHasSSE3S = proc.hasSSE3S();
+ mHasSSE41 = proc.hasSSE41();
+ mHasSSE42 = proc.hasSSE42();
+ mHasSSE4a = proc.hasSSE4a();
mHasAltivec = proc.hasAltivec();
mCPUMHz = (F64)proc.getCPUFrequency();
mFamily = proc.getCPUFamilyName();
@@ -609,6 +606,35 @@ LLCPUInfo::LLCPUInfo()
}
mCPUString = out.str();
LLStringUtil::trim(mCPUString);
+
+ if (mHasSSE)
+ {
+ mSSEVersions.append("1");
+ }
+ if (mHasSSE2)
+ {
+ mSSEVersions.append("2");
+ }
+ if (mHasSSE3)
+ {
+ mSSEVersions.append("3");
+ }
+ if (mHasSSE3S)
+ {
+ mSSEVersions.append("3S");
+ }
+ if (mHasSSE41)
+ {
+ mSSEVersions.append("4.1");
+ }
+ if (mHasSSE42)
+ {
+ mSSEVersions.append("4.2");
+ }
+ if (mHasSSE4a)
+ {
+ mSSEVersions.append("4a");
+ }
}
bool LLCPUInfo::hasAltivec() const
@@ -626,6 +652,31 @@ bool LLCPUInfo::hasSSE2() const
return mHasSSE2;
}
+bool LLCPUInfo::hasSSE3() const
+{
+ return mHasSSE3;
+}
+
+bool LLCPUInfo::hasSSE3S() const
+{
+ return mHasSSE3S;
+}
+
+bool LLCPUInfo::hasSSE41() const
+{
+ return mHasSSE41;
+}
+
+bool LLCPUInfo::hasSSE42() const
+{
+ return mHasSSE42;
+}
+
+bool LLCPUInfo::hasSSE4a() const
+{
+ return mHasSSE4a;
+}
+
F64 LLCPUInfo::getMHz() const
{
return mCPUMHz;
@@ -636,6 +687,11 @@ std::string LLCPUInfo::getCPUString() const
return mCPUString;
}
+const LLSD& LLCPUInfo::getSSEVersions() const
+{
+ return mSSEVersions;
+}
+
void LLCPUInfo::stream(std::ostream& s) const
{
// gather machine information.
@@ -645,6 +701,11 @@ void LLCPUInfo::stream(std::ostream& s) const
// CPU's attributes regardless of platform
s << "->mHasSSE: " << (U32)mHasSSE << std::endl;
s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl;
+ s << "->mHasSSE3: " << (U32)mHasSSE3 << std::endl;
+ s << "->mHasSSE3S: " << (U32)mHasSSE3S << std::endl;
+ s << "->mHasSSE41: " << (U32)mHasSSE41 << std::endl;
+ s << "->mHasSSE42: " << (U32)mHasSSE42 << std::endl;
+ s << "->mHasSSE4a: " << (U32)mHasSSE4a << std::endl;
s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
s << "->mCPUMHz: " << mCPUMHz << std::endl;
s << "->mCPUString: " << mCPUString << std::endl;
@@ -1341,10 +1402,3 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
if (dst != NULL) gzclose(dst);
return retval;
}
-
-#if LL_DARWIN
-// disable warnings about Gestalt calls being deprecated
-// until Apple get's on the ball and provides an alternative
-//
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index cb92cb0ac6..5ffbf5a732 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -80,10 +80,16 @@ public:
void stream(std::ostream& s) const;
std::string getCPUString() const;
+ const LLSD& getSSEVersions() const;
bool hasAltivec() const;
bool hasSSE() const;
bool hasSSE2() const;
+ bool hasSSE3() const;
+ bool hasSSE3S() const;
+ bool hasSSE41() const;
+ bool hasSSE42() const;
+ bool hasSSE4a() const;
F64 getMHz() const;
// Family is "AMD Duron" or "Intel Pentium Pro"
@@ -92,10 +98,16 @@ public:
private:
bool mHasSSE;
bool mHasSSE2;
+ bool mHasSSE3;
+ bool mHasSSE3S;
+ bool mHasSSE41;
+ bool mHasSSE42;
+ bool mHasSSE4a;
bool mHasAltivec;
F64 mCPUMHz;
std::string mFamily;
std::string mCPUString;
+ LLSD mSSEVersions;
};
//=============================================================================
diff --git a/indra/llcommon/llsys_objc.h b/indra/llcommon/llsys_objc.h
new file mode 100644
index 0000000000..35599a574b
--- /dev/null
+++ b/indra/llcommon/llsys_objc.h
@@ -0,0 +1,33 @@
+/**
+ * @file llsys_objc.h
+ * @brief Header file for llsys_objc.mm
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSYS_OBJC_H
+#define LL_LLSYS_OBJC_H
+
+bool LLGetDarwinOSInfo(int &major, int &minor, int &patch);
+
+
+#endif // LL_LLSYS_OBJC_H
diff --git a/indra/llcommon/llsys_objc.mm b/indra/llcommon/llsys_objc.mm
new file mode 100644
index 0000000000..cdb1e320d5
--- /dev/null
+++ b/indra/llcommon/llsys_objc.mm
@@ -0,0 +1,64 @@
+/**
+ * @file llsys_objc.mm
+ * @brief obj-c implementation of the system information functions
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#import "llsys_objc.h"
+#import <AppKit/AppKit.h>
+
+static int intAtStringIndex(NSArray *array, int index)
+{
+ return [(NSString *)[array objectAtIndex:index] integerValue];
+}
+
+bool LLGetDarwinOSInfo(int &major, int &minor, int &patch)
+{
+ if (NSAppKitVersionNumber > NSAppKitVersionNumber10_8)
+ {
+ NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
+ major = osVersion.majorVersion;
+ minor = osVersion.minorVersion;
+ patch = osVersion.patchVersion;
+ }
+ else
+ {
+ NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile:
+ @"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"];
+ NSArray* versions = [versionString componentsSeparatedByString:@"."];
+ NSUInteger count = [versions count];
+ if (count > 0)
+ {
+ major = intAtStringIndex(versions, 0);
+ if (count > 1)
+ {
+ minor = intAtStringIndex(versions, 1);
+ if (count > 2)
+ {
+ patch = intAtStringIndex(versions, 2);
+ }
+ }
+ }
+ }
+ return true;
+}
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index acce8366ea..6f9e09a587 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -1009,36 +1009,6 @@ LLUUID::LLUUID()
return !(word[0] | word[1] | word[2] | word[3]);
}
-// Copy constructor
- LLUUID::LLUUID(const LLUUID& rhs)
-{
- U32 *tmp = (U32 *)mData;
- U32 *rhstmp = (U32 *)rhs.mData;
- tmp[0] = rhstmp[0];
- tmp[1] = rhstmp[1];
- tmp[2] = rhstmp[2];
- tmp[3] = rhstmp[3];
-}
-
- LLUUID::~LLUUID()
-{
-}
-
-// Assignment
- LLUUID& LLUUID::operator=(const LLUUID& rhs)
-{
- // No need to check the case where this==&rhs. The branch is slower than the write.
- U32 *tmp = (U32 *)mData;
- U32 *rhstmp = (U32 *)rhs.mData;
- tmp[0] = rhstmp[0];
- tmp[1] = rhstmp[1];
- tmp[2] = rhstmp[2];
- tmp[3] = rhstmp[3];
-
- return *this;
-}
-
-
LLUUID::LLUUID(const char *in_string)
{
if (!in_string || in_string[0] == 0)
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 86a396ab06..c139c4eb4e 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -55,10 +55,7 @@ public:
LLUUID();
explicit LLUUID(const char *in_string); // Convert from string.
explicit LLUUID(const std::string& in_string); // Convert from string.
- LLUUID(const LLUUID &in);
- LLUUID &operator=(const LLUUID &rhs);
-
- ~LLUUID();
+ ~LLUUID() = default;
//
// MANIPULATORS
@@ -131,6 +128,9 @@ public:
U8 mData[UUID_BYTES];
};
+static_assert(std::is_trivially_copyable<LLUUID>::value, "LLUUID must be trivial copy");
+static_assert(std::is_trivially_move_assignable<LLUUID>::value, "LLUUID must be trivial move");
+static_assert(std::is_standard_layout<LLUUID>::value, "LLUUID must be a standard layout type");
typedef std::vector<LLUUID> uuid_vec_t;
typedef std::set<LLUUID> uuid_set_t;
diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp
index ba914035e2..d5adf11264 100644
--- a/indra/llcommon/threadpool.cpp
+++ b/indra/llcommon/threadpool.cpp
@@ -22,6 +22,7 @@
#include "stringize.h"
LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity):
+ super(name),
mQueue(name, capacity),
mName("ThreadPool:" + name),
mThreadCount(threads)
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index b79c9b9090..f8eec3b457 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -22,8 +22,10 @@
namespace LL
{
- class ThreadPool
+ class ThreadPool: public LLInstanceTracker<ThreadPool, std::string>
{
+ private:
+ using super = LLInstanceTracker<ThreadPool, std::string>;
public:
/**
* Pass ThreadPool a string name. This can be used to look up the
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 96574a18b9..70fd65bd0c 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -403,7 +403,7 @@ namespace LL
[result = std::forward<CALLABLE>(callable)(),
callback = std::move(callback)]
()
- { callback(std::move(result)); };
+ mutable { callback(std::move(result)); };
}
};
@@ -449,7 +449,7 @@ namespace LL
callable = std::move(callable),
callback = std::move(callback)]
()
- {
+ mutable {
// Use postMaybe() below in case this originating WorkQueue
// has been closed or destroyed. Remember, the outer lambda is
// now running on a thread servicing the target WorkQueue, and
@@ -513,7 +513,7 @@ namespace LL
// We dare to bind a reference to Promise because it's
// specifically designed for cross-thread communication.
[&promise, callable = std::move(callable)]()
- {
+ mutable {
try
{
// call the caller's callable and trigger promise with result
@@ -542,7 +542,7 @@ namespace LL
time,
// &promise is designed for cross-thread access
[&promise, callable = std::move(callable)]()
- {
+ mutable {
try
{
callable();