test mbuf attach
[dpdk.git] / lib / librte_eal / common / rte_random.c
index e53d96d..b7a089a 100644 (file)
@@ -137,6 +137,45 @@ rte_rand(void)
        return __rte_rand_lfsr258(state);
 }
 
+uint64_t
+rte_rand_max(uint64_t upper_bound)
+{
+       struct rte_rand_state *state;
+       uint8_t ones;
+       uint8_t leading_zeros;
+       uint64_t mask = ~((uint64_t)0);
+       uint64_t res;
+
+       if (unlikely(upper_bound < 2))
+               return 0;
+
+       state = __rte_rand_get_state();
+
+       ones = __builtin_popcountll(upper_bound);
+
+       /* Handle power-of-2 upper_bound as a special case, since it
+        * has no bias issues.
+        */
+       if (unlikely(ones == 1))
+               return __rte_rand_lfsr258(state) & (upper_bound - 1);
+
+       /* The approach to avoiding bias is to create a mask that
+        * stretches beyond the request value range, and up to the
+        * next power-of-2. In case the masked generated random value
+        * is equal to or greater than the upper bound, just discard
+        * the value and generate a new one.
+        */
+
+       leading_zeros = __builtin_clzll(upper_bound);
+       mask >>= leading_zeros;
+
+       do {
+               res = __rte_rand_lfsr258(state) & mask;
+       } while (unlikely(res >= upper_bound));
+
+       return res;
+}
+
 static uint64_t
 __rte_random_initial_seed(void)
 {
@@ -150,17 +189,16 @@ __rte_random_initial_seed(void)
                return ge_seed;
 #endif
 #ifdef RTE_MACHINE_CPUFLAG_RDSEED
-       unsigned int rdseed_rc;
-       unsigned long long rdseed_seed;
+       unsigned int rdseed_low;
+       unsigned int rdseed_high;
 
        /* first fallback: rdseed instruction, if available */
-       rdseed_rc = _rdseed64_step(&rdseed_seed);
-
-       if (rdseed_rc == 1)
-               return (uint64_t)rdseed_seed;
+       if (_rdseed32_step(&rdseed_low) == 1 &&
+           _rdseed32_step(&rdseed_high) == 1)
+               return (uint64_t)rdseed_low | ((uint64_t)rdseed_high << 32);
 #endif
        /* second fallback: seed using rdtsc */
-       return rte_get_timer_cycles();
+       return rte_get_tsc_cycles();
 }
 
 RTE_INIT(rte_rand_init)