Module 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::sync::Arc;
use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};

#[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"),
        }), GFP_KERNEL)
    }
}

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

    fn run(this: Arc<MyStruct>) {
        pr_info!("The value is: {}\n", 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::sync::Arc;
use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};

#[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"),
        }), GFP_KERNEL)
    }
}

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

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

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

    fn run(this: Arc<MyStruct>) {
        pr_info!("The second value is: {}\n", 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

Macros§

impl_has_work
Used to safely implement the HasWork<T, ID> trait.
new_work
Creates a Work initialiser with the given name and a newly-created lock class.

Structs§

Queue
A kernel work queue.
Work
Links for a work item.

Traits§

HasWork
Declares that a type has a Work<T, ID> field.
RawWorkItem
A raw work item.
WorkItem
Defines the method that should be called when this work item is executed.
WorkItemPointer
Defines the method that should be called directly when a work item is executed.

Functions§

system
Returns the system work queue (system_wq).
system_bh
Returns the system bottom halves work queue (system_bh_wq).
system_bh_highpri
Returns the system bottom halves high-priority work queue (system_bh_highpri_wq).
system_freezable
Returns the system freezable work queue (system_freezable_wq).
system_freezable_power_efficient
Returns the system freezable power-efficient work queue (system_freezable_power_efficient_wq).
system_highpri
Returns the system high-priority work queue (system_highpri_wq).
system_long
Returns the system work queue for potentially long-running work items (system_long_wq).
system_power_efficient
Returns the system power-efficient work queue (system_power_efficient_wq).
system_unbound
Returns the system unbound work queue (system_unbound_wq).