|
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