[Sheepdog] [PATCH 2/5] sheep: add some candy helpers in util.c

MORITA Kazutaka morita.kazutaka at lab.ntt.co.jp
Wed Nov 16 06:14:03 CET 2011


At Tue, 15 Nov 2011 11:16:43 +0800,
Liu Yuan wrote:
> 
> From: Liu Yuan <tailai.ly at taobao.com>
> 
> These are trivial helper wrappers around standard IO functions
> and interger hash function. "stolen" from git and Linux kernel.
> 
> Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
> ---
>  include/util.h |   63 +++++++++++++++++++++++
>  sheep/util.c   |  150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 213 insertions(+), 0 deletions(-)
>  create mode 100644 sheep/util.c
> 
> diff --git a/include/util.h b/include/util.h
> index 2dccd16..c73a6d5 100644
> --- a/include/util.h
> +++ b/include/util.h
> @@ -2,6 +2,8 @@
>  #define __UTIL_H__
>  
>  #include <string.h>
> +#include <limits.h>
> +#include <stdint.h>
>  
>  #include "bitops.h"
>  
> @@ -53,4 +55,65 @@ static inline void *zalloc(size_t size)
>  	return calloc(1, size);
>  }
>  
> +typedef void (*try_to_free_t)(size_t);
> +extern try_to_free_t set_try_to_free_routine(try_to_free_t);
> +
> +extern void *xmalloc(size_t size);
> +extern void *xzalloc(size_t size);
> +extern void *xrealloc(void *ptr, size_t size);
> +extern void *xcalloc(size_t nmemb, size_t size);
> +extern ssize_t xread(int fd, void *buf, size_t len);
> +extern ssize_t xwrite(int fd, const void *buf, size_t len);
> +
> +/* Integer hash functions, taken from Linux kernel.
> + * Use hash_long() to get most out of your cpu.
> + */
> +
> +/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
> +#define GOLDEN_RATIO_PRIME_32 0x9e370001UL
> +/*  2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
> +#define GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001UL
> +
> +#if __SIZEOF_POINTER__ == 4
> +#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_PRIME_32
> +#define hash_long(val, bits) hash_32(val, bits)
> +#elif __SIZEOF_POINTER__ == 8
> +#define hash_long(val, bits) hash_64(val, bits)
> +#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_PRIME_64
> +#else
> +#error Wordsize not 32 or 64
> +#endif
> +
> +static inline uint64_t hash_64(uint64_t val, unsigned int bits)
> +{
> +        uint64_t hash = val;
> +
> +        /*  Sigh, gcc can't optimise this alone like it does for 32 bits. */
> +        uint64_t n = hash;
> +        n <<= 18;
> +        hash -= n;
> +        n <<= 33;
> +        hash -= n;
> +        n <<= 3;
> +        hash += n;
> +        n <<= 3;
> +        hash -= n;
> +        n <<= 4;
> +        hash += n;
> +        n <<= 2;
> +        hash += n;
> +
> +        /* High bits are more random, so use them. */
> +        return hash >> (64 - bits);
> +}
> +
> +static inline uint32_t hash_32(uint32_t val, unsigned int bits)
> +{
> +        /* On some cpus multiply is faster, on others gcc will do shifts */
> +        uint32_t hash = val * GOLDEN_RATIO_PRIME_32;
> +
> +        /* High bits are more random, so use them. */
> +        return hash >> (32 - bits);
> +}

We already have a hash function, fnv_64a_buf().  How about using it
instead of introducing new one?

Thanks,

Kazutaka

> +
>  #endif
> diff --git a/sheep/util.c b/sheep/util.c
> new file mode 100644
> index 0000000..ebcc1d8
> --- /dev/null
> +++ b/sheep/util.c
> @@ -0,0 +1,150 @@
> +/* 
> + * Taken from git and Linux kernel by Liu Yuan <namei.unix at gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License version
> + * 2 as published by the Free Software Foundation.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <unistd.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +
> +#include "util.h"
> +#include "logger.h"
> +
> +static void do_nothing(size_t size)
> +{
> +}
> +
> +static void (*try_to_free_routine)(size_t size) = do_nothing;
> +
> +try_to_free_t set_try_to_free_routine(try_to_free_t routine)
> +{
> +        try_to_free_t old = try_to_free_routine;
> +        if (!routine)
> +                routine = do_nothing;
> +        try_to_free_routine = routine;
> +        return old;
> +}
> +
> +void *xmalloc(size_t size)
> +{
> +        void *ret = malloc(size);
> +        if (!ret && !size)
> +                ret = malloc(1);
> +        if (!ret) {
> +                try_to_free_routine(size);
> +                ret = malloc(size);
> +                if (!ret && !size)
> +                        ret = malloc(1);
> +                if (!ret)
> +                        panic("Out of memory");
> +        }
> +        return ret;
> +}
> +
> +void *xzalloc(size_t size)
> +{
> +        void *ret;
> +        ret = xmalloc(size);
> +        memset(ret, 0, size);
> +        return ret;
> +}
> +
> +void *xrealloc(void *ptr, size_t size)
> +{
> +        void *ret = realloc(ptr, size);
> +        if (!ret && !size)
> +                ret = realloc(ptr, 1);
> +        if (!ret) {
> +                try_to_free_routine(size);
> +                ret = realloc(ptr, size);
> +                if (!ret && !size)
> +                        ret = realloc(ptr, 1);
> +                if (!ret)
> +                        panic("Out of memory");
> +        }
> +        return ret;
> +}
> +
> +void *xcalloc(size_t nmemb, size_t size)
> +{
> +        void *ret = calloc(nmemb, size);
> +        if (!ret && (!nmemb || !size))
> +                ret = calloc(1, 1);
> +        if (!ret) {
> +                try_to_free_routine(nmemb * size);
> +                ret = calloc(nmemb, size);
> +                if (!ret && (!nmemb || !size))
> +                        ret = calloc(1, 1);
> +                if (!ret)
> +                        panic("Out of memory");
> +        }
> +        return ret;
> +}
> +
> +static ssize_t _read(int fd, void *buf, size_t len)
> +{
> +        ssize_t nr;
> +        while (1) {
> +                nr = read(fd, buf, len);
> +                if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
> +                        continue;
> +                return nr;
> +        }
> +}
> +
> +static ssize_t _write(int fd, const void *buf, size_t len)
> +{
> +        ssize_t nr;
> +        while (1) {
> +                nr = write(fd, buf, len);
> +                if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
> +                        continue;
> +                return nr;
> +        }
> +}
> +
> +ssize_t xread(int fd, void *buf, size_t count)
> +{
> +        char *p = buf;
> +        ssize_t total = 0;
> +
> +        while (count > 0) {
> +                ssize_t loaded = _read(fd, p, count);
> +                if (loaded < 0)
> +                        return -1;
> +                if (loaded == 0)
> +                        return total;
> +                count -= loaded;
> +                p += loaded;
> +                total += loaded;
> +        }
> +
> +        return total;
> +}
> +
> +ssize_t xwrite(int fd, const void *buf, size_t count)
> +{
> +        const char *p = buf;
> +        ssize_t total = 0;
> +
> +        while (count > 0) {
> +                ssize_t written = _write(fd, p, count);
> +                if (written < 0)
> +                        return -1;
> +                if (!written) {
> +                        errno = ENOSPC;
> +                        return -1;
> +                }
> +                count -= written;
> +                p += written;
> +                total += written;
> +        }
> +
> +        return total;
> +}
> -- 
> 1.7.6.1
> 
> -- 
> sheepdog mailing list
> sheepdog at lists.wpkg.org
> http://lists.wpkg.org/mailman/listinfo/sheepdog



More information about the sheepdog mailing list