Module kernel::workqueue

source ·
Expand description

Work queues.

This file has two components: The raw work item API, and the safe work item API.

One pattern that is used in both APIs is the ID const generic, which exists to allow a single type to define multiple work_struct fields. This is done by choosing an id for each field, and using that id to specify which field you wish to use. (The actual value doesn’t matter, as long as you use different values for different fields of the same struct.) Since these IDs are generic, they are used only at compile-time, so they shouldn’t exist in the final binary.

The raw API

The raw API consists of the RawWorkItem trait, where the work item needs to provide an arbitrary function that knows how to enqueue the work item. It should usually not be used directly, but if you want to, you can use it without using the pieces from the safe API.

The safe API

The safe API is used via the Work struct and WorkItem traits. Furthermore, it also includes a trait called WorkItemPointer, which is usually not used directly by the user.

  • The Work struct is the Rust wrapper for the C work_struct type.
  • The WorkItem trait is implemented for structs that can be enqueued to a workqueue.
  • The WorkItemPointer trait is implemented for the pointer type that points at a something that implements WorkItem.

Example

This example defines a struct that holds an integer and can be scheduled on the workqueue. When the struct is executed, it will print the integer. Since there is only one work_struct field, we do not need to specify ids for the fields.

use kernel::prelude::*;
use kernel::sync::Arc;
use kernel::workqueue::{self, Work, WorkItem};
use kernel::{impl_has_work, new_work};

#[pin_data]
struct MyStruct {
    value: i32,
    #[pin]
    work: Work<MyStruct>,
}

impl_has_work! {
    impl HasWork<Self> for MyStruct { self.work }
}

impl MyStruct {
    fn new(value: i32) -> Result<Arc<Self>> {
        Arc::pin_init(pin_init!(MyStruct {
            value,
            work <- new_work!("MyStruct::work"),
        }))
    }
}

impl WorkItem for MyStruct {
    type Pointer = Arc<MyStruct>;

    fn run(this: Arc<MyStruct>) {
        pr_info!("The value is: {}", this.value);
    }
}

/// This method will enqueue the struct for execution on the system workqueue, where its value
/// will be printed.
fn print_later(val: Arc<MyStruct>) {
    let _ = workqueue::system().enqueue(val);
}

The following example shows how multiple work_struct fields can be used:

use kernel::prelude::*;
use kernel::sync::Arc;
use kernel::workqueue::{self, Work, WorkItem};
use kernel::{impl_has_work, new_work};

#[pin_data]
struct MyStruct {
    value_1: i32,
    value_2: i32,
    #[pin]
    work_1: Work<MyStruct, 1>,
    #[pin]
    work_2: Work<MyStruct, 2>,
}

impl_has_work! {
    impl HasWork<Self, 1> for MyStruct { self.work_1 }
    impl HasWork<Self, 2> for MyStruct { self.work_2 }
}

impl MyStruct {
    fn new(value_1: i32, value_2: i32) -> Result<Arc<Self>> {
        Arc::pin_init(pin_init!(MyStruct {
            value_1,
            value_2,
            work_1 <- new_work!("MyStruct::work_1"),
            work_2 <- new_work!("MyStruct::work_2"),
        }))
    }
}

impl WorkItem<1> for MyStruct {
    type Pointer = Arc<MyStruct>;

    fn run(this: Arc<MyStruct>) {
        pr_info!("The value is: {}", this.value_1);
    }
}

impl WorkItem<2> for MyStruct {
    type Pointer = Arc<MyStruct>;

    fn run(this: Arc<MyStruct>) {
        pr_info!("The second value is: {}", this.value_2);
    }
}

fn print_1_later(val: Arc<MyStruct>) {
    let _ = workqueue::system().enqueue::<Arc<MyStruct>, 1>(val);
}

fn print_2_later(val: Arc<MyStruct>) {
    let _ = workqueue::system().enqueue::<Arc<MyStruct>, 2>(val);
}

C header: include/linux/workqueue.h

Structs

  • A kernel work queue.
  • Links for a work item.

Traits

Functions

  • Returns the system work queue (system_wq).
  • Returns the system freezable work queue (system_freezable_wq).
  • Returns the system freezable power-efficient work queue (system_freezable_power_efficient_wq).
  • Returns the system high-priority work queue (system_highpri_wq).
  • Returns the system work queue for potentially long-running work items (system_long_wq).
  • Returns the system power-efficient work queue (system_power_efficient_wq).
  • Returns the system unbound work queue (system_unbound_wq).