aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-05-24 17:12:57 +0000
committerNick Mathewson <nickm@torproject.org>2007-05-24 17:12:57 +0000
commitd3d86b17a761011f62dc2e06c04c0af8f1a75ef6 (patch)
treeefb329c2d77ef6f39c02db8db62bfa18ad5f4d6d /src/common
parentd0a5c4f9848f44c46f001428bd3078673033ef19 (diff)
downloadtor-d3d86b17a761011f62dc2e06c04c0af8f1a75ef6.tar
tor-d3d86b17a761011f62dc2e06c04c0af8f1a75ef6.tar.gz
r12916@catbus: nickm | 2007-05-24 12:43:45 -0400
Add math functions to round values to the nearest power of 2. Make mempools more careful about making sure that the size of their chunks is a little less than a power of 2, not a little more. svn:r10304
Diffstat (limited to 'src/common')
-rw-r--r--src/common/compat.h2
-rw-r--r--src/common/mempool.c14
-rw-r--r--src/common/util.c48
-rw-r--r--src/common/util.h4
4 files changed, 64 insertions, 4 deletions
diff --git a/src/common/compat.h b/src/common/compat.h
index 085af036d..cd3643740 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -96,6 +96,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
#if defined(__GNUC__) && __GNUC__ >= 3
#define ATTR_NORETURN __attribute__((noreturn))
#define ATTR_PURE __attribute__((pure))
+#define ATTR_CONST __attribute__((const))
#define ATTR_MALLOC __attribute__((malloc))
#define ATTR_NORETURN __attribute__((noreturn))
#define ATTR_NONNULL(x) __attribute__((nonnull x))
@@ -108,6 +109,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
#else
#define ATTR_NORETURN
#define ATTR_PURE
+#define ATTR_CONST
#define ATTR_MALLOC
#define ATTR_NORETURN
#define ATTR_NONNULL(x)
diff --git a/src/common/mempool.c b/src/common/mempool.c
index 2b1775c1b..665a803af 100644
--- a/src/common/mempool.c
+++ b/src/common/mempool.c
@@ -361,18 +361,24 @@ mp_pool_new(size_t item_size, size_t chunk_capacity)
/* Now we figure out how many items fit in each chunk. We need to fit at
* least 2 items per chunk. No chunk can be more than MAX_CHUNK bytes long,
* or less than MIN_CHUNK. */
- /* XXXX020 Try a bit harder here: we want to be a bit less than a power of
- 2, not a bit over. */
if (chunk_capacity > MAX_CHUNK)
chunk_capacity = MAX_CHUNK;
- if (chunk_capacity < alloc_size * 2 + CHUNK_OVERHEAD)
- chunk_capacity = alloc_size * 2 + CHUNK_OVERHEAD;
+ /* Try to be around a power of 2 in size, since that's what allocators like
+ * handing out. 512K-1 byte is a lot better than 512K+1 byte. */
+ chunk_capacity = (size_t) round_to_power_of_2(chunk_capacity);
+ while (chunk_capacity < alloc_size * 2 + CHUNK_OVERHEAD)
+ chunk_capacity *= 2;
if (chunk_capacity < MIN_CHUNK)
chunk_capacity = MIN_CHUNK;
pool->new_chunk_capacity = (chunk_capacity-CHUNK_OVERHEAD) / alloc_size;
pool->item_alloc_size = alloc_size;
+ log_debug(LD_MM, "Capacity is %lu, item size is %lu, alloc size is %lu",
+ (unsigned long)pool->new_chunk_capacity,
+ (unsigned long)pool->item_alloc_size,
+ (unsigned long)(pool->new_chunk_capacity*pool->item_alloc_size));
+
return pool;
}
diff --git a/src/common/util.c b/src/common/util.c
index d4a30a145..7ca08363d 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -214,6 +214,54 @@ _tor_free(void *mem)
}
/* =====
+ * Math
+ * ===== */
+
+/** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */
+int
+tor_log2(uint64_t u64)
+{
+ int r = 0;
+ if (u64 >= (U64_LITERAL(1)<<32)) {
+ u64 >>= 32;
+ r = 32;
+ }
+ if (u64 >= (U64_LITERAL(1)<<16)) {
+ u64 >>= 16;
+ r += 16;
+ }
+ if (u64 >= (U64_LITERAL(1)<<8)) {
+ u64 >>= 8;
+ r += 8;
+ }
+ if (u64 >= (U64_LITERAL(1)<<4)) {
+ u64 >>= 4;
+ r += 4;
+ }
+ if (u64 >= (U64_LITERAL(1)<<2)) {
+ u64 >>= 2;
+ r += 2;
+ }
+ if (u64 >= (U64_LITERAL(1)<<1)) {
+ u64 >>= 1;
+ r += 1;
+ }
+ return r;
+}
+
+/** Return the power of 2 closest to <b>u64</b>. */
+uint64_t
+round_to_power_of_2(uint64_t u64)
+{
+ int lg2 = tor_log2(u64);
+ uint64_t low = U64_LITERAL(1) << lg2, high = U64_LITERAL(1) << (lg2+1);
+ if (high - u64 < u64 - low)
+ return high;
+ else
+ return low;
+}
+
+/* =====
* String manipulation
* ===== */
diff --git a/src/common/util.h b/src/common/util.h
index 6b32708c5..f04160935 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -142,6 +142,10 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
/** Macro: true if two values have different boolean values. */
#define bool_neq(a,b) (!(a)!=!(b))
+/* Math functions */
+int tor_log2(uint64_t u64) ATTR_CONST;
+uint64_t round_to_power_of_2(uint64_t u64);
+
/* String manipulation */
/** Allowable characters in a hexadecimal string. */