Skip to content
Open
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
15 changes: 14 additions & 1 deletion general/echo/kmdf/driver/DriverSync/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ use crate::{
WDF_REQUEST_CONTEXT_TYPE_INFO,
};

/// Number of 100-nanosecond intervals in one millisecond. WDF relative times
/// are expressed in 100-nanosecond units, so this converts a millisecond delay
/// into the units WDF expects.
const RELATIVE_100_NS_INTERVALS_PER_MS: i64 = 10_000;

/// Delay, in milliseconds, before the periodic timer first fires once the
/// device has started.
const START_TIMER_DUE_TIME_MS: i64 = 100;

/// 100ms relative time (in 100-nanosecond units). The negative sign marks the
/// value as a relative (rather than absolute) timeout.
const WDF_REL_TIMEOUT_IN_MS: i64 = -START_TIMER_DUE_TIME_MS * RELATIVE_100_NS_INTERVALS_PER_MS;

/// Worker routine called to create a device and its software resources.
///
/// # Arguments:
Expand Down Expand Up @@ -162,7 +175,7 @@ extern "C" fn echo_evt_device_self_managed_io_start(device: WDFDEVICE) -> NTSTAT
// into low power state.
unsafe { call_unsafe_wdf_function_binding!(WdfIoQueueStart, queue) };

let due_time: i64 = -(100) * (10000);
let due_time: i64 = WDF_REL_TIMEOUT_IN_MS;

let _ = unsafe { (*queue_context).timer.start(due_time) };

Expand Down
10 changes: 8 additions & 2 deletions general/echo/kmdf/driver/DriverSync/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,15 @@ fn echo_print_driver_version() -> NTSTATUS {
call_unsafe_wdf_function_binding!(WdfDriverIsVersionAvailable, driver, &raw mut ver)
} > 0
{
println!("Yes, framework version is 1.0");
println!(
"Yes, framework version is {}.{}",
ver.MajorVersion, ver.MinorVersion
);
} else {
println!("No, framework version is not 1.0");
println!(
"No, framework version is not {}.{}",
ver.MajorVersion, ver.MinorVersion
);
}

STATUS_SUCCESS
Expand Down
42 changes: 32 additions & 10 deletions general/echo/kmdf/driver/DriverSync/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,33 @@ use crate::{
WDF_TIMER_CONFIG_SIZE,
};

/// Set max write length for testing
const MAX_WRITE_LENGTH: usize = 1024 * 40;
/// Number of bytes in one kilobyte.
const BYTES_PER_KB: usize = 1024;

/// Set timer period in ms
const TIMER_PERIOD: u32 = 1000 * 10;
/// Max write length, in bytes, for testing
const MAX_WRITE_LENGTH: usize = 40 * BYTES_PER_KB;

/// Number of milliseconds in one second.
const MS_PER_SECOND: u32 = 1000;

/// Watchdog timer period, in seconds.
const TIMER_PERIOD_SECONDS: u32 = 10;

/// Timer period in ms
const TIMER_PERIOD: u32 = TIMER_PERIOD_SECONDS * MS_PER_SECOND;

/// Non-zero char literal (of one to four chars) for pool tag used in
/// `ExAllocatePool2`
const MEMORY_TAG: u32 = u32::from_be_bytes(*b"sam1");

/// Initial cancel/completion ownership count assigned to a new request. A
/// claimant takes ownership by decrementing the count down to zero.
const INITIAL_CANCEL_OWNERSHIP_COUNT: i32 = 1;

/// Total ownership count held by the timer DPC once it has claimed completion
/// of a request: the initial count plus the single increment it acquired via
/// `echo_increment_request_cancel_ownership_count`.
const TIMER_CLAIMED_OWNERSHIP_COUNT: i32 = INITIAL_CANCEL_OWNERSHIP_COUNT + 1;

/// This routine will interlock increment a value only if the current value
/// is greater then the floor value.
Expand Down Expand Up @@ -356,7 +378,8 @@ fn echo_set_current_request(request: WDFREQUEST, queue: WDFQUEUE) {
// they will interlock decrement the count. When the count reaches zero,
// ownership has been acquired and the caller may complete the request.
unsafe {
(*request_context).cancel_completion_ownership_count = AtomicI32::new(1);
(*request_context).cancel_completion_ownership_count =
AtomicI32::new(INITIAL_CANCEL_OWNERSHIP_COUNT);
}

// Defer the completion to another thread from the timer dpc
Expand Down Expand Up @@ -564,9 +587,8 @@ extern "C" fn echo_evt_io_write(queue: WDFQUEUE, request: WDFREQUEST, length: us
(*queue_context).length = 0;
}

// FIXME: Memory Tag
(*queue_context).buffer =
ExAllocatePool2(POOL_FLAG_NON_PAGED, length as SIZE_T, 's' as u32);
ExAllocatePool2(POOL_FLAG_NON_PAGED, length as SIZE_T, MEMORY_TAG);
if (*queue_context).buffer.is_null() {
println!(
"echo_evt_io_write Could not allocate {:?} byte buffer",
Expand Down Expand Up @@ -697,12 +719,12 @@ unsafe extern "C" fn echo_evt_timer_func(timer: WDFTIMER) {
// currently racing with it), there is no need to use an interlocked
// decrement to lower the cancel ownership count.

// 2 is the initial count we set when we initialized
// CancelCompletionOwnershipCount plus the call to
// TIMER_CLAIMED_OWNERSHIP_COUNT is the initial count we set when we
// initialized CancelCompletionOwnershipCount plus the call to
// EchoIncrementRequestCancelOwnershipCount()
(*request_context)
.cancel_completion_ownership_count
.fetch_sub(2, Ordering::SeqCst);
.fetch_sub(TIMER_CLAIMED_OWNERSHIP_COUNT, Ordering::SeqCst);
complete_request = true;
}
}
Expand Down
21 changes: 18 additions & 3 deletions general/echo/kmdf/exe/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ static READER_TYPE: u32 = 1;
static WRITER_TYPE: u32 = 2;
static NUM_ASYNCH_IO: usize = 100;
static BUFFER_SIZE: usize = 40 * 1024;
/// Transfer length, in bytes, for the first synchronous write/read test.
static SYNC_TEST_SMALL_LENGTH: u32 = 512;
/// Transfer length, in bytes, for the second synchronous write/read test.
static SYNC_TEST_LARGE_LENGTH: u32 = 30 * 1024;
/// Completion key associated with the device handle on the I/O completion port.
static COMPLETION_PORT_KEY: usize = 1;
/// Number of concurrent threads allowed to run for the I/O completion port.
/// Zero lets the system allow as many concurrent threads as there are
/// processors.
static COMPLETION_PORT_CONCURRENT_THREADS: u32 = 0;

fn main() -> Result<(), Box<dyn Error>> {
let argument_vector: Vec<String> = env::args().collect();
Expand Down Expand Up @@ -155,9 +165,9 @@ Exit the app anytime by pressing Ctrl-C

h.join().unwrap().unwrap();
} else {
perform_write_read_test(h_device, 512)?;
perform_write_read_test(h_device, SYNC_TEST_SMALL_LENGTH)?;

perform_write_read_test(h_device, 30 * 1024)?;
perform_write_read_test(h_device, SYNC_TEST_LARGE_LENGTH)?;
}

Ok(())
Expand Down Expand Up @@ -334,7 +344,12 @@ fn async_io_work(io_type: u32) -> Result<(), Box<dyn Error>> {
// Call Win32 API FFI CreateIoCompletionPort to get handle for completing async
// requests
unsafe {
h_completion_port = CreateIoCompletionPort(h_device, std::ptr::null_mut(), 1, 0);
h_completion_port = CreateIoCompletionPort(
h_device,
std::ptr::null_mut(),
COMPLETION_PORT_KEY,
COMPLETION_PORT_CONCURRENT_THREADS,
);
}

if h_completion_port.is_null() {
Expand Down
Loading