Received: by 2002:a05:7412:3784:b0:e2:908c:2ebd with SMTP id jk4csp2252390rdb; Tue, 3 Oct 2023 15:30:01 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFNWSJzLTxEpwPb9p0TZxMD6GiRdotEMfpPRGTfgpe1L4VQRq4NYNO8BMBRjMZx5RhdrMMR X-Received: by 2002:a17:902:e54a:b0:1b5:674d:2aa5 with SMTP id n10-20020a170902e54a00b001b5674d2aa5mr815623plf.13.1696372197337; Tue, 03 Oct 2023 15:29:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696372197; cv=none; d=google.com; s=arc-20160816; b=er6o8McGbSFHwaLM5GDHrVDgYGy0czTGFtp1/+JzY2WnDu7Wy4V0gn1sX0plZygeGs s8kLP20X5VBiwC+SpFjuVyJgAWq/OMqkAJA82r4Z9Sg0p6ZuVImfCTUVQo+VfAP12GMR TSnqgcLw7u7MjwBNM5DNNi+VGAi/l67TykeITQ7UJSwyjN88NJJZ/oFwC3d5CHi9I2Je 5sL82Ti/cAx8WxvgrTIT1fFFMHu8o6Tpp3F2FrFqBPNY5OlvtbRKMxa+BquQscYR/lRp 0f/4CbmM38kjl4Xei2sLLwyEYp9GxDXRs+ifuuXcDlyKM6sPCMluOCb2zmdUSLmhDphX qHRg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=dAD+NyD8rwm68rv+KcO6kIHA2BI/1BAlT5OkmuE/mvM=; fh=3bUguKIUe2T7MFd8a6lJufe7iRNO4X+3eTh+ee4gv0U=; b=lqqJfukBufg7EuR29tr/zFz0I96jLOu4Vf5EgzE8Wk7lAuNoHhX9OhxMtdI2l46VkZ ELtqLFKVBERa7RWwqNdXI5ncX5cyJN+tbWT6i78fJSzTxHaS/rf+nWA7dxiSTg09D2iW NkadEoPk4NEyCw8DN6j+5KZ+p2xkq4S6GL9k+LfvUBEf/qFnupgXVMRsz6vqp7q6zpDk oB5IvA3wRvxsbGbszaIkUXe1p0L6tVdFWDnDXQ2KEM6c9Bqpg6+F+EbUUhev2pcG448C 5Cc4yKI3dz2fAZQ/Yt/Gb0mzvCQk4HQ9yqbS6BrC4mCdt8wbbVLVxHcrW1bPS57KAVH4 Xzfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=fZb6IBe5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from howler.vger.email (howler.vger.email. [23.128.96.34]) by mx.google.com with ESMTPS id n17-20020a170902e55100b001c3e500e6d4si2458658plf.344.2023.10.03.15.29.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Oct 2023 15:29:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) client-ip=23.128.96.34; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=fZb6IBe5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id 495B68025831; Tue, 3 Oct 2023 15:29:56 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230032AbjJCW34 (ORCPT + 99 others); Tue, 3 Oct 2023 18:29:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229776AbjJCW3z (ORCPT ); Tue, 3 Oct 2023 18:29:55 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7218DB0 for ; Tue, 3 Oct 2023 15:29:51 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-59b59e1ac70so21888777b3.1 for ; Tue, 03 Oct 2023 15:29:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1696372190; x=1696976990; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=dAD+NyD8rwm68rv+KcO6kIHA2BI/1BAlT5OkmuE/mvM=; b=fZb6IBe5rRmR0jkZKZdQoc2lOLcUyNJeVJv6ov3fv8MSZ1hBDbV+eKcmXW/Re5aTOF BfpzDYe1DO1B63SKJJ6vKvCiRZjmM02KdQgYzQ7wgShFAGdnPXWmaj2kO/c9lH+Xl5dT EyLscf27lygnuqE7ugZ5NTXfRXti2O00V/MmFF0E09PveSgOhm9SrwjJCQx7LzZbaqwc mkQ+XY4TL3lkv07cFvl6EiWVi1JD5D6um28REq/WV78T5JYX6PvPrg6ESas0jzmCV7oL bgH8CteMSIXuvPeSIjpeTjkEGT1p8GTNZK3+mFPr0MAvtvXMkbG6L9s/Vztt6Om5xO14 Z2xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696372190; x=1696976990; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=dAD+NyD8rwm68rv+KcO6kIHA2BI/1BAlT5OkmuE/mvM=; b=lat2ot4pxrXSzmOkrSeHCQbPuRB7imP66UnpnrUUZxGHsyPnSWx9Ji14grUhh9jl2z Ot4Wn9Q3wlzupnoD80JvRD0jkbCNsEoVFdo3A3B5hw8WDfBRsO5Iin8Fb+F6bcGlo4Ub wcFJtV+/ZbZqQLngCHpa79w8oQqsCNkh3PzV+9gBr/6MfLFgosB9gdqeEpY6vWRtzJon to9EQAWpzGn0++VQ5JmCy+9WrqpofLfiZlIlEBF7XNZ6BZxGNmU5s+zXRqJwty7qUACn xwAaUZCj4piR1JkCTmmPy1Vj70DkN6Iq6T9/LNk1X4pqauZPB+7IsAMdd8TUcOLgt+V7 KgvQ== X-Gm-Message-State: AOJu0YyhlgPXULHVQg9HokIkQkkg5gd2feZwtTjGt2vgk9I8A42R6Uea wfTk0o8r5hNC7Q4FX+Y/bIZ8QonedtjbxP8= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a25:248:0:b0:d8c:cc9b:81cc with SMTP id 69-20020a250248000000b00d8ccc9b81ccmr8747ybc.3.1696372190665; Tue, 03 Oct 2023 15:29:50 -0700 (PDT) Date: Tue, 3 Oct 2023 22:29:47 +0000 In-Reply-To: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.42.0.582.g8ccd20d70d-goog Message-ID: <20231003222947.374039-1-aliceryhl@google.com> Subject: Re: [PATCH v4 7/7] rust: workqueue: add examples From: Alice Ryhl To: k.shelekhin@ftml.net Cc: alex.gaynor@gmail.com, aliceryhl@google.com, benno.lossin@proton.me, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, gary@garyguo.net, jiangshanlai@gmail.com, linux-kernel@vger.kernel.org, nmi@metaspace.dk, ojeda@kernel.org, patches@lists.linux.dev, rust-for-linux@vger.kernel.org, tj@kernel.org, wedsonaf@gmail.com, yakoyoku@gmail.com Content-Type: text/plain; charset="utf-8" X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PDS_OTHER_BAD_TLD, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Tue, 03 Oct 2023 15:29:56 -0700 (PDT) On Tue, Oct 3, 2023 at 10:13PM Konstantin Shelekhin wrote: > +//! #[pin_data] > +//! struct MyStruct { > +//! value: i32, > +//! #[pin] > +//! work: Work, > +//! } > +//! > +//! impl_has_work! { > +//! impl HasWork for MyStruct { self.work } > +//! } > +//! > +//! impl MyStruct { > +//! fn new(value: i32) -> Result> { > +//! Arc::pin_init(pin_init!(MyStruct { > +//! value, > +//! work <- new_work!("MyStruct::work"), > +//! })) > +//! } > +//! } > +//! > +//! impl WorkItem for MyStruct { > +//! type Pointer = Arc; > +//! > +//! fn run(this: Arc) { > +//! 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) { > +//! let _ = workqueue::system().enqueue(val); > +//! } > > I understand that this is highly opionated, but is it possible to make > the initialization less verbose? The short answer is yes. There are safe alternatives that are much less verbose. Unfortunately, those alternatives give up some of the features that this design has. Specifically, they give up the feature that allows you to embed the work_struct inside custom structs. I need to be able to embed the work_struct inside of custom structs, so I did not go that route. There are also some parts of this (mainly `impl_has_work!`) that I am unhappy with. I would be happy to see a solution that doesn't need it, but I couldn't figure out how to avoid it. > Because the C version looks much, much cleaner and easier to grasp: > > struct my_struct { > i32 value; > struct work_struct work; > }; > > void log_value(struct work_struct *work) > { > struct my_struct *s = container_of(work, struct my_struct, work); > pr_info("The value is: %d\n", s->value); > } > > void print_later(struct my_struct &s) > { > INIT_WORK(&s->work, log_value); > schedule_work(&s->work); > } Although I think that a part of this is just whether you are familiar with Rust syntax, there is definitely some truth to this. Your code is a lot closer to the machine code of what actually happens here. Perhaps it would be interesting to see what you get if you just unsafely do exactly the same thing in Rust? It would look something like this: struct MyStruct { value: i32, work: bindings::work_struct, } unsafe fn log_value(work: *mut bindings::work_struct) { unsafe { let s = container_of!(work, MyStruct, work); pr_info!("The value is: {}", (*s).value); } } unsafe fn print_later(s: *mut bindings::work_struct) { unsafe { bindings::INIT_WORK(&mut (*s).work, log_value); bindings::schedule_work(&mut (*s).work); } } (I didn't try to compile this.) The problem with this approach is that it uses unsafe in driver code, but the goal behind Rust abstractions is to isolate all of the related unsafe code. The idea being that drivers using the workqueue do not need any unsafe code to use it. This means that, assuming these workqueue abstractions are correct, no driver can accidentally cause memory unsafety by using the workqueue wrong. The main difficult part of making this happen is the container_of operation. We need to somehow verify *at compile time* that the container_of in log_value really is given a pointer to the work field of a MyStruct. Other than the things that are just how Rust looks, most of the verbosity is necessary to make this compile-time check possible. Another thing it does is handle proper transfer of ownership. In my original example, MyStruct is reference counted (due to the use of Arc), so the workqueue passes ownership of one refcount to the workqueue, which eventually passes the refcount to run. When `this` goes out of scope at the end of `run`, the refcount is decremented and the struct is freed if the refcount dropped to zero. If you wanted to just have exclusive ownership of my_struct, you could do that by using Box instead of Arc. In either case, the ownership is correctly passed to run, and you cannot accidentally forget to free it at the end of log_value. So, ultimately there's a tradeoff here. The code corresponds less directly to what the machine code will be. On the other hand, it will be *more* difficult to use incorrectly since incorrect uses will usually result in compilation errors. The claim of Rust is that this tradeoff is worth it. Alice