| 1033 | } |
| 1034 | |
| 1035 | int |
| 1036 | stats_tpl_sample_rollthedice(struct stats_tpl_sample_rate *rates, int nrates, |
| 1037 | void *seed_bytes, size_t seed_len) |
| 1038 | { |
| 1039 | uint32_t cum_pct, rnd_pct; |
| 1040 | int i; |
| 1041 | |
| 1042 | cum_pct = 0; |
| 1043 | |
| 1044 | /* |
| 1045 | * Choose a pseudorandom or seeded number in range [0,100] and use |
| 1046 | * it to make a sampling decision and template selection where required. |
| 1047 | * If no seed is supplied, a PRNG is used to generate a pseudorandom |
| 1048 | * number so that every selection is independent. If a seed is supplied, |
| 1049 | * the caller desires random selection across different seeds, but |
| 1050 | * deterministic selection given the same seed. This is achieved by |
| 1051 | * hashing the seed and using the hash as the random number source. |
| 1052 | * |
| 1053 | * XXXLAS: Characterise hash function output distribution. |
| 1054 | */ |
| 1055 | if (seed_bytes == NULL) |
| 1056 | rnd_pct = random() / (INT32_MAX / 100); |
| 1057 | else |
| 1058 | rnd_pct = hash32_buf(seed_bytes, seed_len, 0) / |
| 1059 | (UINT32_MAX / 100U); |
| 1060 | |
| 1061 | /* |
| 1062 | * We map the randomly selected percentage on to the interval [0,100] |
| 1063 | * consisting of the cumulatively summed template sampling percentages. |
| 1064 | * The difference between the cumulative sum of all template sampling |
| 1065 | * percentages and 100 is treated as a NULL assignment i.e. no stats |
| 1066 | * template will be assigned, and -1 returned instead. |
| 1067 | */ |
| 1068 | for (i = 0; i < nrates; i++) { |
| 1069 | cum_pct += rates[i].tpl_sample_pct; |
| 1070 | |
| 1071 | KASSERT(cum_pct <= 100, ("%s cum_pct %u > 100", __func__, |
| 1072 | cum_pct)); |
| 1073 | if (rnd_pct > cum_pct || rates[i].tpl_sample_pct == 0) |
| 1074 | continue; |
| 1075 | |
| 1076 | return (rates[i].tpl_slot_id); |
| 1077 | } |
| 1078 | |
| 1079 | return (-1); |
| 1080 | } |
| 1081 | |
| 1082 | int |
| 1083 | stats_v1_blob_clone(struct statsblobv1 **dst, size_t dstmaxsz, |
no test coverage detected