@@ -70,6 +70,7 @@ enum filter_pred_fn {
70
70
FILTER_PRED_FN_CPU ,
71
71
FILTER_PRED_FN_CPU_CPUMASK ,
72
72
FILTER_PRED_FN_CPUMASK ,
73
+ FILTER_PRED_FN_CPUMASK_CPU ,
73
74
FILTER_PRED_FN_FUNCTION ,
74
75
FILTER_PRED_FN_ ,
75
76
FILTER_PRED_TEST_VISITED ,
@@ -957,6 +958,22 @@ static int filter_pred_cpumask(struct filter_pred *pred, void *event)
957
958
return do_filter_cpumask (pred -> op , mask , cmp );
958
959
}
959
960
961
+ /* Filter predicate for cpumask field vs user-provided scalar */
962
+ static int filter_pred_cpumask_cpu (struct filter_pred * pred , void * event )
963
+ {
964
+ u32 item = * (u32 * )(event + pred -> offset );
965
+ int loc = item & 0xffff ;
966
+ const struct cpumask * mask = (event + loc );
967
+ unsigned int cpu = pred -> val ;
968
+
969
+ /*
970
+ * This inverts the usual usage of the function (field is first element,
971
+ * user parameter is second), but that's fine because the (scalar, mask)
972
+ * operations used are symmetric.
973
+ */
974
+ return do_filter_scalar_cpumask (pred -> op , cpu , mask );
975
+ }
976
+
960
977
/* Filter predicate for COMM. */
961
978
static int filter_pred_comm (struct filter_pred * pred , void * event )
962
979
{
@@ -1453,6 +1470,8 @@ static int filter_pred_fn_call(struct filter_pred *pred, void *event)
1453
1470
return filter_pred_cpu_cpumask (pred , event );
1454
1471
case FILTER_PRED_FN_CPUMASK :
1455
1472
return filter_pred_cpumask (pred , event );
1473
+ case FILTER_PRED_FN_CPUMASK_CPU :
1474
+ return filter_pred_cpumask_cpu (pred , event );
1456
1475
case FILTER_PRED_FN_FUNCTION :
1457
1476
return filter_pred_function (pred , event );
1458
1477
case FILTER_PRED_TEST_VISITED :
@@ -1666,6 +1685,7 @@ static int parse_pred(const char *str, void *data,
1666
1685
1667
1686
} else if (!strncmp (str + i , "CPUS" , 4 )) {
1668
1687
unsigned int maskstart ;
1688
+ bool single ;
1669
1689
char * tmp ;
1670
1690
1671
1691
switch (field -> filter_type ) {
@@ -1724,8 +1744,21 @@ static int parse_pred(const char *str, void *data,
1724
1744
1725
1745
/* Move along */
1726
1746
i ++ ;
1747
+
1748
+ /*
1749
+ * Optimisation: if the user-provided mask has a weight of one
1750
+ * then we can treat it as a scalar input.
1751
+ */
1752
+ single = cpumask_weight (pred -> mask ) == 1 ;
1753
+ if (single && field -> filter_type == FILTER_CPUMASK ) {
1754
+ pred -> val = cpumask_first (pred -> mask );
1755
+ kfree (pred -> mask );
1756
+ }
1757
+
1727
1758
if (field -> filter_type == FILTER_CPUMASK ) {
1728
- pred -> fn_num = FILTER_PRED_FN_CPUMASK ;
1759
+ pred -> fn_num = single ?
1760
+ FILTER_PRED_FN_CPUMASK_CPU :
1761
+ FILTER_PRED_FN_CPUMASK ;
1729
1762
} else if (field -> filter_type == FILTER_CPU ) {
1730
1763
pred -> fn_num = FILTER_PRED_FN_CPU_CPUMASK ;
1731
1764
} else {
0 commit comments