mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 03:33:56 +00:00
Basic working thread support
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user