Is it valid to do the following
struct foo {
int data;
struct rb_node node
};
struct rb_root root;
/* Filling tree with kalloc'ed foo nodes */
struct rb_node *node=rb_first(&root);
while (node)
{
struct rb_node *next=rb_next(node);
kfree(node);
node = next;
}
root=RB_ROOT;
In fact, I just want do foreach and clear at same time with linear time.
Explored rb_next implementation. It returns parent before right children.
So, It is impossible to clear list this way.
Related
I'm wrapping a C library in Rust, and many of its functions take parameters by pointers to structs, which themselves often have pointers to other structs. In the interest of reducing overhead, I'd like to provide the ability to cache the results of marshaling the Rust data into the C structs.
Here's an example of how the C library might expect some parameters:
#[repr(C)]
struct Foo {
x: i32,
y: f32
}
#[repr(C)]
struct Bar {
p_foo: *const Foo,
z: bool
}
And how I'd imagine an owning, "cached" version would look:
struct Cached {
foo: Option<Foo>,
bar: Bar
}
The p_foo field of bar would be constructed to point to Some value within foo, or a null pointer if there was None.
The issue, here, of course, is that if a value of Cached was to be moved, a straight memcpy would be inappropriate and bar.p_foo would additionally need to be redirected. This would be easy to ensure in C++, with its definable move semantics, but does Rust offer a solution besides "don't set bar.p_foo until it's used"? While it would certainly work to do it that way, I don't imagine that these cached values will be moved more than (or even close to the frequency that) they are reused, and there is a bit of work involved to set up these pointers, especially if the nesting/chaining is deep/long. I'd also rather not Box the substructures up on the heap.
To clarify, here's what I can write in C++, which I would like to replicate in Rust:
struct Foo {
int x;
float y;
};
struct Bar {
Foo const*pFoo;
bool z;
};
// bear with me while I conjure up a Maybe for C++
class Cached {
public:
// would have appropriate copy constructor/assignment
Cached(Cached &&other) {
m_foo = other.m_foo;
m_bar = other.m_bar;
if(m_foo.isJust()) {
m_bar.pFoo = &m_foo.value();
} // else already nullptr
}
// similar move assignment
private:
Maybe<Foo> m_foo;
Bar m_bar;
};
The Rust-equivalent would be to not use raw pointers, as raw pointers are there for implementing our safe datastructures, not for implementing normal datastructures.
#[repr(C)]
struct Foo {
x: i32,
y: f32
}
#[repr(C)]
struct Bar {
p_foo: Option<Box<Foo>>,
z: bool
}
An Option<Box<T>> is guaranteed to be exactly equivalent (in bits in memory) to a *const T, as long as T is a type and not a trait. The only difference is that it's safe to use within Rust.
This way you don't even need a Cached struct anymore, but can directly pass around the Bar object.
I'd also rather not Box the substructures up on the heap.
Then I suggest you don't keep a Bar object around, and instead conjure it up whenever you need to pass one to C:
#[repr(C)]
struct Foo {
x: i32,
y: f32
}
#[repr(C)]
struct Bar<'a> {
p_foo: Option<&'a Foo>,
z: bool
}
struct Cached {
foo: Option<Foo>,
z: bool,
}
impl Cached {
fn bar<'a>(&'a self) -> Bar<'a> {
Bar {
p_foo: self.foo.as_ref(),
z: self.z,
}
}
}
there is a bit of work involved to set up these pointers, especially if the nesting/chaining is deep/long.
That sounds a lot like premature optimization. Don't optimize where you haven't benchmarked.
I need to use the kthread functions for a work processor and the distinction between the two is not very clear to me. This is my understanding of the fields.
struct kthread_worker {
spinlock_t lock; // lock to update the work queue
struct list_head work_list; // list kthread_work items
struct task_struct *task; // handle for thread
struct kthread_work *current_work; // ?
};
struct kthread_work {
struct list_head node; // list of threads?
kthread_work_func_t func; // func to execute?
struct kthread_worker *worker; // worker associated with this work item
};
My questions are:
Any clarification on the unclear fields.
kthread_work_func_t is a func ptr expecting an argument of kthread_work. How does that work? It should point to the function you want the thread to execute, right?
kthread_worker is a worker, which can execute works (kthread_work). Work can be added to worker at any time. Worker executes works one by one. If no work is currently available, worker waits.
kthread_work_func_t is a func ptr expecting an argument of kthread_work. How does that work? It should point to the function you want the thread to execute, right?
Yes, it is just function you want to execute as work.
If only one work uses this function(e.g., this is some sort of garbage collector), function may simply ignore its argument.
If you want to have several works, which uses same functionality but with different parameters, you may embed kthread_work structure into your structure, which contain these parameters:
struct my_work
{
struct kthread_work work; //Base work object
int i; // Your parameter
}
// Parametrized work function
void my_func(struct kthread_work* work)
{
// Extract actual work object
struct my_work* my_work = container_of(work, struct my_work, work);
// Parameter for the work
int i = my_work->i;
// Do something
...
// Free memory used for work object
kfree(my_work);
}
// Helper for add your work with given parameter
void add_my_work(struct kthread_worker* worker, int i)
{
// Allocate your work object on the heap
struct my_work* my_work = kmalloc(sizeof(struct my_work), GFP_KERNEL);
// Initialize base work structure
init_kthread_work(&my_work->work, &my_func);
// Store parameter
work->i = i;
queue_kthread_work(worker, &my_work->work);
}
Any clarification on the unclear fields.
As you can see from previous example, knowing fields of struct kthread_worker and struct kthread_work is rarely useful for just using it. But actually semantic is simple:
struct kthread_worker {
spinlock_t lock; // lock to update the work queue
struct list_head work_list; // list kthread_work items
struct task_struct *task; // handle for thread
struct kthread_work *current_work; // (+) currently executed work object
};
struct kthread_work {
struct list_head node; // (+) element in the kthread_worker.work_list
kthread_work_func_t func; // func to execute
struct kthread_worker *worker; // worker associated with this work item
};
I would like to wrap a Rust struct in a C++ class.
Rust:
#[repr(C)]
pub struct RustStruct {
num: i32,
// other members..
}
pub extern "C" fn update(rust_struct: *mut RustStruct) {
(*rust_struct).num = 1i32;
}
extern "C" {
void update(void*);
}
C++:
class Wrapper {
public:
Wrapper();
// ..
private:
void* rustStruct;
// ..
};
Wrapper::Wrapper() {
update(rustStruct); // crash
}
int main() {
std::cout << "Testing..";
}
I understand why this wouldn't work. My question is: how can I achieve what I'm basically trying to do (wrap a rust struct in a c++ class)?
There is a mix of multiple FFIs concepts in your answer, so first let me recommend that your read the Reference.
There are two ways to achieve what you wish, you can either:
use a POD struct (Plain Old Data), aka C-compatible struct
use an opaque pointer (void* in C)
Mixing them, as you did, does not make sense.
Which to pick?
Both solutions have advantages and disadvantages, it's basically an expressiveness versus performance trade-off.
On the one hand, opaque pointers are more expressive: they can point to any Rust type. However:
they require dynamic memory allocation
they require being manipulated by Rust functions (so always indirectly from C or C++)
On the other hand, POD struct do not require either of those, but they are limited to only a subset of types expressible in Rust.
How to use a POD?
This is the easiest, actually, so let's start with it!
In Rust:
#[repr(C)]
pub struct RustStruct {
num: i32,
// other members, also PODs!
}
In C++
struct RustStruct {
int32_t num;
// other members, also with Standard Layout
// http://en.cppreference.com/w/cpp/types/is_standard_layout
};
class Wrapper {
public:
private:
RustStruct rustStruct;
};
Note that I just got along with your question stricto censu here, you could actually merge the two in a single C++ class:
class RustStruct {
public:
private:
int32_t num;
// other members, also with Standard Layout
// http://en.cppreference.com/w/cpp/types/is_standard_layout
};
Just avoid virtual methods.
How to use an opaque pointer?
This gets trickier:
Only the Rust code may correctly create/copy/destruct the type
Beware of leaking...
So, we need to implement a lot of functions in Rust:
#![feature(box_raw, box_syntax)]
use std::boxed;
pub struct RustStruct {
num: i32,
// other members, anything goes
}
pub extern "C" fn createRustStruct() -> *mut RustStruct {
boxed::into_raw(box RustStruct::new())
}
pub extern "C" fn destroyRustStruct(o: *mut RustStruct) {
boxed::from_raw(o);
}
Alright... now on to C++:
struct RustStruct;
RustStruct* createRustStruct();
void destroyRustStruct(RustStruct*);
class Wrapper {
public:
Wrapper(): rustStruct(RustStructPtr(createRustStruct())) {}
private:
struct Deleter {
void operator()(RustStruct* rs) const {
destroyRustStruct(rs);
}
};
typedef std::unique_ptr<RustStruct, Deleter> RustStructPtr;
RustStructPtr rustStruct;
}; // class Wrapper
So, yes, a bit more involved, and Wrapper is not copyable either (copy has to be delegated to Rust too). Anyway, this should get you started!
Note: if you have a lot of opaque pointers to wrap, a templated C++ class taking the copy/destroy functions as template parameters could alleviate a lot of boiler plate.
I want to implement multiple hrtimers, but I'm not sure how to use all of them with same callback function. For example I have array of type my_struct where one of the field is a struct hrtimer.
When I enter the callback function how to determine which element of the array is calling it?
Use the container_of macro:
struct my_struct {
int my_something;
struct hrtimer my_timer;
...
};
enum hrtimer_restart my_callback(struct hrtimer *hrtimer)
{
struct my_struct my = container_of(hrtimer, struct my_struct, my_timer);
my->my_something = 42;
...
}
I know if we have task_struct, surly we can get the contained sched_entity because it's one field in the task struct. But can we get the pointer to the task_struct given the shed_entity? Following is the sched_entity structure:
struct sched_entity {
struct load_weight load; /* for load-balancing */
struct rb_node run_node;
struct list_head group_node;
unsigned int on_rq;
u64 exec_start;
u64 sum_exec_runtime;
u64 vruntime;
u64 prev_sum_exec_runtime;
u64 nr_migrations;
#ifdef CONFIG_SCHEDSTATS
struct sched_statistics statistics;
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
struct sched_entity *parent;
/* rq on which this entity is (to be) queued: */
struct cfs_rq *cfs_rq;
/* rq "owned" by this entity/group: */
struct cfs_rq *my_q;
#endif
};
It seems that there is no place where I can get the task_struct. My final goal is to get the sched_entity of the task group_leader containing the task with this shed_entity :>
The Linux kernel code provides a standard way to take a pointer to an element contained within a structure, and get back a pointer to the containing structure: the container_of macro, which is used extensively throughout the kernel.
In this case, if you have a struct sched_entity *foo, you can get the enclosing task_struct with:
struct task_struct *task = container_of(foo, struct task_struct, se);
(Obviously this is only safe if you know for sure that the original struct sched_entity * pointer is pointing to a struct sched_entity which is inside a struct task_struct, so be careful...)