On Wed, Dec 02, 2009 at 10:38:10AM +0100, Otto Moerbeek wrote:
> Hi,
re

> apart from the random page addresses obtained form mmap(2) malloc(3)
> itself also randomizes cache en chunk operations. It uses a nibble of
> randomness per call, so optimize that to not waste half the random
> bits. 

arc4 random does not use entropy and is very cheap
almost the speed of memory copy. "caching" arc4 output
like this is the same as running rot13 twice (:

> Please test, should be a bit faster.
> 
>       -Otto
>       
> Index: malloc.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
> retrieving revision 1.121
> diff -u -p -r1.121 malloc.c
> --- malloc.c  27 Nov 2009 20:11:01 -0000      1.121
> +++ malloc.c  30 Nov 2009 19:40:47 -0000
> @@ -64,7 +64,7 @@
>  
>  #define MALLOC_MAXCHUNK              (1 << (MALLOC_PAGESHIFT-1))
>  #define MALLOC_MAXCACHE              256
> -#define MALLOC_DELAYED_CHUNKS        16      /* should be power of 2 */
> +#define MALLOC_DELAYED_CHUNKS        15      /* max of getrnibble() */
>  /*
>   * When the P option is active, we move allocations between half a page
>   * and a whole page towards the end, subject to alignment constraints.
> @@ -110,7 +110,7 @@ struct dir_info {
>                                       /* free pages cache */
>       struct region_info free_regions[MALLOC_MAXCACHE];
>                                       /* delayed free chunk slots */
> -     void *delayed_chunks[MALLOC_DELAYED_CHUNKS];
> +     void *delayed_chunks[MALLOC_DELAYED_CHUNKS + 1];
>  #ifdef MALLOC_STATS
>       size_t inserts;
>       size_t insert_collisions;
> @@ -183,9 +183,9 @@ static int        malloc_active;          /* status of 
>  static size_t        malloc_guarded;         /* bytes used for guards */
>  static size_t        malloc_used;            /* bytes allocated */
>  
> -static size_t rbytesused;            /* random bytes used */
> +static size_t rnibblesused;          /* random nibbles used */
>  static u_char rbytes[512];           /* random bytes */
> -static u_char getrbyte(void);
> +static u_char getrnibble(void);
>  
>  extern char  *__progname;
>  
> @@ -378,6 +378,26 @@ wrterror(char *p)
>               abort();
>  }
>  
> +static void
> +rbytes_init(void)
> +{
> +     arc4random_buf(rbytes, sizeof(rbytes));
> +     rnibblesused = 0;
> +}
> +
> +static inline u_char
> +getrnibble(void)
> +{
> +     u_char x;
> +
> +     if (rnibblesused >= 2 * sizeof(rbytes))
> +             rbytes_init();
> +     x = rnibblesused < sizeof(rbytes) ? (rbytes[rnibblesused] & 0xf) :
> +         (rbytes[rnibblesused - sizeof(rbytes)] >> 4);
> +     rnibblesused++;
> +     return x;
> +}
> +
>  /*
>   * Cache maintenance. We keep at most malloc_cache pages cached.
>   * If the cache is becoming full, unmap pages in the cache for real,
> @@ -408,7 +428,7 @@ unmap(struct dir_info *d, void *p, size_
>       rsz = mopts.malloc_cache - d->free_regions_size;
>       if (psz > rsz)
>               tounmap = psz - rsz;
> -     offset = getrbyte();
> +     offset = getrnibble();
>       for (i = 0; tounmap > 0 && i < mopts.malloc_cache; i++) {
>               r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
>               if (r->p != NULL) {
> @@ -489,7 +509,7 @@ map(struct dir_info *d, size_t sz, int z
>               /* zero fill not needed */
>               return p;
>       }
> -     offset = getrbyte();
> +     offset = getrnibble();
>       for (i = 0; i < mopts.malloc_cache; i++) {
>               r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
>               if (r->p != NULL) {
> @@ -536,21 +556,6 @@ map(struct dir_info *d, size_t sz, int z
>       return p;
>  }
>  
> -static void
> -rbytes_init(void)
> -{
> -     arc4random_buf(rbytes, sizeof(rbytes));
> -     rbytesused = 0;
> -}
> -
> -static u_char
> -getrbyte(void)
> -{
> -     if (rbytesused >= sizeof(rbytes))
> -             rbytes_init();
> -     return rbytes[rbytesused++];
> -}
> -
>  /*
>   * Initialize a dir_info, which should have been cleared by caller
>   */
> @@ -1010,7 +1015,7 @@ malloc_bytes(struct dir_info *d, size_t 
>       }
>  
>       /* advance a random # of positions */
> -     i = (getrbyte() & (MALLOC_DELAYED_CHUNKS - 1)) % bp->free;
> +     i = getrnibble() % bp->free;
>       while (i > 0) {
>               u += u;
>               k++;
> @@ -1273,7 +1278,7 @@ ofree(void *p)
>               if (mopts.malloc_junk && sz > 0)
>                       memset(p, SOME_FREEJUNK, sz);
>               if (!mopts.malloc_freeprot) {
> -                     i = getrbyte() & (MALLOC_DELAYED_CHUNKS - 1);
> +                     i = getrnibble();
>                       tmp = p;
>                       p = g_pool->delayed_chunks[i];
>                       g_pool->delayed_chunks[i] = tmp;
> 

-- 
    paranoic mickey       (my employers have changed but, the name has remained)

Reply via email to