use super::{HostState, Registry, StubFn, Win32Error, arg_dword};
use crate::emulator::emulator::{Cpu, Mmu};
pub fn register(registry: &mut Registry) {
let dll = "pthreadVC2.dll";
registry.register(dll, "pthread_key_create", stub_key_create as StubFn, 0);
registry.register(dll, "pthread_key_delete", stub_zero as StubFn, 0);
registry.register(dll, "pthread_setspecific", stub_setspecific as StubFn, 0);
registry.register(dll, "pthread_getspecific", stub_getspecific as StubFn, 0);
registry.register(dll, "pthread_once", stub_once as StubFn, 0);
registry.register(dll, "pthread_mutex_init", stub_zero as StubFn, 0);
registry.register(dll, "pthread_mutex_destroy", stub_zero as StubFn, 0);
registry.register(dll, "pthread_mutex_lock", stub_zero as StubFn, 0);
registry.register(dll, "pthread_mutex_trylock", stub_zero as StubFn, 0);
registry.register(dll, "pthread_mutex_unlock", stub_zero as StubFn, 0);
registry.register(dll, "pthread_mutexattr_init", stub_zero as StubFn, 0);
registry.register(dll, "pthread_mutexattr_destroy", stub_zero as StubFn, 0);
registry.register(dll, "pthread_mutexattr_settype", stub_zero as StubFn, 0);
registry.register(dll, "pthread_cond_init", stub_zero as StubFn, 0);
registry.register(dll, "pthread_cond_destroy", stub_zero as StubFn, 0);
registry.register(dll, "pthread_cond_signal", stub_zero as StubFn, 0);
registry.register(dll, "pthread_cond_broadcast", stub_zero as StubFn, 0);
registry.register(dll, "pthread_cond_wait", stub_zero as StubFn, 0);
registry.register(dll, "pthread_cond_timedwait", stub_zero as StubFn, 0);
registry.register(dll, "pthread_condattr_init", stub_zero as StubFn, 0);
registry.register(dll, "pthread_condattr_destroy", stub_zero as StubFn, 0);
registry.register(dll, "pthread_rwlock_init", stub_zero as StubFn, 0);
registry.register(dll, "pthread_rwlock_destroy", stub_zero as StubFn, 0);
registry.register(dll, "pthread_rwlock_rdlock", stub_zero as StubFn, 0);
registry.register(dll, "pthread_rwlock_wrlock", stub_zero as StubFn, 0);
registry.register(dll, "pthread_rwlock_unlock", stub_zero as StubFn, 0);
registry.register(dll, "pthread_self", stub_self as StubFn, 0);
registry.register(dll, "pthread_equal", stub_equal as StubFn, 0);
registry.register(dll, "pthread_create", stub_zero as StubFn, 0);
registry.register(dll, "pthread_join", stub_zero as StubFn, 0);
registry.register(dll, "pthread_detach", stub_zero as StubFn, 0);
registry.register(dll, "pthread_attr_init", stub_zero as StubFn, 0);
registry.register(dll, "pthread_attr_destroy", stub_zero as StubFn, 0);
registry.register(dll, "pthread_attr_setstacksize", stub_zero as StubFn, 0);
registry.register(dll, "pthread_attr_setdetachstate", stub_zero as StubFn, 0);
registry.register(dll, "pthread_setcancelstate", stub_zero as StubFn, 0);
registry.register(dll, "pthread_setcanceltype", stub_zero as StubFn, 0);
registry.register(dll, "pthread_testcancel", stub_zero as StubFn, 0);
registry.register(dll, "pthread_cancel", stub_zero as StubFn, 0);
}
fn stub_key_create(
cpu: &mut Cpu,
mmu: &mut Mmu,
state: &mut HostState,
_registry: &mut Registry,
) -> Result<u32, Win32Error> {
let key_ptr = arg_dword(cpu, mmu, 0)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_key_create", t))?;
let _destructor = arg_dword(cpu, mmu, 1)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_key_create", t))?;
if state.next_pthread_key == 0 {
state.next_pthread_key = 1;
}
let slot = state.next_pthread_key;
state.next_pthread_key = state.next_pthread_key.saturating_add(1);
if key_ptr != 0 {
mmu.store32(key_ptr, slot)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_key_create", t))?;
}
Ok(0)
}
fn stub_setspecific(
cpu: &mut Cpu,
mmu: &mut Mmu,
state: &mut HostState,
_registry: &mut Registry,
) -> Result<u32, Win32Error> {
let key = arg_dword(cpu, mmu, 0)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_setspecific", t))?;
let value = arg_dword(cpu, mmu, 1)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_setspecific", t))?;
state.cur_thread_mut().pthread_slots.insert(key, value);
Ok(0)
}
fn stub_getspecific(
cpu: &mut Cpu,
mmu: &mut Mmu,
state: &mut HostState,
_registry: &mut Registry,
) -> Result<u32, Win32Error> {
let key = arg_dword(cpu, mmu, 0)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_getspecific", t))?;
Ok(state
.cur_thread()
.pthread_slots
.get(&key)
.copied()
.unwrap_or(0))
}
fn stub_once(
cpu: &mut Cpu,
mmu: &mut Mmu,
state: &mut HostState,
registry: &mut Registry,
) -> Result<u32, Win32Error> {
let once_ptr = arg_dword(cpu, mmu, 0)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_once", t))?;
let init_fn = arg_dword(cpu, mmu, 1)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_once", t))?;
if once_ptr == 0 || init_fn == 0 {
return Ok(0);
}
let state_word = mmu
.load32(once_ptr)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_once", t))?;
if state_word != 0 {
return Ok(0);
}
mmu.store32(once_ptr, 1)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_once", t))?;
if let Err(crate::emulator::Error::Win32(e)) =
crate::emulator::win32::call_guest(cpu, mmu, registry, state, init_fn, &[])
{
return Err(e);
}
Ok(0)
}
fn stub_self(
_cpu: &mut Cpu,
_mmu: &mut Mmu,
state: &mut HostState,
_registry: &mut Registry,
) -> Result<u32, Win32Error> {
Ok(state.active_tid)
}
fn stub_equal(
cpu: &mut Cpu,
mmu: &mut Mmu,
_state: &mut HostState,
_registry: &mut Registry,
) -> Result<u32, Win32Error> {
let a = arg_dword(cpu, mmu, 0)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_equal", t))?;
let b = arg_dword(cpu, mmu, 1)
.map_err(|t| crate::emulator::win32::trap_to_win32_local("pthread_equal", t))?;
Ok(if a == b { 1 } else { 0 })
}
fn stub_zero(
_cpu: &mut Cpu,
_mmu: &mut Mmu,
_state: &mut HostState,
_registry: &mut Registry,
) -> Result<u32, Win32Error> {
Ok(0)
}