[Threading] Make VA thread safe

This fixes an issue for dedis
This commit is contained in:
momo5502 2017-05-31 18:03:33 +02:00
parent 7af0f7368c
commit 9f50c260c8
3 changed files with 52 additions and 9 deletions

View File

@ -43,5 +43,8 @@ namespace Components
Utils::Hook(0x627695, 0x627040, HOOK_CALL).install()->quick(); Utils::Hook(0x627695, 0x627040, HOOK_CALL).install()->quick();
Utils::Hook(0x43D1C7, Threading::PacketEventStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x43D1C7, Threading::PacketEventStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x6272E3, Threading::FrameEpilogueStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x6272E3, Threading::FrameEpilogueStub, HOOK_JUMP).install()->quick();
// Make VA thread safe
Utils::Hook(0x4785B0, Utils::String::VA, HOOK_JUMP).install()->quick();
} }
} }

View File

@ -3,25 +3,51 @@
#include "base128.h" #include "base128.h"
#endif #endif
#define VA_BUFFER_COUNT 32
#define VA_BUFFER_SIZE 65536
namespace Utils namespace Utils
{ {
namespace String namespace String
{ {
VAProvider::VAProvider(size_t buffers) : currentBuffer(0)
{
this->stringBuffers.resize(buffers);
}
char* VAProvider::get(const char* format, va_list ap)
{
++this->currentBuffer %= this->stringBuffers.size();
auto& buffer = this->stringBuffers[this->currentBuffer];
if (!buffer.first || !buffer.second)
{
buffer.first = 256;
if (buffer.second) this->allocator.free(buffer.second);
buffer.second = this->allocator.allocateArray<char>(buffer.first + 1);
}
while(true)
{
int res = vsnprintf_s(buffer.second, buffer.first, _TRUNCATE, format, ap);
if (res > 0) break; // Success
if (res == 0) return ""; // Error
buffer.first *= 2;
this->allocator.free(buffer.second);
buffer.second = this->allocator.allocateArray<char>(buffer.first + 1);
}
return buffer.second;
}
const char *VA(const char *fmt, ...) const char *VA(const char *fmt, ...)
{ {
static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE]; static thread_local VAProvider provider;
static int g_vaNextBufferIndex = 0;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
char* dest = g_vaBuffer[g_vaNextBufferIndex]; const char* result = provider.get(fmt, ap);
vsnprintf_s(g_vaBuffer[g_vaNextBufferIndex], VA_BUFFER_SIZE, fmt, ap);
g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT;
va_end(ap); va_end(ap);
return dest; return result;
} }
std::string ToLower(std::string input) std::string ToLower(std::string input)

View File

@ -4,6 +4,20 @@ namespace Utils
{ {
namespace String namespace String
{ {
class VAProvider
{
public:
VAProvider(size_t buffers = 8);
char* get(const char* format, va_list ap);
private:
size_t currentBuffer;
std::vector<std::pair<size_t,char*>> stringBuffers;
Utils::Memory::Allocator allocator;
};
const char *VA(const char *fmt, ...); const char *VA(const char *fmt, ...);
int IsSpace(int c); int IsSpace(int c);