Basic working thread support

This commit is contained in:
momo5502
2024-10-19 10:59:50 +02:00
parent d3ce5de9de
commit 669bf73fb6
4 changed files with 114 additions and 19 deletions

View File

@@ -138,9 +138,8 @@ public:
return this->store_.size();
}
bool erase(const handle_value h)
bool erase(const typename value_map::iterator& entry)
{
const auto entry = this->get_iterator(h);
if (entry == this->store_.end())
{
return false;
@@ -158,6 +157,12 @@ public:
return true;
}
bool erase(const handle_value h)
{
const auto entry = this->get_iterator(h);
return this->erase(entry);
}
bool erase(const handle h)
{
return this->erase(h.value);
@@ -171,6 +176,12 @@ public:
return this->erase(hh);
}
bool erase(const T& value)
{
const auto entry = this->find(value);
return this->erase(entry);
}
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write_map(this->store_);
@@ -181,22 +192,50 @@ public:
buffer.read_map(this->store_);
}
value_map::iterator begin()
typename value_map::iterator find(const T& value)
{
auto i = this->store_.begin();
for (; i != this->store_.end(); ++i)
{
if (&i->second == &value)
{
break;
}
}
return i;
}
typename value_map::const_iterator find(const T& value) const
{
auto i = this->store_.begin();
for (; i != this->store_.end(); ++i)
{
if (&i->second == &value)
{
break;
}
}
return i;
}
typename value_map::iterator begin()
{
return this->store_.begin();
}
value_map::const_iterator begin() const
typename value_map::const_iterator begin() const
{
return this->store_.begin();
}
value_map::iterator end()
typename value_map::iterator end()
{
return this->store_.end();
}
value_map::const_iterator end() const
typename value_map::const_iterator end() const
{
return this->store_.end();
}

View File

@@ -21,12 +21,31 @@
#define GDT_LIMIT 0x1000
#define GDT_ENTRY_SIZE 0x8
struct event
struct ref_counted_object
{
uint32_t ref_count{1};
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->ref_count);
}
void deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->ref_count);
}
static bool deleter(ref_counted_object& e)
{
return --e.ref_count == 0;
}
};
struct event : ref_counted_object
{
bool signaled{};
EVENT_TYPE type{};
std::wstring name{};
uint32_t ref_count{0};
bool is_signaled()
{
@@ -45,7 +64,8 @@ struct event
buffer.write(this->signaled);
buffer.write(this->type);
buffer.write(this->name);
buffer.write(this->ref_count);
ref_counted_object::serialize(buffer);
}
void deserialize(utils::buffer_deserializer& buffer)
@@ -53,12 +73,8 @@ struct event
buffer.read(this->signaled);
buffer.read(this->type);
buffer.read(this->name);
buffer.read(this->ref_count);
}
static bool deleter(event& e)
{
return --e.ref_count == 0;
ref_counted_object::deserialize(buffer);
}
};
@@ -157,7 +173,7 @@ private:
bool was_moved_{false};
};
class emulator_thread
class emulator_thread : ref_counted_object
{
public:
emulator_thread() = default;

View File

@@ -273,6 +273,11 @@ namespace
return STATUS_SUCCESS;
}
if (value.type == handle_types::thread && c.proc.threads.erase(handle))
{
return STATUS_SUCCESS;
}
if (value.type == handle_types::event && c.proc.events.erase(handle))
{
return STATUS_SUCCESS;
@@ -319,7 +324,6 @@ namespace
event e{};
e.type = event_type;
e.signaled = initial_state != FALSE;
e.ref_count = 1;
e.name = std::move(name);
const auto handle = c.proc.events.store(std::move(e));
@@ -2032,10 +2036,13 @@ namespace
return STATUS_WAIT_0;
}
NTSTATUS handle_NtTerminateThread(const syscall_context& c, const uint64_t thread_handle,
NTSTATUS handle_NtTerminateThread(const syscall_context& c, uint64_t thread_handle,
const NTSTATUS exit_status)
{
auto* thread = c.proc.threads.get(thread_handle);
auto* thread = !thread_handle
? c.proc.active_thread
: c.proc.threads.get(thread_handle);
if (!thread)
{
return STATUS_INVALID_HANDLE;

View File

@@ -430,6 +430,33 @@ namespace
thread.setup_if_necessary(emu, context);
}
void cleanup_threads(process_context& context)
{
while (true)
{
bool has_changed = false;
for (auto i = context.threads.begin(); i != context.threads.end(); ++i)
{
if (i->second.exit_status.has_value())
{
if (&i->second == context.active_thread)
{
context.active_thread = nullptr;
}
context.threads.erase(i);
has_changed = true;
break;
}
}
if (!has_changed)
{
break;
}
}
}
void switch_to_thread(x64_emulator& emu, process_context& context, const handle thread_handle)
{
auto* thread = context.threads.get(thread_handle);
@@ -443,13 +470,19 @@ namespace
void switch_to_next_thread(x64_emulator& emu, process_context& context)
{
bool next_thread = false;
//cleanup_threads(context);
bool next_thread = false;
for (auto& thread : context.threads)
{
if (next_thread)
{
if (thread.second.exit_status.has_value())
{
continue;
}
switch_to_thread(emu, context, thread.second);
return;
}