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

Liu Yuan namei.unix at gmail.com
Tue Nov 15 04:16:43 CET 2011


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);
+}
+
 #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




More information about the sheepdog mailing list