hipthread 0.1.3

no-std thread library based on pthread
Documentation
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_mutexattr_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)] {
        /// 如果是***-windows-msvc, 拷贝libwinpthread-1.dll到运行环境也可以使用.
        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) type pthread_mutexattr_t = c_uint;
        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_init( mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_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::pid_t;
        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
            }
        }

        // windows下根据当前使用情况的想特定实现, 如果pid == 0, 则代表当前线程, 否则设置进程的亲和性
        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;
        }
    }
}