Messages in this thread | | | Date | Fri, 16 Apr 2021 16:03:07 +0100 | From | Matthew Wilcox <> | Subject | Re: [PATCH 00/13] [RFC] Rust support |
| |
On Fri, Apr 16, 2021 at 02:07:49PM +0100, Wedson Almeida Filho wrote: > There is nothing in C forcing developers to actually use DEFINE_MUTEX_GUARD. So > someone may simply forget (or not know that they need) to lock > current->perf_event_mutex and directly access some field protected by it. This > is unlikely to happen when one first writes the code, but over time as different > people modify the code and invariants change, it is possible for this to happen. > > In Rust, this isn't possible: the data protected by a lock is only accessible > when the lock is locked. So developers cannot accidentally make mistakes of this > kind. And since the enforcement happens at compile time, there is no runtime > cost.
Well, we could do that in C too.
struct unlocked_inode { spinlock_t i_lock; };
struct locked_inode { spinlock_t i_lock; unsigned short i_bytes; blkcnt_t i_blocks; };
struct locked_inode *lock_inode(struct unlocked_inode *inode) { spin_lock(&inode->i_lock); return (struct locked_inode *)inode; }
There's a combinatoric explosion when you have multiple locks in a data structure that protect different things in it (and things in a data structure that are protected by locks outside that data structure), but I'm not sufficiently familiar with Rust to know if/how it solves that problem.
Anyway, my point is that if we believe this is a sufficiently useful feature to have, and we're willing to churn the kernel, it's less churn to do this than it is to rewrite in Rust.
> Another scenario: suppose within perf_event_task_enable you need to call a > function that requires the mutex to be locked and that will unlock it for you on > error (or unconditionally, doesn't matter). How would you do that in C? In Rust, > there is a clean idiomatic way of transferring ownership of a guard (or any > other object) such that the previous owner cannot continue to use it after > ownership is transferred. Again, this is enforced at compile time. I'm happy to > provide a small example if that would help.
I think we could do that too with an __attribute__((free)). It isn't, of course, actually freeing the pointer to the locked_inode, but it will make the compiler think the pointer is invalid after the function returns.
(hm, looks like gcc doesn't actually have __attribute__((free)) yet. that's unfortunate. there's a potential solution in gcc-11 that might do what we need)
| |