Skip to content

Commit

Permalink
Merge pull request #7 from jimin-kiim/assignment-10
Browse files Browse the repository at this point in the history
Assignment 10, 11 Synchronization; atomic operations and linked list with synchronization, vm.dirty_ratio Test
  • Loading branch information
jimin-kiim authored Jan 6, 2024
2 parents 99f83d7 + 488a147 commit 0551d2d
Show file tree
Hide file tree
Showing 25 changed files with 4,814 additions and 17 deletions.
12 changes: 12 additions & 0 deletions assignment10/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
obj-m := compare_and_swap_module.o test_and_set_module.o fetch_and_add_module.o \
spinlock_module_final.o mutex_module_final.o rw_semaphore_module_final.o
spinlock_module_final-y := spinlock_module.o calclock.o
mutex_module_final-y := mutex_module.o calclock.o
rw_semaphore_module_final-y := rw_semaphore_module.o calclock.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
20 changes: 20 additions & 0 deletions assignment10/calclock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "calclock.h"
unsigned long long calclock(struct timespec *myclock,
unsigned long long *total_time, unsigned long long *total_count)

{
unsigned long long timedelay = 0, temp = 0, temp_n = 0;
if (myclock[1].tv_nsec >= myclock[0].tv_nsec) {
temp = myclock[1].tv_sec - myclock[0].tv_sec;
temp_n = myclock[1].tv_nsec - myclock[0].tv_nsec;
timedelay = BILLION * temp + temp_n;
} else {
temp = myclock[1].tv_sec - myclock[0].tv_sec - 1;
temp_n = BILLION + myclock[1].tv_nsec - myclock[0].tv_nsec;
timedelay = BILLION * temp + temp_n;
}
__sync_fetch_and_add(total_time, timedelay);
__sync_fetch_and_add(total_count, 1);
return timedelay;
}

12 changes: 12 additions & 0 deletions assignment10/calclock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef __CALCLOCK_H
#define __CALCLOCK_H

#include <linux/time.h>

#define BILLION 1000000000UL

unsigned long long calclock(struct timespec *myclock,
unsigned long long *total_time, unsigned long long *total_clock);

#endif

8 changes: 8 additions & 0 deletions assignment10/compare_and_swap_module/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
obj-m := compare_and_swap_module.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
47 changes: 47 additions & 0 deletions assignment10/compare_and_swap_module/compare_and_swap_module.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// #--------- compare_and_swap_module.c ---------#
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/atomic.h>
#include <linux/delay.h>

#define NUM_THREADS 4
static struct task_struct *threads[NUM_THREADS];
int counter = 0;


static int compare_and_swap_function(void *data)
{
int original;
while(!kthread_should_stop()) {
// critical section
original = __sync_val_compare_and_swap(&counter, counter, counter + 1);
// end of the critical section
printk(KERN_INFO "pid[%u] %s: counter: %d\n", current->pid, __func__, original);
msleep(500);
}
do_exit(0);
}


int __init compare_and_swap_module_init(void) {
printk("Entering Compare and Swap Module!");
int i;
for (i = 0; i < NUM_THREADS; i++) {
threads[i] = kthread_run(compare_and_swap_function, NULL, "compare_and_swap_function");
}
return 0;
}

void __exit compare_and_swap_module_cleanup(void) {
int i;
for(i = 0; i < NUM_THREADS; i++) {
kthread_stop(threads[i]);
}
printk("Exiting Compare and Swap Module!\n");
}

module_init(compare_and_swap_module_init);
module_exit(compare_and_swap_module_cleanup);
MODULE_LICENSE("GPL");
8 changes: 8 additions & 0 deletions assignment10/fetch_and_add_module/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
obj-m := fetch_and_add_module.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
48 changes: 48 additions & 0 deletions assignment10/fetch_and_add_module/fetch_and_add_module.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// #--------- fetch_and_add_module.c ---------#
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/atomic.h>
#include <linux/delay.h>

#define NUM_THREADS 4
static struct task_struct *threads[NUM_THREADS];

static int counter = 0;
static int fetch_and_add_function(void *data)
{
int original;
while(!kthread_should_stop()) {
// critical section
original = __sync_fetch_and_add(&counter, 1);
// end of the critical section
printk(KERN_INFO "pid[%u] %s: counter: %d\n", current->pid, __func__, original);
msleep(500);
}
do_exit(0);
}


int __init fetch_and_add_module_init(void) {
printk("Entering Fetch and Add Module!");
int i;
for (i = 0; i < NUM_THREADS; i++) {
threads[i] = kthread_run(fetch_and_add_function, NULL, "fetch_and_add_function");
}
return 0;
}

void __exit fetch_and_add_module_cleanup(void) {
int i;
for (i = 0; i < NUM_THREADS; i++) {
kthread_stop(threads[i]);
}
printk("Exiting Fetch and Add Module!\n");

}

module_init(fetch_and_add_module_init);
module_exit(fetch_and_add_module_cleanup);
MODULE_LICENSE("GPL");

17 changes: 17 additions & 0 deletions assignment10/linked_list_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef _LINKED_LIST_IMPL_H
#define _LINKED_LIST_IMPL_H
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>

struct my_node {
struct list_head list;
unsigned int data;
};

void *add_to_list(int thread_id, int range_bound[]);
int search_list(int thread_id, void *data, int range_bound[]);
int delete_from_list(int thread_id, int range_bound[]);


#endif
9 changes: 9 additions & 0 deletions assignment10/mutex_module/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
obj-m := mutex_module_final.o
mutex_module_final-y := mutex_module.o linked_list_impl.o ../calclock.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
70 changes: 70 additions & 0 deletions assignment10/mutex_module/linked_list_impl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "../calclock.h"
#include "../linked_list_impl.h"
#include <linux/list.h>
#include <linux/spinlock.h>

DEFINE_MUTEX(my_lock);

LIST_HEAD(my_list);

unsigned long long count_insert, count_search, count_delete;
unsigned long long time_insert, time_search, time_delete;

void *add_to_list(int thread_id, int range_bound[]) {
struct timespec localclock[2];
struct my_node *first = NULL;
int i;

mutex_lock(&my_lock);
for (i = range_bound[0]; i < range_bound[1] + 1; i++) {
struct my_node *new = kmalloc(sizeof(struct my_node), GFP_KERNEL);
new->data = i;

getrawmonotonic(&localclock[0]);
list_add(&new->list, &my_list);
getrawmonotonic(&localclock[1]);
calclock(localclock, &time_insert, &count_insert);

if (first == NULL) first = new;
}
mutex_unlock(&my_lock);

printk(KERN_INFO "thread #%d range: %d ~ %d\n",thread_id, range_bound[0], range_bound[1]);

return first;
}

int search_list(int thread_id, void *data, int range_bound[]) {
struct my_node *cur = (struct my_node *) data, *tmp;
struct timespec localclock[2];

mutex_lock(&my_lock);
list_for_each_entry_safe(cur, tmp, &my_list, list) {
if(range_bound[0] <= cur->data && cur->data <= range_bound[1]) {
getrawmonotonic(&localclock[0]);
getrawmonotonic(&localclock[1]);
calclock(localclock, &time_search,&count_search);
}
};
mutex_unlock(&my_lock);

return 0;
}

int delete_from_list(int thread_id, int range_bound[2]) {
struct my_node *cur, *tmp;
struct timespec localclock[2];

mutex_lock(&my_lock);
list_for_each_entry_safe(cur, tmp, &my_list, list) {
getrawmonotonic(&localclock[0]);
list_del(&cur->list);
kfree(cur);
getrawmonotonic(&localclock[1]);
calclock(localclock, &time_delete, &count_delete);
};
mutex_unlock(&my_lock);

return 0;
}

67 changes: 67 additions & 0 deletions assignment10/mutex_module/mutex_module.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// #--------- mutex_module.c ---------#
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include "../calclock.h"
#include "../linked_list_impl.h"

#define NUM_THREADS 4
static struct task_struct *threads[NUM_THREADS];

extern unsigned long long count_insert, count_search, count_delete;
extern unsigned long long time_insert, time_search, time_delete;

void set_iter_range(int thread_id, int range_bound[2]) {
range_bound[0] = thread_id * 250000;
range_bound[1] = range_bound[0] + 249999;
}

static int work_fn(void *data)
{
int range_bound[2];
int thread_id = *(int*) data;
void *ret;

set_iter_range(thread_id, range_bound);
ret = add_to_list(thread_id, range_bound);
search_list(thread_id, ret, range_bound);
delete_from_list(thread_id, range_bound);

while(!kthread_should_stop()) {
msleep(500);
}

printk(KERN_INFO "thread #%d stopped!\n", thread_id);
return 0;
}

int __init mutex_module_init(void) {
int i;

printk("Entering Mutex Module!\n");

for (i = 0; i < NUM_THREADS; i++) {
int* arg = (int*)kmalloc(sizeof(int), GFP_KERNEL);
*arg = i;
threads[i] = kthread_run(work_fn, (void*)arg, "thread%d", i);
}
return 0;
}

void __exit mutex_module_cleanup(void) {
int i;

printk(KERN_INFO"%s: Mutex linked list insert time: %llu ms, count: %llu", __func__, time_insert, count_insert);
printk(KERN_INFO"%s: Mutex linked list search time: %llu ms, count: %llu", __func__, time_search, count_search);
printk(KERN_INFO"%s: Mutex linked list delete time: %llu ms, count: %llu", __func__, time_delete, count_delete);

for(i = 0; i < NUM_THREADS; i++)
kthread_stop(threads[i]);

printk(KERN_INFO"%s: Exiting Mutex Module!\n", __func__);
}

module_init(mutex_module_init);
module_exit(mutex_module_cleanup);
MODULE_LICENSE("GPL");

9 changes: 9 additions & 0 deletions assignment10/rw_semaphore_module/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
obj-m := rw_semaphore_module_final.o
rw_semaphore_module_final-y := rw_semaphore_module.o linked_list_impl.o ../calclock.o
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
Loading

0 comments on commit 0551d2d

Please sign in to comment.