|
1 | 1 | //! Low level threading primitives
|
2 | 2 |
|
| 3 | +use std::convert::From; |
| 4 | + |
| 5 | +use libc::{self, pthread_t}; |
| 6 | + |
3 | 7 | #[cfg(not(target_os = "redox"))]
|
4 | 8 | use crate::errno::Errno;
|
5 | 9 | #[cfg(not(target_os = "redox"))]
|
6 | 10 | use crate::Result;
|
7 |
| -use libc::{self, pthread_t}; |
8 | 11 |
|
9 | 12 | /// Identifies an individual thread.
|
10 | 13 | pub type Pthread = pthread_t;
|
@@ -39,4 +42,55 @@ pub fn pthread_kill<T>(thread: Pthread, signal: T) -> Result<()>
|
39 | 42 | let res = unsafe { libc::pthread_kill(thread, sig) };
|
40 | 43 | Errno::result(res).map(drop)
|
41 | 44 | }
|
| 45 | + |
| 46 | +/// Value to pass with a signal. Can be either integer or pointer. |
| 47 | +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| 48 | +pub enum SigVal { |
| 49 | + /// Use this variant to pass a integer to the sigval union |
| 50 | + Int(libc::c_int), |
| 51 | + /// Use this variant to pass a pointer to the sigval union |
| 52 | + Ptr(*mut libc::c_void), |
| 53 | +} |
| 54 | + |
| 55 | +// Because of macro/trait machinery in libc, libc doesn't provide this union. |
| 56 | +// Only used to ensure that union type conversion is done exactly as C would. |
| 57 | +#[repr(C)] |
| 58 | +union sigval_union { |
| 59 | + ptr: *mut libc::c_void, |
| 60 | + int: libc::c_int, |
| 61 | +} |
| 62 | + |
| 63 | +impl From<SigVal> for libc::sigval { |
| 64 | + fn from(sigval: SigVal) -> Self { |
| 65 | + match sigval { |
| 66 | + SigVal::Int(int) => { |
| 67 | + let as_ptr = unsafe { sigval_union { int }.ptr }; |
| 68 | + libc::sigval { sival_ptr: as_ptr } |
| 69 | + } |
| 70 | + SigVal::Ptr(ptr) => { |
| 71 | + libc::sigval { sival_ptr: ptr } |
| 72 | + } |
| 73 | + } |
| 74 | + } |
| 75 | +} |
| 76 | + |
| 77 | +/// Queue a signal and data to a thread (see [`pthread_sigqueue(3)`]). |
| 78 | +/// |
| 79 | +/// If `signal` is `None`, `pthread_sigqueue` will only preform error checking and |
| 80 | +/// won't send any signal. |
| 81 | +/// |
| 82 | +/// `pthread_sigqueue` is a GNU extension and is not available on other libcs |
| 83 | +/// |
| 84 | +/// [`pthread_sigqueue(3)`]: https://man7.org/linux/man-pages/man3/pthread_sigqueue.3.html |
| 85 | +#[cfg(all(any(target_os = "linux", target_os = "android"), target_env = "gnu"))] |
| 86 | +pub fn pthread_sigqueue<T>(thread: Pthread, signal: T, sigval: SigVal) -> Result<()> |
| 87 | + where T: Into<Option<crate::sys::signal::Signal>> |
| 88 | +{ |
| 89 | + let sig = match signal.into() { |
| 90 | + Some(s) => s as libc::c_int, |
| 91 | + None => 0, |
| 92 | + }; |
| 93 | + let res = unsafe { libc::pthread_sigqueue(thread, sig, sigval.into()) }; |
| 94 | + Errno::result(res).map(drop) |
| 95 | +} |
42 | 96 | }
|
0 commit comments