xref: /linux/tools/perf/bench/futex.c (revision e78f70bad29c5ae1e1076698b690b15794e9b81e) !
1 // SPDX-License-Identifier: GPL-2.0
2 #include <err.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/prctl.h>
6 
7 #include "futex.h"
8 
9 #ifndef PR_FUTEX_HASH
10 #define PR_FUTEX_HASH                   78
11 # define PR_FUTEX_HASH_SET_SLOTS        1
12 # define FH_FLAG_IMMUTABLE              (1ULL << 0)
13 # define PR_FUTEX_HASH_GET_SLOTS        2
14 # define PR_FUTEX_HASH_GET_IMMUTABLE    3
15 #endif // PR_FUTEX_HASH
16 
17 void futex_set_nbuckets_param(struct bench_futex_parameters *params)
18 {
19 	unsigned long flags;
20 	int ret;
21 
22 	if (params->nbuckets < 0)
23 		return;
24 
25 	flags = params->buckets_immutable ? FH_FLAG_IMMUTABLE : 0;
26 	ret = prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, params->nbuckets, flags);
27 	if (ret) {
28 		printf("Requesting %d hash buckets failed: %d/%m\n",
29 		       params->nbuckets, ret);
30 		err(EXIT_FAILURE, "prctl(PR_FUTEX_HASH)");
31 	}
32 }
33 
34 void futex_print_nbuckets(struct bench_futex_parameters *params)
35 {
36 	char *futex_hash_mode;
37 	int ret;
38 
39 	ret = prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_GET_SLOTS);
40 	if (params->nbuckets >= 0) {
41 		if (ret != params->nbuckets) {
42 			if (ret < 0) {
43 				printf("Can't query number of buckets: %m\n");
44 				err(EXIT_FAILURE, "prctl(PR_FUTEX_HASH)");
45 			}
46 			printf("Requested number of hash buckets does not currently used.\n");
47 			printf("Requested: %d in usage: %d\n", params->nbuckets, ret);
48 			err(EXIT_FAILURE, "prctl(PR_FUTEX_HASH)");
49 		}
50 		if (params->nbuckets == 0) {
51 			ret = asprintf(&futex_hash_mode, "Futex hashing: global hash");
52 		} else {
53 			ret = prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_GET_IMMUTABLE);
54 			if (ret < 0) {
55 				printf("Can't check if the hash is immutable: %m\n");
56 				err(EXIT_FAILURE, "prctl(PR_FUTEX_HASH)");
57 			}
58 			ret = asprintf(&futex_hash_mode, "Futex hashing: %d hash buckets %s",
59 				       params->nbuckets,
60 				       ret == 1 ? "(immutable)" : "");
61 		}
62 	} else {
63 		if (ret <= 0) {
64 			ret = asprintf(&futex_hash_mode, "Futex hashing: global hash");
65 		} else {
66 			ret = asprintf(&futex_hash_mode, "Futex hashing: auto resized to %d buckets",
67 				       ret);
68 		}
69 	}
70 	if (ret < 0)
71 		err(EXIT_FAILURE, "ENOMEM, futex_hash_mode");
72 	printf("%s\n", futex_hash_mode);
73 	free(futex_hash_mode);
74 }
75