diff options
author | Patrick Mochel <mochel@osdl.org> | 2003-01-06 23:38:43 -0600 |
---|---|---|
committer | Patrick Mochel <mochel@osdl.org> | 2003-01-06 23:38:43 -0600 |
commit | eeacc9367455a3bbbed00ced63a06c65fe347784 (patch) | |
tree | 55b12e320e6065468186214509cc08076e0fb32f /lib | |
parent | 351b11abdb0c25cb383b8e881939a6e2f3d64c28 (diff) | |
parent | a34aca8a2ee295cc711418518f1d8c9fe099833d (diff) | |
download | history-eeacc9367455a3bbbed00ced63a06c65fe347784.tar.gz |
Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
Diffstat (limited to 'lib')
-rw-r--r-- | lib/crc32.c | 4 | ||||
-rw-r--r-- | lib/radix-tree.c | 89 |
2 files changed, 66 insertions, 27 deletions
diff --git a/lib/crc32.c b/lib/crc32.c index b3defb2db34563..01db3a187bc163 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -92,7 +92,7 @@ u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len) crc = __cpu_to_le32(crc); /* Align it */ - for ( ; ((u32)b)&3 && len ; len--){ + for ( ; ((long)b)&3 && len ; len--){ # ifdef __LITTLE_ENDIAN crc = (crc>>8) ^ crc32table_le[ (crc ^ *((u8 *)b)++) & 0xff ]; # else @@ -201,7 +201,7 @@ u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len) crc = __cpu_to_be32(crc); /* Align it */ - for ( ; ((u32)b)&3 && len ; len--){ + for ( ; ((long)b)&3 && len ; len--){ # ifdef __LITTLE_ENDIAN crc = (crc>>8) ^ crc32table_be[ (crc ^ *((u8 *)b)++) & 0xff ]; # else diff --git a/lib/radix-tree.c b/lib/radix-tree.c index c13196a91c7a43..dc20f8513946c1 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -20,10 +20,11 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/kernel.h> -#include <linux/mempool.h> #include <linux/module.h> #include <linux/radix-tree.h> +#include <linux/percpu.h> #include <linux/slab.h> +#include <linux/gfp.h> #include <linux/string.h> /* @@ -49,18 +50,74 @@ struct radix_tree_path { * Radix tree node cache. */ static kmem_cache_t *radix_tree_node_cachep; -static mempool_t *radix_tree_node_pool; -static inline struct radix_tree_node * +/* + * Per-cpu pool of preloaded nodes + */ +struct radix_tree_preload { + int nr; + struct radix_tree_node *nodes[RADIX_TREE_MAX_PATH]; +}; +DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, }; + +/* + * This assumes that the caller has performed appropriate preallocation, and + * that the caller has pinned this thread of control to the current CPU. + */ +static struct radix_tree_node * radix_tree_node_alloc(struct radix_tree_root *root) { - return mempool_alloc(radix_tree_node_pool, root->gfp_mask); + struct radix_tree_node *ret; + + ret = kmem_cache_alloc(radix_tree_node_cachep, root->gfp_mask); + if (ret == NULL && !(root->gfp_mask & __GFP_WAIT)) { + struct radix_tree_preload *rtp; + + rtp = &__get_cpu_var(radix_tree_preloads); + if (rtp->nr) { + ret = rtp->nodes[rtp->nr - 1]; + rtp->nodes[rtp->nr - 1] = NULL; + rtp->nr--; + } + } + return ret; } static inline void radix_tree_node_free(struct radix_tree_node *node) { - mempool_free(node, radix_tree_node_pool); + kmem_cache_free(radix_tree_node_cachep, node); +} + +/* + * Load up this CPU's radix_tree_node buffer with sufficient objects to + * ensure that the addition of a single element in the tree cannot fail. On + * success, return zero, with preemption disabled. On error, return -ENOMEM + * with preemption not disabled. + */ +int radix_tree_preload(int gfp_mask) +{ + struct radix_tree_preload *rtp; + struct radix_tree_node *node; + int ret = -ENOMEM; + + preempt_disable(); + rtp = &__get_cpu_var(radix_tree_preloads); + while (rtp->nr < ARRAY_SIZE(rtp->nodes)) { + preempt_enable(); + node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask); + if (node == NULL) + goto out; + preempt_disable(); + rtp = &__get_cpu_var(radix_tree_preloads); + if (rtp->nr < ARRAY_SIZE(rtp->nodes)) + rtp->nodes[rtp->nr++] = node; + else + kmem_cache_free(radix_tree_node_cachep, node); + } + ret = 0; +out: + return ret; } /* @@ -339,26 +396,12 @@ int radix_tree_delete(struct radix_tree_root *root, unsigned long index) } EXPORT_SYMBOL(radix_tree_delete); -static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags) +static void +radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags) { memset(node, 0, sizeof(struct radix_tree_node)); } -static void *radix_tree_node_pool_alloc(int gfp_mask, void *data) -{ - return kmem_cache_alloc(radix_tree_node_cachep, gfp_mask); -} - -static void radix_tree_node_pool_free(void *node, void *data) -{ - kmem_cache_free(radix_tree_node_cachep, node); -} - -/* - * FIXME! 512 nodes is 200-300k of memory. This needs to be - * scaled by the amount of available memory, and hopefully - * reduced also. - */ void __init radix_tree_init(void) { radix_tree_node_cachep = kmem_cache_create("radix_tree_node", @@ -366,8 +409,4 @@ void __init radix_tree_init(void) 0, radix_tree_node_ctor, NULL); if (!radix_tree_node_cachep) panic ("Failed to create radix_tree_node cache\n"); - radix_tree_node_pool = mempool_create(512, radix_tree_node_pool_alloc, - radix_tree_node_pool_free, NULL); - if (!radix_tree_node_pool) - panic ("Failed to create radix_tree_node pool\n"); } |