Skip to content

Commit c6c588b

Browse files
author
dsl
committed
Change the logic used for thread locking to make the code more readable.
The effect on the object code is to replace a function call with a branch that will predict correctly in the non-threaded case. Minor optimise of some other paths.
1 parent 840c552 commit c6c588b

File tree

1 file changed

+47
-98
lines changed

1 file changed

+47
-98
lines changed

lib/libc/gen/arc4random.c

Lines changed: 47 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: arc4random.c,v 1.15 2012/08/18 14:42:46 dsl Exp $ */
1+
/* $NetBSD: arc4random.c,v 1.16 2012/08/18 15:04:53 dsl Exp $ */
22
/* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $ */
33

44
/*
@@ -27,7 +27,7 @@
2727

2828
#include <sys/cdefs.h>
2929
#if defined(LIBC_SCCS) && !defined(lint)
30-
__RCSID("$NetBSD: arc4random.c,v 1.15 2012/08/18 14:42:46 dsl Exp $");
30+
__RCSID("$NetBSD: arc4random.c,v 1.16 2012/08/18 15:04:53 dsl Exp $");
3131
#endif /* LIBC_SCCS and not lint */
3232

3333
#include "namespace.h"
@@ -53,6 +53,21 @@ struct arc4_stream {
5353
uint8_t s[RSIZE];
5454
};
5555

56+
#ifdef _REENTRANT
57+
#define LOCK(rs) { \
58+
int isthreaded = __isthreaded; \
59+
if (isthreaded) \
60+
mutex_lock(&(rs)->mtx);
61+
#define UNLOCK(rs) \
62+
if (isthreaded) \
63+
mutex_unlock(&(rs)->mtx); \
64+
}
65+
#else
66+
#define LOCK(rs)
67+
#define UNLOCK(rs)
68+
#endif
69+
70+
5671
/* XXX lint explodes with an internal error if only mtx is initialized! */
5772
static struct arc4_stream rs = { .i = 0, .mtx = MUTEX_INITIALIZER };
5873

@@ -160,99 +175,53 @@ arc4_getword(struct arc4_stream *as)
160175
return val;
161176
}
162177

163-
static inline void
164-
_arc4random_stir_unlocked(void)
165-
{
166-
if (__predict_false(!arc4_check_init(&rs))) /* init() stirs */
167-
arc4_stir(&rs);
168-
}
169-
170178
void
171179
arc4random_stir(void)
172180
{
173-
#ifdef _REENTRANT
174-
if (__isthreaded) {
175-
mutex_lock(&rs.mtx);
176-
_arc4random_stir_unlocked();
177-
mutex_unlock(&rs.mtx);
178-
return;
179-
}
180-
#endif
181-
_arc4random_stir_unlocked();
182-
}
183-
184-
static inline void
185-
_arc4random_addrandom_unlocked(u_char *dat, int datlen)
186-
{
187-
arc4_check_init(&rs);
188-
arc4_addrandom(&rs, dat, datlen);
181+
LOCK(&rs);
182+
if (__predict_false(!arc4_check_init(&rs))) /* init() stirs */
183+
arc4_stir(&rs);
184+
UNLOCK(&rs);
189185
}
190186

191187
void
192188
arc4random_addrandom(u_char *dat, int datlen)
193189
{
194-
#ifdef _REENTRANT
195-
if (__isthreaded) {
196-
mutex_lock(&rs.mtx);
197-
_arc4random_addrandom_unlocked(dat, datlen);
198-
mutex_unlock(&rs.mtx);
199-
return;
200-
}
201-
#endif
202-
_arc4random_addrandom_unlocked(dat, datlen);
203-
}
204-
205-
static inline uint32_t
206-
_arc4random_unlocked(void)
207-
{
190+
LOCK(&rs);
208191
arc4_check_init(&rs);
209-
return arc4_getword(&rs);
192+
arc4_addrandom(&rs, dat, datlen);
193+
UNLOCK(&rs);
210194
}
211195

212196
uint32_t
213197
arc4random(void)
214198
{
215199
uint32_t v;
216-
#ifdef _REENTRANT
217-
if (__isthreaded) {
218-
mutex_lock(&rs.mtx);
219-
v = _arc4random_unlocked();
220-
mutex_unlock(&rs.mtx);
221-
return v;
222-
}
223-
#endif
224-
v = _arc4random_unlocked();
200+
201+
LOCK(&rs);
202+
arc4_check_init(&rs);
203+
v = arc4_getword(&rs);
204+
UNLOCK(&rs);
225205
return v;
226206
}
227207

228-
static void
229-
_arc4random_buf_unlocked(void *buf, size_t len)
208+
void
209+
arc4random_buf(void *buf, size_t len)
230210
{
231211
uint8_t *bp = buf;
232212
uint8_t *ep = bp + len;
213+
int skip;
233214

215+
LOCK(&rs);
234216
arc4_check_init(&rs);
235217

236-
bp[0] = arc4_getbyte(&rs) % 3;
237-
while (bp[0]--)
218+
skip = arc4_getbyte(&rs) % 3;
219+
while (skip--)
238220
(void)arc4_getbyte(&rs);
239221

240222
while (bp < ep)
241223
*bp++ = arc4_getbyte(&rs);
242-
}
243-
244-
void
245-
arc4random_buf(void *buf, size_t len)
246-
{
247-
#ifdef _REENTRANT
248-
if (__isthreaded) {
249-
mutex_lock(&rs.mtx);
250-
_arc4random_buf_unlocked(buf, len);
251-
mutex_unlock(&rs.mtx);
252-
return;
253-
} else
254-
#endif
255-
_arc4random_buf_unlocked(buf, len);
224+
UNLOCK(&rs);
256225
}
257226

258227
/*-
@@ -271,54 +240,34 @@ arc4random_buf(void *buf, size_t len)
271240
* [2^32 % upper_bound, 2^32[ which maps back to
272241
* [0, upper_bound[ after reduction modulo upper_bound.
273242
*/
274-
static uint32_t
275-
_arc4random_uniform_unlocked(uint32_t upper_bound)
243+
uint32_t
244+
arc4random_uniform(uint32_t upper_bound)
276245
{
277246
uint32_t r, min;
278247

279248
if (upper_bound < 2)
280249
return 0;
281250

282-
#if defined(ULONG_MAX) && (ULONG_MAX > 0xFFFFFFFFUL)
283-
min = (uint32_t)(0x100000000U % upper_bound);
284-
#else
285251
/* calculate (2^32 % upper_bound) avoiding 64-bit math */
286-
if (upper_bound > 0x80000000U)
287-
/* 2^32 - upper_bound (only one "value area") */
288-
min = 1 + ~upper_bound;
289-
else
290-
/* ((2^32 - x) % x) == (2^32 % x) when x <= 2^31 */
291-
min = (0xFFFFFFFFU - upper_bound + 1) % upper_bound;
292-
#endif
252+
/* ((2^32 - x) % x) == (2^32 % x) when x <= 2^31 */
253+
min = (0xFFFFFFFFU - upper_bound + 1) % upper_bound;
254+
255+
LOCK(&rs);
256+
arc4_check_init(&rs);
257+
258+
if (arc4_getbyte(&rs) & 1)
259+
(void)arc4_getbyte(&rs);
293260

294261
/*
295262
* This could theoretically loop forever but each retry has
296263
* p > 0.5 (worst case, usually far better) of selecting a
297264
* number inside the range we need, so it should rarely need
298265
* to re-roll (at all).
299266
*/
300-
arc4_check_init(&rs);
301-
if (arc4_getbyte(&rs) & 1)
302-
(void)arc4_getbyte(&rs);
303267
do
304268
r = arc4_getword(&rs);
305269
while (r < min);
270+
UNLOCK(&rs);
306271

307272
return r % upper_bound;
308273
}
309-
310-
uint32_t
311-
arc4random_uniform(uint32_t upper_bound)
312-
{
313-
uint32_t v;
314-
#ifdef _REENTRANT
315-
if (__isthreaded) {
316-
mutex_lock(&rs.mtx);
317-
v = _arc4random_uniform_unlocked(upper_bound);
318-
mutex_unlock(&rs.mtx);
319-
return v;
320-
}
321-
#endif
322-
v = _arc4random_uniform_unlocked(upper_bound);
323-
return v;
324-
}

0 commit comments

Comments
 (0)