@@ -586,36 +586,48 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
586586 }
587587}
588588
589- #define READ_ONCE (x ) \
590- ({ \
591- union { typeof(x) __val; char __c[1]; } __u = \
592- { .__c = { 0 } }; \
593- __read_once_size(&(x), __u.__c, sizeof(x)); \
594- __u.__val; \
595- })
596-
597- #define WRITE_ONCE (x , val ) \
598- ({ \
599- union { typeof(x) __val; char __c[1]; } __u = \
600- { .__val = (val) }; \
601- __write_once_size(&(x), __u.__c, sizeof(x)); \
602- __u.__val; \
603- })
604-
605- #define READ_ONCE_ARENA (type , x ) \
606- ({ \
607- union { type __val; char __c[1]; } __u = \
608- { .__c = { 0 } }; \
609- __read_once_size((void *)&(x), __u.__c, sizeof(x)); \
610- __u.__val; \
589+ /*
590+ * __unqual_typeof(x) - Declare an unqualified scalar type, leaving
591+ * non-scalar types unchanged,
592+ *
593+ * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
594+ * is not type-compatible with 'signed char', and we define a separate case.
595+ *
596+ * This is copied verbatim from kernel's include/linux/compiler_types.h, but
597+ * with default expression (for pointers) changed from (x) to (typeof(x)0).
598+ *
599+ * This is because LLVM has a bug where for lvalue (x), it does not get rid of
600+ * an extra address_space qualifier, but does in case of rvalue (typeof(x)0).
601+ * Hence, for pointers, we need to create an rvalue expression to get the
602+ * desired type. See https://github.com/llvm/llvm-project/issues/53400.
603+ */
604+ #define __scalar_type_to_expr_cases (type ) \
605+ unsigned type : (unsigned type)0, signed type : (signed type)0
606+
607+ #define __unqual_typeof (x ) \
608+ typeof(_Generic((x), \
609+ char: (char)0, \
610+ __scalar_type_to_expr_cases(char), \
611+ __scalar_type_to_expr_cases(short), \
612+ __scalar_type_to_expr_cases(int), \
613+ __scalar_type_to_expr_cases(long), \
614+ __scalar_type_to_expr_cases(long long), \
615+ default: (typeof(x))0))
616+
617+ #define READ_ONCE (x ) \
618+ ({ \
619+ union { __unqual_typeof(x) __val; char __c[1]; } __u = \
620+ { .__c = { 0 } }; \
621+ __read_once_size((__unqual_typeof(x) *)&(x), __u.__c, sizeof(x)); \
622+ __u.__val; \
611623})
612624
613- #define WRITE_ONCE_ARENA ( type , x , val ) \
614- ({ \
615- union { type __val; char __c[1]; } __u = \
616- { .__val = (val) }; \
617- __write_once_size((void *)&(x), __u.__c, sizeof(x)); \
618- __u.__val; \
625+ #define WRITE_ONCE ( x , val ) \
626+ ({ \
627+ union { __unqual_typeof(x) __val; char __c[1]; } __u = \
628+ { .__val = (val) }; \
629+ __write_once_size((__unqual_typeof(x) *)&(x), __u.__c, sizeof(x)); \
630+ __u.__val; \
619631})
620632
621633/*
@@ -648,6 +660,23 @@ static inline u32 log2_u64(u64 v)
648660 return log2_u32 (v ) + 1 ;
649661}
650662
663+ /*
664+ * Return a value proportionally scaled to the task's weight.
665+ */
666+ static inline u64 scale_by_task_weight (const struct task_struct * p , u64 value )
667+ {
668+ return (value * p -> scx .weight ) / 100 ;
669+ }
670+
671+ /*
672+ * Return a value inversely proportional to the task's weight.
673+ */
674+ static inline u64 scale_by_task_weight_inverse (const struct task_struct * p , u64 value )
675+ {
676+ return value * 100 / p -> scx .weight ;
677+ }
678+
679+
651680#include "compat.bpf.h"
652681#include "enums.bpf.h"
653682
0 commit comments