Skip to content

feat!: reimplement some C macros and inline functions #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 3 additions & 17 deletions examples/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ngx::core;
use ngx::ffi::{
ngx_array_push, ngx_command_t, ngx_conf_t, ngx_cycle, ngx_event_t, ngx_http_core_module, ngx_http_core_run_phases,
ngx_http_handler_pt, ngx_http_module_t, ngx_http_phases_NGX_HTTP_ACCESS_PHASE, ngx_http_request_t, ngx_int_t,
ngx_module_t, ngx_posted_events, ngx_queue_s, ngx_str_t, ngx_uint_t, NGX_CONF_TAKE1, NGX_HTTP_LOC_CONF,
ngx_module_t, ngx_post_event, ngx_posted_events, ngx_str_t, ngx_uint_t, NGX_CONF_TAKE1, NGX_HTTP_LOC_CONF,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_MODULE,
};
use ngx::http::{self, HTTPModule, MergeConfigError};
Expand Down Expand Up @@ -112,7 +112,7 @@ unsafe extern "C" fn check_async_work_done(event: *mut ngx_event_t) {
// this doesn't have have good performance but works as a simple thread-safe example and doesn't causes
// segfault. The best method that provides both thread-safety and performance requires
// an nginx patch.
post_event(event, addr_of_mut!(ngx_posted_events));
ngx_post_event(event, addr_of_mut!(ngx_posted_events));
}
}

Expand All @@ -128,20 +128,6 @@ struct EventData {
unsafe impl Send for EventData {}
unsafe impl Sync for EventData {}

// same as ngx_post_event
// source: https://github.com/nginx/ngx-rust/pull/31/files#diff-132330bb775bed17fb9990ec2b56e6c52e6a9e56d62f2114fade95e4decdba08R80-R90
unsafe fn post_event(event: *mut ngx_event_t, queue: *mut ngx_queue_s) {
let event = &mut (*event);
if event.posted() == 0 {
event.set_posted(1);
// translated from ngx_queue_insert_tail macro
event.queue.prev = (*queue).prev;
(*event.queue.prev).next = &event.queue as *const _ as *mut _;
event.queue.next = queue;
(*queue).prev = &event.queue as *const _ as *mut _;
}
}

http_request_handler!(async_access_handler, |request: &mut http::Request| {
let co = unsafe { request.get_module_loc_conf::<ModuleConfig>(&*addr_of!(ngx_http_async_module)) };
let co = co.expect("module config is none");
Expand Down Expand Up @@ -184,7 +170,7 @@ http_request_handler!(async_access_handler, |request: &mut http::Request| {
event.data = Arc::into_raw(event_data.clone()) as _;
event.log = (*ngx_cycle).log;

post_event(event, addr_of_mut!(ngx_posted_events));
ngx_post_event(event, addr_of_mut!(ngx_posted_events));
}

ngx_log_debug_http!(request, "async module enabled: {}", co.enable);
Expand Down
83 changes: 83 additions & 0 deletions nginx-sys/src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use core::ptr;

use crate::{
ngx_current_msec, ngx_event_t, ngx_event_timer_rbtree, ngx_msec_t, ngx_queue_insert_before, ngx_queue_remove,
ngx_queue_t, ngx_rbtree_delete, ngx_rbtree_insert, NGX_TIMER_LAZY_DELAY,
};

/// Sets a timeout for an event.
///
/// # Safety
///
///`ev` must be a valid pointer to an `ngx_event_t`.
#[inline]
pub unsafe fn ngx_add_timer(ev: *mut ngx_event_t, timer: ngx_msec_t) {
let key: ngx_msec_t = ngx_current_msec.wrapping_add(timer);

if (*ev).timer_set() != 0 {
/*
* Use a previous timer value if difference between it and a new
* value is less than NGX_TIMER_LAZY_DELAY milliseconds: this allows
* to minimize the rbtree operations for fast connections.
*/
if key.abs_diff((*ev).timer.key) < NGX_TIMER_LAZY_DELAY as _ {
return;
}

ngx_del_timer(ev);
}

(*ev).timer.key = key;

ngx_rbtree_insert(
ptr::addr_of_mut!(ngx_event_timer_rbtree),
ptr::addr_of_mut!((*ev).timer),
);

(*ev).set_timer_set(1);
}

/// Deletes a previously set timeout.
///
/// # Safety
///
/// `ev` must be a valid pointer to an `ngx_event_t`, previously armed with [ngx_add_timer].
#[inline]
pub unsafe fn ngx_del_timer(ev: *mut ngx_event_t) {
ngx_rbtree_delete(
ptr::addr_of_mut!(ngx_event_timer_rbtree),
ptr::addr_of_mut!((*ev).timer),
);

(*ev).timer.left = ptr::null_mut();
(*ev).timer.right = ptr::null_mut();
(*ev).timer.parent = ptr::null_mut();

(*ev).set_timer_set(0);
}

/// Post the event `ev` to the post queue `q`.
///
/// # Safety
///
/// `ev` must be a valid pointer to an `ngx_event_t`.
/// `q` is a valid pointer to a queue head.
#[inline]
pub unsafe fn ngx_post_event(ev: *mut ngx_event_t, q: *mut ngx_queue_t) {
if (*ev).posted() == 0 {
(*ev).set_posted(1);
ngx_queue_insert_before(q, ptr::addr_of_mut!((*ev).queue));
}
}

/// Deletes the event `ev` from the queue it's currently posted in.
///
/// # Safety
///
/// `ev` must be a valid pointer to an `ngx_event_t`.
/// `ev.queue` is initialized with `ngx_queue_init`.
#[inline]
pub unsafe fn ngx_delete_posted_event(ev: *mut ngx_event_t) {
(*ev).set_posted(0);
ngx_queue_remove(ptr::addr_of_mut!((*ev).queue));
}
6 changes: 6 additions & 0 deletions nginx-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#![warn(missing_docs)]
#![no_std]

mod event;
mod queue;

use core::fmt;
use core::mem::offset_of;
use core::ptr::{self, copy_nonoverlapping};
Expand All @@ -22,6 +25,9 @@ mod bindings {
#[doc(no_inline)]
pub use bindings::*;

pub use event::*;
pub use queue::*;

/// The offset of the `main_conf` field in the `ngx_http_conf_ctx_t` struct.
///
/// This is used to access the main configuration context for an HTTP module.
Expand Down
Loading
Loading