00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <rsbac/types.h>
00011 #include <rsbac/rkmem.h>
00012 #include <rsbac/debug.h>
00013 #include <linux/init.h>
00014 #include <linux/kernel.h>
00015 #include <linux/module.h>
00016 #include <linux/slab.h>
00017 #include <linux/vmalloc.h>
00018 #include <linux/timer.h>
00019
00020
00021 typedef struct rsbac_cache_sizes {
00022 size_t cs_size;
00023 kmem_cache_t *cs_cachep;
00024 char name[15];
00025 } rsbac_cache_sizes_t;
00026
00027 static rsbac_cache_sizes_t rsbac_cache_sizes[] = {
00028 #if PAGE_SIZE == 4096
00029 { 32, NULL, "rsbac-32"},
00030 #endif
00031 { 64, NULL, "rsbac-64"},
00032 #if PAGE_SIZE == 4096
00033 { 96, NULL, "rsbac-96"},
00034 #endif
00035 { 128, NULL, "rsbac-128"},
00036 { 192, NULL, "rsbac-192"},
00037 { 256, NULL, "rsbac-256"},
00038 { 512, NULL, "rsbac-512"},
00039 { 1024, NULL, "rsbac-1024"},
00040 { 2048, NULL, "rsbac-2048"},
00041 { 4096, NULL, "rsbac-4096"},
00042 { 8192, NULL, "rsbac-8192"},
00043
00044 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00045 { 16384, NULL, "rsbac-16384"},
00046 { 32768, NULL, "rsbac-32768"},
00047 { 65536, NULL, "rsbac-65536"},
00048 {131072, NULL, "rsbac-131072"},
00049 #ifndef CONFIG_MMU
00050 {262144, NULL, "rsbac-262144"},
00051 {524288, NULL, "rsbac-524288"},
00052 {1048576, NULL, "rsbac-1048576"},
00053 #ifdef CONFIG_LARGE_ALLOCS
00054 {2097152, NULL, "rsbac-2097152"},
00055 {4194304, NULL, "rsbac-4194304"},
00056 {8388608, NULL, "rsbac-8388608"},
00057 {16777216, NULL, "rsbac-16777216"},
00058 {33554432, NULL, "rsbac-33554432"},
00059 #endif
00060 #endif
00061 #endif
00062 { 0, NULL, "rsbac0"}
00063 };
00064 #ifdef CONFIG_RSBAC_INIT_DELAY
00065 void rsbac_kmem_cache_sizes_init(void)
00066 #else
00067 void __init rsbac_kmem_cache_sizes_init(void)
00068 #endif
00069 {
00070 rsbac_cache_sizes_t *sizes = rsbac_cache_sizes;
00071
00072 while (sizes->cs_size) {
00073 sizes->cs_cachep = kmem_cache_create(
00074 sizes->name, sizes->cs_size,
00075 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
00076 if (!sizes->cs_cachep)
00077 BUG();
00078
00079 sizes++;
00080 }
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
00095 EXPORT_SYMBOL(rsbac_kmalloc);
00096 #endif
00097 void * rsbac_kmalloc (size_t size)
00098 {
00099 rsbac_cache_sizes_t *csizep = rsbac_cache_sizes;
00100
00101 if(!size)
00102 return NULL;
00103 for (; csizep->cs_size; csizep++) {
00104 if (size > csizep->cs_size)
00105 continue;
00106 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00107 return kmem_cache_alloc(csizep->cs_cachep, GFP_ATOMIC);
00108 #else
00109 return kmem_cache_alloc(csizep->cs_cachep, GFP_KERNEL);
00110 #endif
00111 }
00112 rsbac_printk(KERN_WARNING
00113 "rsbac_kmalloc: size %u requested, max size is %u!\n",
00114 size, RSBAC_MAX_KMALLOC);
00115 BUG();
00116 return NULL;
00117 }
00118
00119 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
00120 EXPORT_SYMBOL(rsbac_vkmalloc);
00121 #endif
00122 void * rsbac_vkmalloc (size_t size, rsbac_boolean_t * vmalloc_used_p)
00123 {
00124 rsbac_cache_sizes_t *csizep = rsbac_cache_sizes;
00125 void * result;
00126
00127 if(!size)
00128 return NULL;
00129 for (; csizep->cs_size; csizep++) {
00130 if (size > csizep->cs_size)
00131 continue;
00132 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00133 result = kmem_cache_alloc(csizep->cs_cachep, GFP_ATOMIC);
00134 #else
00135 result = kmem_cache_alloc(csizep->cs_cachep, GFP_KERNEL);
00136 #endif
00137 if(result)
00138 {
00139 if(vmalloc_used_p)
00140 *vmalloc_used_p = FALSE;
00141 return result;
00142 }
00143 }
00144 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00145 return NULL;
00146 #else
00147 if(vmalloc_used_p)
00148 *vmalloc_used_p = TRUE;
00149 return vmalloc(size);
00150 #endif
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
00163 EXPORT_SYMBOL(rsbac_kfree);
00164 #endif
00165 void rsbac_kfree (const void *objp)
00166 {
00167 kfree(objp);
00168 }
00169
00170 static void wakeup_kfree(u_long dk_dummy)
00171 {
00172 struct rsbac_delayed_kfree_t * dk_p = (struct rsbac_delayed_kfree_t *) dk_dummy;
00173
00174 kfree(dk_p->objp);
00175 kfree(dk_p);
00176 }
00177
00178 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
00179 EXPORT_SYMBOL(rsbac_delayed_kfree);
00180 #endif
00181 void rsbac_delayed_kfree(void *objp, rsbac_time_t delay)
00182 {
00183 struct rsbac_delayed_kfree_t * dk_p;
00184
00185 if(!objp)
00186 return;
00187 dk_p = rsbac_kmalloc(sizeof(*dk_p));
00188 if(!dk_p)
00189 return;
00190
00191 dk_p->objp = objp;
00192 init_timer(&dk_p->timer);
00193 dk_p->timer.function = wakeup_kfree;
00194 dk_p->timer.data = (u_long) dk_p;
00195 dk_p->timer.expires = jiffies + delay * HZ;
00196 add_timer(&dk_p->timer);
00197 }
00198
00199 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
00200 EXPORT_SYMBOL(rsbac_vkfree);
00201 #endif
00202 void rsbac_vkfree(void *objp, rsbac_boolean_t vmalloc_used)
00203 {
00204 if(vmalloc_used)
00205 vfree(objp);
00206 else
00207 kfree(objp);
00208 }
00209
00210