use core::ffi;
cfg_if::cfg_if! {
if #[cfg(unix)] {
pub(crate) use libc::pthread_t;
pub(crate) use libc::pthread_attr_t;
pub(crate) use libc::sched_param;
pub(crate) use libc::SCHED_OTHER;
pub(crate) use libc::SCHED_FIFO;
pub(crate) use libc::SCHED_RR;
pub(crate) use libc::PTHREAD_EXPLICIT_SCHED;
pub(crate) use libc::PTHREAD_INHERIT_SCHED;
pub(crate) use libc::PTHREAD_CREATE_DETACHED;
pub(crate) use libc::PTHREAD_CREATE_JOINABLE;
pub(crate) use libc::pthread_mutex_t;
pub(crate) use libc::PTHREAD_MUTEX_INITIALIZER;
pub(crate) use libc::pthread_key_t;
pub(crate) use libc::sem_t;
} else if #[cfg(windows)] {
pub(crate) type pthread_t = isize;
#[repr(C)]
pub(crate) struct pthread_attr_t {
p_state: c_uint,
stack: *mut c_void,
s_size: usize,
param: sched_param,
}
#[repr(C)]
pub(crate) struct sched_param {
pub sched_priority: c_int,
}
pub(crate) const SCHED_OTHER: c_int = 0;
pub(crate) const SCHED_FIFO: c_int = 1;
pub(crate) const SCHED_RR: c_int = 2;
pub(crate) const PTHREAD_EXPLICIT_SCHED: c_int = 0;
pub(crate) const PTHREAD_INHERIT_SCHED: c_int = 0x08;
pub(crate) const PTHREAD_CREATE_JOINABLE: c_int = 0;
pub(crate) const PTHREAD_CREATE_DETACHED: c_int = 0x04;
pub(crate) type pthread_mutex_t = isize;
pub(crate) const PTHREAD_MUTEX_INITIALIZER: isize = -1;
pub(crate) type pthread_key_t = c_uint;
pub(crate) type sem_t = usize;
}
}
pub(crate) use ffi::c_char;
pub(crate) use ffi::c_int;
pub(crate) use ffi::c_uint;
pub(crate) use ffi::c_void;
#[cfg_attr(unix, link(name = "pthread"))]
#[cfg_attr(windows, link(name = "winpthread-1"))]
extern "C" {
pub(crate) fn pthread_create(
ptid: *mut pthread_t,
attr: *const pthread_attr_t,
start_routine: extern "C" fn(_: *mut c_void) -> *mut c_void,
arg: *mut c_void,
) -> c_int;
pub(crate) fn pthread_self() -> pthread_t;
pub(crate) fn pthread_join(tid: pthread_t, retval: *mut *mut c_void) -> c_int;
pub(crate) fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int;
pub(crate) fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> c_int;
pub(crate) fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, state: c_int) -> c_int;
pub(crate) fn pthread_attr_getdetachstate(
attr: *const pthread_attr_t,
state: *mut c_int,
) -> c_int;
pub(crate) fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, sched: c_int) -> c_int;
pub(crate) fn pthread_attr_getinheritsched(
attr: *const pthread_attr_t,
sched: *mut c_int,
) -> c_int;
pub(crate) fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, policy: c_int) -> c_int;
pub(crate) fn pthread_attr_getschedpolicy(
attr: *const pthread_attr_t,
policy: *mut c_int,
) -> c_int;
pub(crate) fn pthread_attr_setschedparam(
attr: *mut pthread_attr_t,
param: *const sched_param,
) -> c_int;
pub(crate) fn pthread_attr_getschedparam(
attr: *const pthread_attr_t,
policy: *mut sched_param,
) -> c_int;
pub(crate) fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, stacksize: usize) -> c_int;
pub(crate) fn pthread_attr_getstacksize(
attr: *const pthread_attr_t,
stacksize: *mut usize,
) -> c_int;
pub(crate) fn pthread_getname_np(thread: pthread_t, name: *mut c_char, len: usize) -> c_int;
pub(crate) fn pthread_setname_np(thread: pthread_t, name: *const c_char) -> c_int;
pub(crate) fn sem_init(sem: *mut sem_t, pshared: c_int, init_value: c_uint) -> c_int;
pub(crate) fn sem_destroy(sem: *mut sem_t) -> c_int;
pub(crate) fn sem_post(sem: *mut sem_t) -> c_int;
pub(crate) fn sem_wait(sem: *mut sem_t) -> c_int;
pub(crate) fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int;
pub(crate) fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int;
pub(crate) fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int;
pub(crate) fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int;
pub(crate) fn pthread_key_create(
key: *mut pthread_key_t,
dtor: Option<unsafe extern "C" fn(_: *const c_void)>,
) -> c_int;
pub(crate) fn pthread_key_delete(key: pthread_key_t) -> c_int;
pub(crate) fn pthread_setspecific(key: pthread_key_t, data: *const c_void) -> c_int;
pub(crate) fn pthread_getspecific(key: pthread_key_t) -> *const c_void;
}
cfg_if::cfg_if! {
if #[cfg(unix)] {
pub(crate) use libc::cpu_set_t;
pub(crate) use libc::sched_setaffinity;
pub(crate) use libc::sched_getaffinity;
pub(crate) use libc::CPU_SET;
pub(crate) use libc::CPU_ISSET;
pub(crate) use libc::CPU_COUNT;
pub(crate) use libc::CPU_ZERO;
pub(crate) use libc::getpid;
} else if #[cfg(windows)] {
pub(crate) type cpu_set_t = DWORD_PTR;
pub(crate) type pid_t = HANDLE;
pub(crate) unsafe fn CPU_ZERO(cpuset: &mut cpu_set_t) {
*cpuset = 0;
}
pub(crate) unsafe fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) {
*cpuset |= 0x01 << cpu;
}
pub(crate) unsafe fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool {
((*cpuset) & (0x01 << cpu)) > 0
}
pub(crate) unsafe fn CPU_COUNT(cpuset: &cpu_set_t) -> usize {
let mut cpuset = *cpuset;
let mut cnt = 0;
while cpuset > 0 {
if (cpuset & 1) > 0 {
cnt += 1;
}
cpuset >>= 1;
}
cnt
}
pub(crate) unsafe fn getpid() -> pid_t {
GetCurrentProcess()
}
pub(crate) unsafe fn sched_getaffinity(pid: pid_t, _cpusetsize: usize, cpuset: &mut cpu_set_t) -> c_int {
let mut sysmask: DWORD_PTR = 0;
let ret = unsafe { GetProcessAffinityMask(pid, cpuset, &mut sysmask) };
if ret > 0 {
0
} else {
-1
}
}
pub(crate) unsafe fn sched_setaffinity(pid: pid_t, _cpusetsize: usize, cpuset: &cpu_set_t) -> c_int {
let ret = if pid == 0 {
SetThreadAffinityMask(GetCurrentThread(), *cpuset) > 0
} else {
SetProcessAffinityMask(pid, *cpuset) > 0
};
if ret {
0
} else {
-1
}
}
type HANDLE = usize;
type DWORD_PTR = ffi::c_ulong;
type BOOL = ffi::c_int;
#[link(name = "kernel32")]
extern "C" {
fn GetCurrentProcess() -> HANDLE;
fn GetProcessAffinityMask(hProcess: HANDLE, procmask: *mut DWORD_PTR, sysmask: *mut DWORD_PTR) -> BOOL;
fn GetCurrentThread() -> HANDLE;
fn SetThreadAffinityMask(hThread: HANDLE, mask: DWORD_PTR) -> DWORD_PTR;
fn SetProcessAffinityMask(hProcess: HANDLE, mask: DWORD_PTR) -> BOOL;
}
}
}