summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bufferevent-internal.h4
-rw-r--r--bufferevent_ratelim.c2
-rw-r--r--event-internal.h3
-rw-r--r--evutil.c23
-rw-r--r--poll.c2
-rw-r--r--select.c2
-rw-r--r--test/regress_buffer.c3
-rw-r--r--test/regress_util.c5
-rw-r--r--util-internal.h3
-rw-r--r--win32select.c9
10 files changed, 39 insertions, 17 deletions
diff --git a/bufferevent-internal.h b/bufferevent-internal.h
index 400c6d96..ad2c25c7 100644
--- a/bufferevent-internal.h
+++ b/bufferevent-internal.h
@@ -104,6 +104,10 @@ struct bufferevent_rate_limit_group {
/** Timeout event that goes off once a tick, when the bucket is ready
* to refill. */
struct event master_refill_event;
+
+ /** Seed for weak random number generator. */
+ ev_uint32_t weakrand_seed;
+
/** Lock to protect the members of this group. This lock should nest
* within every bufferevent lock: if you are holding this lock, do
* not assume you can lock another bufferevent. */
diff --git a/bufferevent_ratelim.c b/bufferevent_ratelim.c
index 02c50228..4272c0da 100644
--- a/bufferevent_ratelim.c
+++ b/bufferevent_ratelim.c
@@ -452,7 +452,7 @@ bev_group_random_element_(struct bufferevent_rate_limit_group *group)
EVUTIL_ASSERT(! LIST_EMPTY(&group->members));
- which = evutil_weakrand_() % group->n_members;
+ which = evutil_weakrand_range_(&group->weakrand_seed, group->n_members);
bev = LIST_FIRST(&group->members);
while (which--)
diff --git a/event-internal.h b/event-internal.h
index f840058d..4c882056 100644
--- a/event-internal.h
+++ b/event-internal.h
@@ -290,6 +290,9 @@ struct event_base {
struct event th_notify;
/** A function used to wake up the main thread from another thread. */
int (*th_notify_fn)(struct event_base *base);
+
+ /* Saved seed for weak random number generator. */
+ ev_uint32_t weakrand_seed;
};
struct event_config_entry {
diff --git a/evutil.c b/evutil.c
index abe15604..a87b5246 100644
--- a/evutil.c
+++ b/evutil.c
@@ -2273,14 +2273,23 @@ evutil_getenv_(const char *varname)
return getenv(varname);
}
-long
-evutil_weakrand_(void)
+ev_uint32_t
+evutil_weakrand_(ev_uint32_t* seed)
{
-#ifdef _WIN32
- return rand();
-#else
- return random();
-#endif
+ *seed = ((*seed) * 1103515245 + 12345) & 0x7fffffff;
+ return (*seed);
+}
+
+ev_uint32_t
+evutil_weakrand_range_(ev_uint32_t* seed, ev_uint32_t top)
+{
+ ev_uint32_t divisor, result;
+
+ divisor = EV_INT32_MAX / top;
+ do
+ result = evutil_weakrand_(seed) / divisor;
+ while (result > top);
+ return result;
}
int
diff --git a/poll.c b/poll.c
index 744c7141..3ac427ac 100644
--- a/poll.c
+++ b/poll.c
@@ -183,7 +183,7 @@ poll_dispatch(struct event_base *base, struct timeval *tv)
if (res == 0 || nfds == 0)
return (0);
- i = random() % nfds;
+ i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
for (j = 0; j < nfds; j++) {
int what;
if (++i == nfds)
diff --git a/select.c b/select.c
index e1d4987c..f9a0c206 100644
--- a/select.c
+++ b/select.c
@@ -186,7 +186,7 @@ select_dispatch(struct event_base *base, struct timeval *tv)
event_debug(("%s: select reports %d", __func__, res));
check_selectop(sop);
- i = random() % nfds;
+ i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
for (j = 0; j < nfds; ++j) {
if (++i >= nfds)
i = 0;
diff --git a/test/regress_buffer.c b/test/regress_buffer.c
index dfb680b5..2e4ef176 100644
--- a/test/regress_buffer.c
+++ b/test/regress_buffer.c
@@ -699,6 +699,7 @@ test_evbuffer_add_file(void *ptr)
struct event *rev=NULL, *wev=NULL;
struct event_base *base = testdata->base;
evutil_socket_t pair[2] = {-1, -1};
+ static ev_uint32_t seed = 123456789U;
/* This test is highly parameterized based on substrings of its
* argument. The strings are: */
@@ -757,7 +758,7 @@ test_evbuffer_add_file(void *ptr)
data = malloc(1024*512);
tt_assert(data);
for (i = 0; i < datalen; ++i)
- data[i] = (char)evutil_weakrand_();
+ data[i] = (char)evutil_weakrand_(&seed);
} else {
data = strdup("here is a relatively small string.");
tt_assert(data);
diff --git a/test/regress_util.c b/test/regress_util.c
index e7662e0f..2d53ba8d 100644
--- a/test/regress_util.c
+++ b/test/regress_util.c
@@ -829,6 +829,7 @@ test_evutil_rand(void *arg)
char buf2[32];
int counts[256];
int i, j, k, n=0;
+ static ev_uint32_t seed = 12346789U;
memset(buf2, 0, sizeof(buf2));
memset(counts, 0, sizeof(counts));
@@ -836,8 +837,8 @@ test_evutil_rand(void *arg)
for (k=0;k<32;++k) {
/* Try a few different start and end points; try to catch
* the various misaligned cases of arc4random_buf */
- int startpoint = evutil_weakrand_() % 4;
- int endpoint = 32 - (evutil_weakrand_() % 4);
+ int startpoint = evutil_weakrand_(&seed) % 4;
+ int endpoint = 32 - (evutil_weakrand_(&seed) % 4);
memset(buf2, 0, sizeof(buf2));
diff --git a/util-internal.h b/util-internal.h
index 508eae92..291feb8a 100644
--- a/util-internal.h
+++ b/util-internal.h
@@ -254,7 +254,8 @@ int evutil_resolve_(int family, const char *hostname, struct sockaddr *sa,
const char *evutil_getenv_(const char *name);
-long evutil_weakrand_(void);
+ev_uint32_t evutil_weakrand_(ev_uint32_t* seed);
+ev_uint32_t evutil_weakrand_range_(ev_uint32_t* seed, ev_uint32_t top);
/* Evaluates to the same boolean value as 'p', and hints to the compiler that
* we expect this value to be false. */
diff --git a/win32select.c b/win32select.c
index 441222f1..ce2d525f 100644
--- a/win32select.c
+++ b/win32select.c
@@ -326,7 +326,8 @@ win32_dispatch(struct event_base *base, struct timeval *tv)
}
if (win32op->readset_out->fd_count) {
- i = rand() % win32op->readset_out->fd_count;
+ i = evutil_weakrand_range_(&base->weakrand_seed,
+ win32op->readset_out->fd_count);
for (j=0; j<win32op->readset_out->fd_count; ++j) {
if (++i >= win32op->readset_out->fd_count)
i = 0;
@@ -335,7 +336,8 @@ win32_dispatch(struct event_base *base, struct timeval *tv)
}
}
if (win32op->exset_out->fd_count) {
- i = rand() % win32op->exset_out->fd_count;
+ i = evutil_weakrand_range_(&base->weakrand_seed,
+ win32op->exset_out->fd_count);
for (j=0; j<win32op->exset_out->fd_count; ++j) {
if (++i >= win32op->exset_out->fd_count)
i = 0;
@@ -345,7 +347,8 @@ win32_dispatch(struct event_base *base, struct timeval *tv)
}
if (win32op->writeset_out->fd_count) {
SOCKET s;
- i = rand() % win32op->writeset_out->fd_count;
+ i = evutil_weakrand_range_(&base->weakrand_seed,
+ win32op->writeset_out->fd_count);
for (j=0; j<win32op->writeset_out->fd_count; ++j) {
if (++i >= win32op->writeset_out->fd_count)
i = 0;