|
3 | 3 |
|
4 | 4 | use libc; |
5 | 5 | use {Errno, Error, Result}; |
6 | | -use std::fmt; |
7 | | -use std::fmt::Debug; |
8 | 6 | use std::mem; |
9 | 7 | #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] |
10 | 8 | use std::os::unix::io::RawFd; |
11 | 9 | use std::ptr; |
12 | 10 |
|
| 11 | +#[cfg(not(target_os = "openbsd"))] |
| 12 | +pub use self::sigevent::*; |
| 13 | + |
13 | 14 | // Currently there is only one definition of c_int in libc, as well as only one |
14 | 15 | // type for signal constants. |
15 | 16 | // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately |
@@ -488,102 +489,114 @@ pub enum SigevNotify { |
488 | 489 | si_value: libc::intptr_t }, |
489 | 490 | } |
490 | 491 |
|
491 | | -/// Used to request asynchronous notification of the completion of certain |
492 | | -/// events, such as POSIX AIO and timers. |
493 | | -#[repr(C)] |
494 | | -pub struct SigEvent { |
495 | | - sigevent: libc::sigevent |
496 | | -} |
| 492 | +#[cfg(not(target_os = "openbsd"))] |
| 493 | +mod sigevent { |
| 494 | + use libc; |
| 495 | + use std::mem; |
| 496 | + use std::ptr; |
| 497 | + use std::fmt::{self, Debug}; |
| 498 | + use super::SigevNotify; |
| 499 | + #[cfg(any(target_os = "freebsd", target_os = "linux"))] |
| 500 | + use super::type_of_thread_id; |
| 501 | + |
| 502 | + /// Used to request asynchronous notification of the completion of certain |
| 503 | + /// events, such as POSIX AIO and timers. |
| 504 | + #[repr(C)] |
| 505 | + pub struct SigEvent { |
| 506 | + sigevent: libc::sigevent |
| 507 | + } |
| 508 | + |
| 509 | + impl SigEvent { |
| 510 | + /// **Note:** this constructor does not allow the user to set the |
| 511 | + /// `sigev_notify_kevent_flags` field. That's considered ok because on FreeBSD |
| 512 | + /// at least those flags don't do anything useful. That field is part of a |
| 513 | + /// union that shares space with the more genuinely useful fields. |
| 514 | + /// |
| 515 | + /// **Note:** This constructor also doesn't allow the caller to set the |
| 516 | + /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are |
| 517 | + /// required for `SIGEV_THREAD`. That's considered ok because on no operating |
| 518 | + /// system is `SIGEV_THREAD` the most efficient way to deliver AIO |
| 519 | + /// notification. FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`. |
| 520 | + /// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or |
| 521 | + /// `SIGEV_SIGNAL`. That field is part of a union that shares space with the |
| 522 | + /// more genuinely useful `sigev_notify_thread_id` |
| 523 | + pub fn new(sigev_notify: SigevNotify) -> SigEvent { |
| 524 | + let mut sev = unsafe { mem::zeroed::<libc::sigevent>()}; |
| 525 | + sev.sigev_notify = match sigev_notify { |
| 526 | + SigevNotify::SigevNone => libc::SIGEV_NONE, |
| 527 | + SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL, |
| 528 | + #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] |
| 529 | + SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT, |
| 530 | + #[cfg(target_os = "freebsd")] |
| 531 | + SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, |
| 532 | + #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))] |
| 533 | + SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, |
| 534 | + #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))] |
| 535 | + SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined |
| 536 | + }; |
| 537 | + sev.sigev_signo = match sigev_notify { |
| 538 | + SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int, |
| 539 | + #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] |
| 540 | + SigevNotify::SigevKevent{ kq, ..} => kq, |
| 541 | + #[cfg(any(target_os = "linux", target_os = "freebsd"))] |
| 542 | + SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int, |
| 543 | + _ => 0 |
| 544 | + }; |
| 545 | + sev.sigev_value.sival_ptr = match sigev_notify { |
| 546 | + SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(), |
| 547 | + SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void, |
| 548 | + #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] |
| 549 | + SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void, |
| 550 | + #[cfg(any(target_os = "freebsd", target_os = "linux"))] |
| 551 | + SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void, |
| 552 | + }; |
| 553 | + SigEvent::set_tid(&mut sev, &sigev_notify); |
| 554 | + SigEvent{sigevent: sev} |
| 555 | + } |
497 | 556 |
|
498 | | -impl SigEvent { |
499 | | - // Note: this constructor does not allow the user to set the |
500 | | - // sigev_notify_kevent_flags field. That's considered ok because on FreeBSD |
501 | | - // at least those flags don't do anything useful. That field is part of a |
502 | | - // union that shares space with the more genuinely useful |
503 | | - // Note: This constructor also doesn't allow the caller to set the |
504 | | - // sigev_notify_function or sigev_notify_attributes fields, which are |
505 | | - // required for SIGEV_THREAD. That's considered ok because on no operating |
506 | | - // system is SIGEV_THREAD the most efficient way to deliver AIO |
507 | | - // notification. FreeBSD and Dragonfly programs should prefer SIGEV_KEVENT. |
508 | | - // Linux, Solaris, and portable programs should prefer SIGEV_THREAD_ID or |
509 | | - // SIGEV_SIGNAL. That field is part of a union that shares space with the |
510 | | - // more genuinely useful sigev_notify_thread_id |
511 | | - pub fn new(sigev_notify: SigevNotify) -> SigEvent { |
512 | | - let mut sev = unsafe { mem::zeroed::<libc::sigevent>()}; |
513 | | - sev.sigev_notify = match sigev_notify { |
514 | | - SigevNotify::SigevNone => libc::SIGEV_NONE, |
515 | | - SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL, |
516 | | - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] |
517 | | - SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT, |
518 | | - #[cfg(target_os = "freebsd")] |
519 | | - SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, |
520 | | - #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))] |
521 | | - SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, |
522 | | - #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))] |
523 | | - SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined |
524 | | - }; |
525 | | - sev.sigev_signo = match sigev_notify { |
526 | | - SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int, |
527 | | - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] |
528 | | - SigevNotify::SigevKevent{ kq, ..} => kq, |
529 | | - #[cfg(any(target_os = "linux", target_os = "freebsd"))] |
530 | | - SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int, |
531 | | - _ => 0 |
532 | | - }; |
533 | | - sev.sigev_value.sival_ptr = match sigev_notify { |
534 | | - SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(), |
535 | | - SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void, |
536 | | - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] |
537 | | - SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void, |
538 | | - #[cfg(any(target_os = "linux", target_os = "freebsd"))] |
539 | | - SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void, |
540 | | - }; |
541 | | - SigEvent::set_tid(&mut sev, &sigev_notify); |
542 | | - SigEvent{sigevent: sev} |
543 | | - } |
| 557 | + #[cfg(any(target_os = "freebsd", target_os = "linux"))] |
| 558 | + fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) { |
| 559 | + sev.sigev_notify_thread_id = match sigev_notify { |
| 560 | + &SigevNotify::SigevThreadId { thread_id, .. } => thread_id, |
| 561 | + _ => 0 as type_of_thread_id |
| 562 | + }; |
| 563 | + } |
544 | 564 |
|
545 | | - #[cfg(any(target_os = "linux", target_os = "freebsd"))] |
546 | | - fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) { |
547 | | - sev.sigev_notify_thread_id = match sigev_notify { |
548 | | - &SigevNotify::SigevThreadId { thread_id, .. } => thread_id, |
549 | | - _ => 0 as type_of_thread_id |
550 | | - }; |
551 | | - } |
| 565 | + #[cfg(not(any(target_os = "freebsd", target_os = "linux")))] |
| 566 | + fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) { |
| 567 | + } |
552 | 568 |
|
553 | | - #[cfg(not(any(target_os = "freebsd", target_os = "linux")))] |
554 | | - fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) { |
| 569 | + pub fn sigevent(&self) -> libc::sigevent { |
| 570 | + self.sigevent |
| 571 | + } |
555 | 572 | } |
556 | 573 |
|
557 | | - pub fn sigevent(&self) -> libc::sigevent { |
558 | | - self.sigevent |
559 | | - } |
560 | | -} |
| 574 | + impl Debug for SigEvent { |
| 575 | + #[cfg(any(target_os = "freebsd", target_os = "linux"))] |
| 576 | + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
| 577 | + fmt.debug_struct("SigEvent") |
| 578 | + .field("sigev_notify", &self.sigevent.sigev_notify) |
| 579 | + .field("sigev_signo", &self.sigevent.sigev_signo) |
| 580 | + .field("sigev_value", &self.sigevent.sigev_value.sival_ptr) |
| 581 | + .field("sigev_notify_thread_id", |
| 582 | + &self.sigevent.sigev_notify_thread_id) |
| 583 | + .finish() |
| 584 | + } |
561 | 585 |
|
562 | | -impl Debug for SigEvent { |
563 | | - #[cfg(any(target_os = "linux", target_os = "freebsd"))] |
564 | | - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
565 | | - fmt.debug_struct("SigEvent") |
566 | | - .field("sigev_notify", &self.sigevent.sigev_notify) |
567 | | - .field("sigev_signo", &self.sigevent.sigev_signo) |
568 | | - .field("sigev_value", &self.sigevent.sigev_value.sival_ptr) |
569 | | - .field("sigev_notify_thread_id", |
570 | | - &self.sigevent.sigev_notify_thread_id) |
571 | | - .finish() |
572 | | - } |
573 | | - |
574 | | - #[cfg(not(any(target_os = "linux", target_os = "freebsd")))] |
575 | | - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
576 | | - fmt.debug_struct("SigEvent") |
577 | | - .field("sigev_notify", &self.sigevent.sigev_notify) |
578 | | - .field("sigev_signo", &self.sigevent.sigev_signo) |
579 | | - .field("sigev_value", &self.sigevent.sigev_value.sival_ptr) |
580 | | - .finish() |
| 586 | + #[cfg(not(any(target_os = "freebsd", target_os = "linux")))] |
| 587 | + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
| 588 | + fmt.debug_struct("SigEvent") |
| 589 | + .field("sigev_notify", &self.sigevent.sigev_notify) |
| 590 | + .field("sigev_signo", &self.sigevent.sigev_signo) |
| 591 | + .field("sigev_value", &self.sigevent.sigev_value.sival_ptr) |
| 592 | + .finish() |
| 593 | + } |
581 | 594 | } |
582 | | -} |
583 | 595 |
|
584 | | -impl<'a> From<&'a libc::sigevent> for SigEvent { |
585 | | - fn from(sigevent: &libc::sigevent) -> Self { |
586 | | - SigEvent{ sigevent: sigevent.clone() } |
| 596 | + impl<'a> From<&'a libc::sigevent> for SigEvent { |
| 597 | + fn from(sigevent: &libc::sigevent) -> Self { |
| 598 | + SigEvent{ sigevent: sigevent.clone() } |
| 599 | + } |
587 | 600 | } |
588 | 601 | } |
589 | 602 |
|
|
0 commit comments