]> git.feebdaed.xyz Git - linuxyz.git/commitdiff
rcu update, remove
authorseantywork <seantywork@gmail.com>
Sun, 21 Sep 2025 08:00:30 +0000 (08:00 +0000)
committerseantywork <seantywork@gmail.com>
Sun, 21 Sep 2025 08:00:30 +0000 (08:00 +0000)
krcu-cmap/rcucmap.c

index 7f9dd1a624ff2ed95c9af110fdd9e889e5ec93c9..f26840cc3f5340a4dc277edb99672f926d35336a 100644 (file)
 
 #define OP_COUNT 10
 
-struct myelement {
-  
-       struct list_head node;
-       struct rcu_head rcu;
+struct node {
+    int key;
+    int value;
+       struct list_head _node;
+       struct rcu_head _rcu;
 };
 
-static LIST_HEAD(myelements);
-static spinlock_t myelements_lock;
+struct cc_buck {
+    struct list_head nodes;
+    spinlock_t lock;
+};
+
+struct cc_map {
+    struct cc_buck* buckets;
+    int count;
+};
 
+static struct cc_map* cmap;
 static struct task_struct *task_write;
 static struct task_struct *task_read;
 static int w = 10;
 static int r = 11;
 
+
+static int _hashfunc(__u32 key, __u32 bcount){
+    __u32 hash = ((key >> 16) ^ key) * 0x45d9f3bu;
+    hash = ((hash >> 16) ^ hash) * 0x45d9f3bu;
+    hash = (hash >> 16) ^ hash;
+    return hash % bcount;
+}
+
+static struct cc_map* make_ccmap(int bcount){
+
+    struct cc_map* cmap = (struct cc_map*)kzalloc(sizeof(struct cc_map), GFP_KERNEL);
+    cmap->count = bcount;
+    cmap->buckets = (struct cc_buck*)kzalloc(sizeof(struct cc_buck) * cmap->count, GFP_KERNEL);
+    for(int i = 0; i < cmap->count; i++){
+        spin_lock_init(&cmap->buckets[i].lock);
+        INIT_LIST_HEAD(&cmap->buckets[i].nodes);
+    }
+    return cmap;    
+}
+
+static void _ccmap_cb(struct rcu_head* _rcu){
+    struct node* n = container_of(_rcu, struct node, _rcu);
+    kfree(n);
+}
+
+static int update_ccmap(struct cc_map* cmap, int key, int value){
+    int result = -1;
+    struct node* n = NULL;
+    struct node* old_n = NULL;
+    struct node* new_n = NULL;
+    __u32 idx = _hashfunc((__u32)key, (__u32)cmap->count);
+    rcu_read_lock();
+    spin_lock(&cmap->buckets[idx].lock);
+    list_for_each_entry(n, &cmap->buckets[idx].nodes, _node){
+        if(n->key != key){
+            continue;
+        }
+        old_n = n;
+        break;
+    }
+    new_n = kzalloc(sizeof(struct node), GFP_ATOMIC);
+    if(new_n == NULL){
+        goto done;
+    }
+    if(old_n == NULL){
+        new_n->key = key;
+        new_n->value = value;
+        list_add_rcu(&new_n->_node, &cmap->buckets[idx].nodes);
+    } else {
+        memcpy(new_n, old_n, sizeof(struct node));
+        new_n->value = value;
+        list_replace_rcu(&old_n->_node, &new_n->_node);
+    }
+    result = (int)idx;
+
+done:
+    spin_unlock(&cmap->buckets[idx].lock);
+    rcu_read_unlock();
+//    synchronize_rcu();
+//    if(old_n != NULL && new_n != NULL){
+//        kfree(old_n);
+//    }
+    if(old_n != NULL && new_n != NULL){
+        call_rcu(&old_n->_rcu, _ccmap_cb);
+    }
+    return result;
+}
+
+
+static int remove_ccmap(struct cc_map* cmap, int key){
+    int result = -1;
+    struct node* n = NULL;
+    struct node* found_n = NULL;
+    __u32 idx = _hashfunc((__u32)key, (__u32)cmap->count);
+    rcu_read_lock();
+    spin_lock(&cmap->buckets[idx].lock);
+    list_for_each_entry(n, &cmap->buckets[idx].nodes, _node){
+        if(n->key != key){
+            continue;
+        }
+        found_n = n;
+        break;
+    }
+    if(found_n == NULL){
+        goto done;
+    }
+    list_del_rcu(&found_n->_node);
+    result = (int)idx;
+done:
+    spin_unlock(&cmap->buckets[idx].lock);
+    rcu_read_unlock();
+    if(found_n != NULL){
+        call_rcu(&found_n->_rcu, _ccmap_cb);
+    }
+    return result;
+}
+
+static void delete_ccmap(struct cc_map* cmap){
+    if(cmap == NULL){
+        return;
+    }
+    struct node* n = NULL;
+    struct node* tmp_n = NULL;
+    for(int i = 0; i < cmap->count; i++){
+        spin_lock(&cmap->buckets[i].lock);
+        list_for_each_entry_safe(n, tmp_n, &cmap->buckets[i].nodes, _node){
+            list_del(&n->_node);
+            kfree(n);
+        }
+        spin_unlock(&cmap->buckets[i].lock);
+        kfree(&cmap->buckets[i]);
+    }
+    kfree(cmap);
+
+}
+
 static int task_writer(void *arg){
 
     int v = *(int *)arg;
@@ -52,8 +177,8 @@ static int task_reader(void *arg){
 
 static int __init rcu_cmap_init(void){
 
-    spin_lock_init(&myelements_lock);
 
+    /*
     task_write = kthread_run(task_writer, (void*)&w, "tw/%d", w);
     if(IS_ERR(task_write)){
         printk(KERN_ERR "rcucmap: failed to create task_write thread\n");
@@ -66,17 +191,34 @@ static int __init rcu_cmap_init(void){
     }
     get_task_struct(task_write);
     get_task_struct(task_read);
-
-    printk(KERN_INFO "rcucmap: loaded\n");
+    */
+
+    printk(KERN_INFO "rcucmap: init\n");
+    cmap = make_ccmap(OP_COUNT);
+    printk(KERN_INFO "rcucmap: updating cmap\n");
+    for(int i = 0 ; i < OP_COUNT; i++){
+        int idx = update_ccmap(cmap, i, i);
+        printk(KERN_INFO "update cmap: %d\n", idx);
+    }
+    printk(KERN_INFO "rcucmap: removing from cmap\n");
+    for(int i = 0 ; i < OP_COUNT; i++){
+        int idx = remove_ccmap(cmap, i);
+        printk(KERN_INFO "remove cmap: %d\n", idx);
+    }
+    printk(KERN_INFO "rcucmap: done\n");
 
     return 0;
 }
 
 static void __exit rcu_cmap_exit(void){
+    /*
     kthread_stop(task_write);
     kthread_stop(task_read);
+    */
 
-    printk(KERN_INFO "rcucmap: unloaded\n");
+    printk(KERN_INFO "rcucmap: deleting cmap\n");
+    delete_ccmap(cmap);
+    printk(KERN_INFO "rcucmap: exit\n");
 
 }