[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v5 1/7] xen/riscv: use {read,write}{b,w,l,q}_cpu() to define {read,write}_atomic()
On 28.08.2024 11:21, oleksii.kurochko@xxxxxxxxx wrote: > On Tue, 2024-08-27 at 12:06 +0200, Jan Beulich wrote: >> On 21.08.2024 18:06, Oleksii Kurochko wrote: >>> In Xen, memory-ordered atomic operations are not necessary, >> >> This is an interesting statement. > I looked at the definition of build_atomic_{write,read}() for other > architectures and didn't find any additional memory-ordered primitives > such as fences. > >> I'd like to suggest that you at least >> limit it to the two constructs in question, rather than stating this >> globally for everything. > I am not sure that I understand what is "the two constructs". Could you > please clarify? {read,write}_atomic() (the statement in your description is, after all, not obviously limited to just those two, yet I understand you mean to say what you say only for them) >>> based on {read,write}_atomic() implementations for other >>> architectures. >>> Therefore, {read,write}{b,w,l,q}_cpu() can be used instead of >>> {read,write}{b,w,l,q}(), allowing the caller to decide if >>> additional >>> fences should be applied before or after {read,write}_atomic(). >>> >>> Change the declaration of _write_atomic() to accept a 'volatile >>> void *' >>> type for the 'x' argument instead of 'unsigned long'. >>> This prevents compilation errors such as: >>> 1."discards 'volatile' qualifier from pointer target type," which >>> occurs >>> due to the initialization of a volatile pointer, >>> e.g., `volatile uint8_t *ptr = p;` in _add_sized(). >> >> I don't follow you here. > This issue started occurring after the change mentioned in point 2 > below. > > I initially provided an incorrect explanation for the compilation error > mentioned above. Let me correct that now and update the commit message > in the next patch version. The reason for this error is that after the > _write_atomic() prototype was updated from _write_atomic(..., unsigned > long, ...) to _write_atomic(..., void *x, ...), the write_atomic() > macro contains x_, which is of type 'volatile uintX_t' because ptr has > the type 'volatile uintX_t *'. While there's no "ptr" in write_atomic(), I think I see what you mean. Yet at the same time Arm - having a similar construct - gets away without volatile. Perhaps this wants modelling after read_atomic() then, using a union? > Therefore, _write_atomic() should have its second argument declared as > volatile const void *. Alternatively, we can consider updating > write_atomic() to: > #define write_atomic(p, x) \ > ({ \ > typeof(*(p)) x_ = (x); \ > _write_atomic(p, (const void *)&x_, sizeof(*(p))); \ > }) > Would this be a better approach?Would it be better? Like const you also should avoid to cast away volatile, whenever possible. >>> 2."incompatible type for argument 2 of '_write_atomic'," which can >>> occur >>> when calling write_pte(), where 'x' is of type pte_t rather than >>> unsigned long. >> >> How's this related to the change at hand? That isn't different ahead >> of >> this change, is it? > This is not directly related to the current change, which is why I > decided to add a sentence about write_pte(). > > Since write_pte(pte_t *p, pte_t pte) uses write_atomic(), and the > argument types are pte_t * and pte respectively, we encounter a > compilation issue in write_atomic() because: > > _write_atomic() expects the second argument to be of type unsigned > long, leading to a compilation error like "incompatible type for > argument 2 of '_write_atomic'." > I considered defining write_pte() as write_atomic(p, pte.pte), but this > would fail at 'typeof(*(p)) x_ = (x);' and result in a compilation > error 'invalid initializer' or something like that. > > It might be better to update write_pte() to: > /* Write a pagetable entry. */ > static inline void write_pte(pte_t *p, pte_t pte) > { > write_atomic((unsigned long *)p, pte.pte); > } > Then, we wouldn't need to modify the definition of write_atomic() or > change the type of the second argument of _write_atomic(). > Would it be better? As said numerous times before: Whenever you can get away without a cast, you should avoid the cast. Here: static inline void write_pte(pte_t *p, pte_t pte) { write_atomic(&p->pte, pte.pte); } That's one of the possible options, yes. Yet, like Arm has it, you may actually want the capability to read/write non-scalar types. If so, adjustments to write_atomic() are necessary, yet as indicated before: Please keep such entirely independent changes separate. Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |