Turn random() to nrand48 in inner loop where it is not cryptographically relevant to avoid futex storm. Thanks and credits to Bart Smienk

dynamic-accesslists
Dirk Engling 4 years ago
parent 0695b48870
commit 616119ee22

@ -258,6 +258,9 @@ static void * server_mainloop( void * args ) {
#endif #endif
if( !ws.inbuf || !ws.outbuf ) if( !ws.inbuf || !ws.outbuf )
panic( "Initializing worker failed" ); panic( "Initializing worker failed" );
ws.rand48_state[0] = (uint16_t)random();
ws.rand48_state[1] = (uint16_t)random();
ws.rand48_state[2] = (uint16_t)random();
for( ; ; ) { for( ; ; ) {
int64 sock; int64 sock;

@ -29,7 +29,7 @@
#include "ot_livesync.h" #include "ot_livesync.h"
/* Forward declaration */ /* Forward declaration */
size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto );
void free_peerlist( ot_peerlist *peer_list ) { void free_peerlist( ot_peerlist *peer_list ) {
if( peer_list->peers.data ) { if( peer_list->peers.data ) {
@ -178,7 +178,7 @@ size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstr
} }
#endif #endif
ws->reply_size = return_peers_for_torrent( torrent, amount, ws->reply, proto ); ws->reply_size = return_peers_for_torrent( ws, torrent, amount, ws->reply, proto );
mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount );
return ws->reply_size; return ws->reply_size;
} }
@ -210,7 +210,7 @@ static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) {
return result; return result;
} }
static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, char *reply ) { static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *peer_list, size_t amount, char *reply ) {
unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; unsigned int bucket_offset, bucket_index = 0, num_buckets = 1;
ot_vector * bucket_list = &peer_list->peers; ot_vector * bucket_list = &peer_list->peers;
unsigned int shifted_pc = peer_list->peer_count; unsigned int shifted_pc = peer_list->peer_count;
@ -232,7 +232,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha
/* Initialize somewhere in the middle of peers so that /* Initialize somewhere in the middle of peers so that
fixpoint's aliasing doesn't alway miss the same peers */ fixpoint's aliasing doesn't alway miss the same peers */
bucket_offset = random() % peer_list->peer_count; bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count;
while( amount-- ) { while( amount-- ) {
ot_peer * peer; ot_peer * peer;
@ -240,7 +240,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha
/* This is the aliased, non shifted range, next value may fall into */ /* This is the aliased, non shifted range, next value may fall into */
unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) - unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) -
( ( amount * shifted_step ) >> shift ); ( ( amount * shifted_step ) >> shift );
bucket_offset += 1 + random() % diff; bucket_offset += 1 + nrand48(ws->rand48_state) % diff;
while( bucket_offset >= bucket_list[bucket_index].size ) { while( bucket_offset >= bucket_list[bucket_index].size ) {
bucket_offset -= bucket_list[bucket_index].size; bucket_offset -= bucket_list[bucket_index].size;
@ -262,7 +262,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha
* reply must have enough space to hold 92+6*amount bytes * reply must have enough space to hold 92+6*amount bytes
* does not yet check not to return self * does not yet check not to return self
*/ */
size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) {
ot_peerlist *peer_list = torrent->peer_list; ot_peerlist *peer_list = torrent->peer_list;
char *r = reply; char *r = reply;
@ -283,7 +283,7 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply
if( amount == peer_list->peer_count ) if( amount == peer_list->peer_count )
r += return_peers_all( peer_list, r ); r += return_peers_all( peer_list, r );
else else
r += return_peers_selection( peer_list, amount, r ); r += return_peers_selection( ws, peer_list, amount, r );
} }
if( proto == FLAG_TCP ) if( proto == FLAG_TCP )

@ -10,6 +10,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
typedef uint8_t ot_hash[20]; typedef uint8_t ot_hash[20];
typedef time_t ot_time; typedef time_t ot_time;
@ -34,7 +35,7 @@ typedef struct { ot_ip6 address; int bits; }
#define OT_TORRENT_TIMEOUT_HOURS 24 #define OT_TORRENT_TIMEOUT_HOURS 24
#define OT_TORRENT_TIMEOUT (60*OT_TORRENT_TIMEOUT_HOURS) #define OT_TORRENT_TIMEOUT (60*OT_TORRENT_TIMEOUT_HOURS)
#define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( random( ) % OT_CLIENT_REQUEST_VARIATION ) ) #define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( nrand48(ws->rand48_state) % OT_CLIENT_REQUEST_VARIATION ) )
/* If WANT_MODEST_FULLSCRAPES is on, ip addresses may not /* If WANT_MODEST_FULLSCRAPES is on, ip addresses may not
fullscrape more frequently than this amount in seconds */ fullscrape more frequently than this amount in seconds */
@ -131,6 +132,10 @@ struct ot_workstruct {
ssize_t header_size; ssize_t header_size;
char *reply; char *reply;
ssize_t reply_size; ssize_t reply_size;
/* Entropy state for rand48 function so that threads don't need to acquire mutexes for
global random() or arc4random() state, which causes heavy load on linuxes */
uint16_t rand48_state[3];
}; };
/* /*

Loading…
Cancel
Save