Commit ec790197 authored by Muktesh Khole's avatar Muktesh Khole Committed by Vikram Narayanan

added memory reclaim feature

parent 32ecf3ff
......@@ -23,15 +23,10 @@ int lcd_init_cspace(struct cspace *cspace) {
return -ENOMEM;
};
cspace->cdt_root_cache = KMEM_CACHE(cdt_root_node, 0);
if(!cspace->cdt_root_cache){
printk(KERN_ERR "lcd_cap Failed to allocate cdt_root slab\n");
return -ENOMEM;
};
cspace->cnode_table = kmem_cache_alloc(cspace->cnode_table_cache, 0);
for (i = 0; i < MAX_SLOTS_PER_TABLE; i++)
{
spin_lock_init(&(cspace->cnode_table->cnode[i].lock));
cspace->cnode_table->cnode[i].type = LCD_CAP_TYPE_FREE;
cspace->cnode_table->table_level = 0;
}
......@@ -108,7 +103,6 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
{
unsigned long flags, flags_cnode_lock;
struct cnode *cnode;
struct cdt_root_node *cdt_node;
spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID)
......@@ -125,7 +119,6 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
cnode->object = object;
spin_lock_irqsave(&cnode->lock, flags_cnode_lock);
cdt_node = kmem_cache_alloc(cspace->cdt_root_cache, 0);
spin_unlock_irqrestore(&cspace->lock, flags);
cnode->cap = cap;
......@@ -135,13 +128,9 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
cnode->prev = NULL;
cnode->child = NULL;
cnode->type = type;
cnode->cdt_root = cdt_node;
cnode->cdt_root->state = ALLOCATION_VALID;
cnode->cdt_root->node_count = 0;
spin_lock_init(&(cnode->cdt_root->lock));
cnode->cdt_root = get_cdt_root();
cnode->cdt_root->cnode = cnode;
cnode->cdt_root->node_count = 1;
cnode->cdt_root->state = ALLOCATION_VALID;
//lcd_cnode_release(cnode);
spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock);
......@@ -193,19 +182,10 @@ void lcd_cap_delete(struct cspace *cspace, capability_t cap) {
spin_unlock_irqrestore(&cnode->lock, flags_cnode_lock);
if (done) {
lcd_free_cap(&(cspace->cap_cache), cap);
if (last_node) {
// at this point we are not holding any locks
// so its ok to request for cspace lock
spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID) {
spin_unlock_irqrestore(&cspace->lock, flags);
return;
}
cdt_node->state = ALLOCATION_REMOVED;
kmem_cache_free(cspace->cdt_root_cache, cdt_node);
spin_unlock_irqrestore(&(cspace->lock), flags);
free_cdt_root(cdt_node);
}
lcd_free_cap(&(cspace->cap_cache), cap);
} else {
// someone is using CDT root
// wait for him to finish
......@@ -414,19 +394,10 @@ int lcd_cap_revoke(struct cspace *cspace, capability_t cap) {
if (done) {
lcd_free_cap(&(cspace->cap_cache), cap);
if (last_node) {
// at this point we are not holding any locks
// so its ok to request for cspace lock
spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID) {
spin_unlock_irqrestore(&cspace->lock, flags);
return 0;
}
cdt_node->state = ALLOCATION_REMOVED;
kmem_cache_free(cspace->cdt_root_cache, cdt_node);
spin_unlock_irqrestore(&(cspace->lock), flags);
free_cdt_root(cdt_node);
}
lcd_free_cap(&(cspace->cap_cache), cap);
} else {
// someone is using CDT root
// wait for him to finish
......@@ -438,6 +409,23 @@ int lcd_cap_revoke(struct cspace *cspace, capability_t cap) {
};
EXPORT_SYMBOL(lcd_cap_revoke);
int lcd_cap_destroy_cspace(struct cspace *cspace) {
int res;
unsigned long flags;
spin_lock_irqsave(&cspace->lock, flags);
if (cspace->state != ALLOCATION_VALID)
{
spin_unlock_irqrestore(&cspace->lock, flags);
return -EIDRM;
}
cspace->state = ALLOCATION_MARKED_FOR_DELETE;
spin_unlock_irqrestore(&cspace->lock, flags);
res = _lcd_delete_table(cspace, cspace->cnode_table);
return res;
};
EXPORT_SYMBOL(lcd_cap_destroy_cspace);
int lcd_cnode_insert(struct cspace *cspace, capability_t cap, struct cnode *cnode) {
/* XXX: not clear */
return 0;
......@@ -547,4 +535,60 @@ bool _lcd_delete_node (struct cnode *cnode){
last_node = true;
}
return last_node;
}
\ No newline at end of file
}
int _lcd_delete_table(struct cspace *cspace, struct cnode_table *table) {
unsigned long flags;
capability_t index = MAX_CAP_SLOTS;
struct cnode *cnode;
struct cdt_root_node *cdt_node;
bool last_node = false;
if (table == NULL || table->cnode[index].type == LCD_CAP_TYPE_FREE) {
return -EINVAL;
}
while (index < MAX_SLOTS_PER_TABLE) {
_lcd_delete_table(cspace, table->cnode[index].object);
// traversal through cnode_table happens only after locking cspace and checking if cspace is valid.
// we have already marked cspace as invalid so insert, revoke and delete cannot reach here.
table->cnode[index].type = LCD_CAP_TYPE_FREE;
index++;
}
index = 0;
while (index < MAX_CAP_SLOTS) {
spin_lock_irqsave(&(table->cnode[index].lock), flags);
if (table->cnode[index].type == LCD_CAP_TYPE_FREE) {
index++;
spin_unlock_irqrestore(&(table->cnode[index].lock), flags);
continue;
}
cnode = &(table->cnode[index]);
if (spin_trylock(&(cnode->cdt_root->lock))) {
cdt_node = cnode->cdt_root;
last_node = _lcd_delete_node(cnode);
if (last_node) {
cdt_node->state = ALLOCATION_MARKED_FOR_DELETE;
}
cnode->cdt_root = NULL;
spin_unlock(&(cdt_node->lock));
spin_unlock_irqrestore(&(cnode->lock), flags);
lcd_free_cap(&(cspace->cap_cache), cnode->cap);
index++;
} else {
spin_unlock_irqrestore(&(table->cnode[index].lock), flags);
msleep(1);
}
if (last_node) {
free_cdt_root(cdt_node);
last_node = false;
}
}
// no locks are being held till here
spin_lock_irqsave(&cspace->lock, flags);
kmem_cache_free(cspace->cnode_table_cache, table);
spin_unlock_irqrestore(&cspace->lock, flags);
return 0;
}
\ No newline at end of file
......@@ -8,12 +8,29 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <lcd/cap.h>
#include "test.h"
struct cdt_cache_t {
spinlock_t lock;
struct kmem_cache *cdt_root_cache;
};
struct cdt_cache_t cdt_cache;
int __init api_init(void)
{
bool res = true;
printk(KERN_ERR "lcd cspace entering module");
printk(KERN_ERR "lcd_cap entering module");
spin_lock_init(&(cdt_cache.lock));
cdt_cache.cdt_root_cache = KMEM_CACHE(cdt_root_node, 0);
if(!cdt_cache.cdt_root_cache){
printk(KERN_ERR "lcd_cap Failed to initialize cdt_root_node allocator\n");
return -ENOMEM;
};
res = begintests();
if (res == false) {
printk(KERN_ERR "tests failed");
......@@ -29,6 +46,27 @@ void __exit api_exit(void)
return;
}
struct cdt_root_node * get_cdt_root(void) {
unsigned long flags;
struct cdt_root_node *cdt_node;
spin_lock_irqsave(&cdt_cache.lock, flags);
cdt_node = kmem_cache_alloc(cdt_cache.cdt_root_cache, 0);
cdt_node->state = ALLOCATION_VALID;
spin_lock_init(&(cdt_node->lock));
cdt_node->node_count = 0;
spin_unlock_irqrestore(&cdt_cache.lock, flags);
return cdt_node;
}
void free_cdt_root(struct cdt_root_node *cdt_node) {
unsigned long flags;
spin_lock_irqsave(&cdt_cache.lock, flags);
cdt_node->state = ALLOCATION_REMOVED;
cdt_node->node_count = 0;
kmem_cache_free(cdt_cache.cdt_root_cache, cdt_node);
spin_unlock_irqrestore(&cdt_cache.lock, flags);
}
module_init(api_init);
module_exit(api_exit);
......@@ -36,6 +36,15 @@ bool begintests(void) {
} else {
printk(KERN_INFO "lcd_cap_test test_revoke() Succeeded\n");
}
res = test_cspace_destroy();
if (res == TEST_FAILED) {
printk(KERN_ERR "lcd_cap_test test_cspace_destroy() failed\n");
return false;
} else {
printk(KERN_INFO "lcd_cap_test test_cspace_destroy() Succeeded\n");
}
return true;
}
......@@ -123,7 +132,7 @@ void test_delete(void) {
test_cap_grant_count2 = 0;
}
bool test_revoke() {
bool test_revoke(void) {
// this inherently tests delete functionality
int i = 0;
int res;
......@@ -141,4 +150,18 @@ bool test_revoke() {
test_cap_grant_count = 0;
test_cap_grant_count2 = 0;
return ret;
}
bool test_cspace_destroy(void) {
bool res = false;
int ret = -1;
res = test_insert();
if (res) {
printk(KERN_INFO "lcd_cap_test insert succeeded");
ret = lcd_cap_destroy_cspace(&test_cspace);
} else {
printk(KERN_ERR "lcd_cap_test insert failed");
}
return ret == 0;
}
\ No newline at end of file
......@@ -4,9 +4,10 @@ extern int lcd_init_cspace(struct cspace *cspace);
extern int lcd_cap_insert(struct cspace *cspace, capability_t cap,
void *object, enum lcd_cap_type type);
extern void lcd_cap_delete(struct cspace *cspace, capability_t cap);
extern int lcd_cap_destroy_cspace(struct cspace *cspace);
bool test_insert(void);
bool test_grant(void);
void test_delete(void);
bool test_revoke(void);
bool test_cspace_destroy(void);
bool begintests(void);
\ No newline at end of file
......@@ -22,9 +22,13 @@
// should always be 2^CAP_IDENTIFIER_BITS + 2^TABLE_IDENTIFIER_BITS
#define MAX_SLOTS_PER_TABLE 6
struct cdt_root_node;
struct cnode;
struct cspace;
extern struct cdt_root_node * get_cdt_root(void);
extern void free_cdt_root(struct cdt_root_node *cdt_node);
enum lcd_cap_type
{
LCD_CAP_TYPE_INVALID,
......@@ -59,7 +63,6 @@ struct cnode {
struct cnode_table {
struct cnode cnode[MAX_SLOTS_PER_TABLE];
uint8_t table_Id;
uint8_t table_level;
};
......@@ -67,13 +70,13 @@ struct cspace {
spinlock_t lock;
enum allocation_state state;
struct cnode_table *cnode_table;
struct kmem_cache *cdt_root_cache;
struct kmem_cache *cnode_table_cache;
struct cap_cache cap_cache;
};
bool _get_level_bits(int table_level, capability_t cap, capability_t *levelId);
bool _lcd_delete_node (struct cnode *cnode);
int _lcd_delete_table(struct cspace *cspace, struct cnode_table *table);
int lcd_cap_init_cspace(struct cspace *cspace);
struct cnode *lcd_cnode_lookup(struct cspace *cspace, capability_t cap, bool alloc);
......@@ -82,4 +85,5 @@ int lcd_cap_insert(struct cspace *cspace, capability_t cap,
void lcd_cap_delete(struct cspace *cspace, capability_t cap);
int lcd_cap_grant(struct cspace *cspacesrc, capability_t capsrc, struct cspace *cspacedst, capability_t capdst);
int lcd_cap_revoke(struct cspace *cspace, capability_t cap);
int lcd_cap_destroy_cspace(struct cspace *cspace);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment