I recently needed to generate a series of unique random numbers (non-repeated) within a bounded range inside of the Linux kernel. The code I came up with is below. I'd appreciate any feedback -- again, please keep in mind that it's within the Linux kernel, so the standard C library is out of the question.
#include <linux/kernel.h>
#include <linux/random.h>
#include <linux/slab.h>
static int mod(int, int);
static int _is_repeated_int(int *, int, int);
/* proj2_create_randints - creates a buffer of random integers
* @dstruct_size: number of random integers
* @max_range: maximum range of values to generate
*
* Allocates a buffer that can hold @dstruct_size random integers. If
* @max_range is greater than 0, mods all values by @max_value to ensure
* they fall within the range. If @dstruct_size is greater than @max_range,
* returns NULL. The buffer returned is guaranteed to have no duplicate values.
*
* On successs, it fills the buffer and returns a pointer to the buffer;
* otherwise returns NULL.
*/
int *proj2_create_randints(int dstruct_size, int max_range)
{
int *randint;
int tmp, idx;
if ((max_range != 0) && (dstruct_size > max_range))
return NULL;
randint = kmalloc(dstruct_size * sizeof(*randint), GFP_KERNEL);
if (randint != NULL) {
idx = 0;
while (idx < dstruct_size) {
tmp = get_random_int();
if (max_range > 0)
tmp = mod(tmp, max_range);
/* Check if 'tmp' is already in array */
if (!_is_repeated_int(randint, idx, tmp)) {
randint[idx] = tmp;
idx++;
}
}
}
return randint;
}
/* mod - returns x modulo m
* @x: value to reduce
* @m: modulo value
*
* Guaranteed to be positive.
*/
static int mod(int x, int m)
{
return (x%m + m)%m;
}
/* _is_repeated_int - checks array against repeated values
* @array: array of integers to check
* @size: size of @array
* @new_value: value to check array for
*/
static int _is_repeated_int(int *array, int size, int new_value)
{
int i;
if (size == 0)
return 0;
for (i = 0; i < size; i++) {
if (array[i] == new_value) {
return 1;
}
}
return 0;
}