diff --git a/a1.2.config b/a1.2.config index a8a60a707a9d..ff905b05fba8 100644 --- a/a1.2.config +++ b/a1.2.config @@ -3755,9 +3755,8 @@ CONFIG_NVMEM_SYSFS=y # CONFIG_PECI is not set # CONFIG_HTE is not set CONFIG_SST=y -CONFIG_SST_MEMLEAK=y # CONFIG_SST_BOUNDS is not set -# CONFIG_SST_LOCKING is not set +# CONFIG_SST_ASYNC_SOURCE is not set # end of Device Drivers # diff --git a/drivers/sst/Kconfig b/drivers/sst/Kconfig index 3dd56be559e8..98802edff6c7 100644 --- a/drivers/sst/Kconfig +++ b/drivers/sst/Kconfig @@ -4,27 +4,21 @@ # menuconfig SST - bool "Modules for system software techniques" + tristate "Modules for system software techniques" default y help TODO if SST -config SST_MEMLEAK - tristate "Memleak errors for exercise a1.2" - default n - help - Enable memleaks for exercise a1.2 - config SST_BOUNDS tristate "Out-of-bounds accesses for exercise a1.3" default n help Activate out-of-bounds accesses for exercise a1.3 -config SST_LOCKING - tristate "Faulty locking for exercise a1.4" +config SST_ASYNC_SOURCE + tristate "Enable async source of messages from the universe" default n help - Make locking for exercise a1.4 faulty + This is needed for task a1.4 endif diff --git a/drivers/sst/boundedbuffer.c b/drivers/sst/boundedbuffer.c index 64a72aabed0d..a1fb40bd985d 100644 --- a/drivers/sst/boundedbuffer.c +++ b/drivers/sst/boundedbuffer.c @@ -6,31 +6,36 @@ #define OFFSET 0 #endif -noinline int is_full(volatile struct boundedbuffer *buffer) { +void init_bbuffer(struct boundedbuffer *buffer) { + buffer->next_in = 0; + buffer->next_out = 0; + buffer->size = BOUNDEDBUFFER_SIZE; +} + +int is_full(struct boundedbuffer *buffer) { return (buffer->next_in + 1) % buffer->size == buffer->next_out; } -noinline int is_empty(volatile struct boundedbuffer *buffer) { +int is_empty(struct boundedbuffer *buffer) { return buffer->next_out == buffer->next_in; } -noinline int produce(volatile struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE data) { +int produce(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE data) { if (is_full(buffer)) { return -1; } - buffer->data[buffer->next_in] = data; + buffer->data[buffer->next_in + OFFSET] = data; buffer->next_in = (buffer->next_in + 1) % buffer->size; return 0; } -noinline int consume(volatile struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE *ret) { +int consume(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE *ret) { if (is_empty(buffer)) { return -1; } - *ret = buffer->data[buffer->next_out]; - buffer->data[buffer->next_out] = 0; + *ret = buffer->data[buffer->next_out + OFFSET]; buffer->next_out = (buffer->next_out + 1) % buffer->size; return 0; diff --git a/drivers/sst/boundedbuffer.h b/drivers/sst/boundedbuffer.h index 0a98f385f6e0..64086e584a8b 100644 --- a/drivers/sst/boundedbuffer.h +++ b/drivers/sst/boundedbuffer.h @@ -21,8 +21,9 @@ struct boundedbuffer { BOUNDEDBUFFER_STORAGE_TYPE data[BOUNDEDBUFFER_SIZE_REAL]; }; -noinline int is_full(volatile struct boundedbuffer *buffer); -noinline int is_empty(volatile struct boundedbuffer *buffer); -noinline int produce(volatile struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE data); -noinline int consume(volatile struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE *ret); +void init_bbuffer(struct boundedbuffer *buffer); +int is_full(struct boundedbuffer *buffer); +int is_empty(struct boundedbuffer *buffer); +int produce(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE data); +int consume(struct boundedbuffer *buffer, BOUNDEDBUFFER_STORAGE_TYPE *ret); #endif // __BOUNDEDBUFFER_H__ diff --git a/drivers/sst/sst_chrdev.c b/drivers/sst/sst_chrdev.c index b159bbee4c00..06f03743be65 100644 --- a/drivers/sst/sst_chrdev.c +++ b/drivers/sst/sst_chrdev.c @@ -29,7 +29,7 @@ static ssize_t universe_read(struct file *file, char __user *buf, size_t count, size_t len = 0; if (sst_consume_answer(sst_info, &answer)) { - pr_err("Cannot read from answers!\n"); + pr_debug("Cannot read from answers!\n"); return 0; } len = strlen(answer); @@ -78,7 +78,7 @@ static struct class universe_class = { .name = SST_CHRDEV, }; -static int __init sst_chdev_init(void) { +static int __init sst_chrdev_init(void) { int err; sst_chrdev_major = err = register_chrdev(0, SST_CHRDEV, &universe_fops); @@ -99,11 +99,14 @@ static int __init sst_chdev_init(void) { } err = sst_init(); if (err) { - return err; + pr_err("Cannot init sst_common: %d\n", err); + goto out_device; } pr_notice("Loaded module %s\n", KBUILD_MODNAME); return 0; +out_device: + device_destroy(&universe_class, MKDEV(sst_chrdev_major, 0)); out_class: class_unregister(&universe_class); out_chrdev: @@ -112,7 +115,7 @@ out: return err; } -static void __exit sst_chdev_exit(void) { +static void __exit sst_chrdev_exit(void) { sst_destroy(); device_destroy(&universe_class, MKDEV(sst_chrdev_major, 0)); class_unregister(&universe_class); @@ -120,6 +123,6 @@ static void __exit sst_chdev_exit(void) { pr_notice("Unloaded module %s\n", KBUILD_MODNAME); } -module_init(sst_chdev_init); -module_exit(sst_chdev_exit); +module_init(sst_chrdev_init); +module_exit(sst_chrdev_exit); MODULE_LICENSE("LGPL"); diff --git a/drivers/sst/sst_common.c b/drivers/sst/sst_common.c index 0ab1d60da991..39126654a489 100644 --- a/drivers/sst/sst_common.c +++ b/drivers/sst/sst_common.c @@ -44,6 +44,9 @@ static int control_thread_work(void *data) { if (err) { pr_err("Questions was empty!\n"); continue; + } else if (question == NULL) { + pr_err("Question is NULL although ret value is 0.\n"); + continue; } else { sst_debug("Received msg '%s' at 0x%lx\n", question, (uintptr_t)question); } @@ -52,7 +55,7 @@ static int control_thread_work(void *data) { (question[len_question - 1] == '\n' && question[len_question - 2] == '?'))) { my_answer = sst_answers[0]; for (i = 0; i < SST_MAX_QUESTIONS; i++) { - if (strcasecmp(question, sst_questions[i]) == 0) { + if (strcmp(question, sst_questions[i]) == 0) { my_answer = sst_answers[i]; break; } @@ -93,8 +96,8 @@ int sst_init(void) { spin_lock_init(&cur_sst_info->lock_answers); sema_init(&cur_sst_info->answers_rdy, 0); init_waitqueue_head(&cur_sst_info->wait); - cur_sst_info->questions.size = BOUNDEDBUFFER_SIZE_REAL; - cur_sst_info->answers.size = BOUNDEDBUFFER_SIZE_REAL; + init_bbuffer(&cur_sst_info->answers); + init_bbuffer(&cur_sst_info->questions); sst_debug("Allocated private data for the universe at [0x%lx,0x%lx]\n", (uintptr_t)cur_sst_info, (uintptr_t)((uintptr_t)cur_sst_info + sizeof(*cur_sst_info))); cur_sst_info->thread = kthread_create(control_thread_work, get_sst_info(), "sst-worker-%d", 1); if (IS_ERR(cur_sst_info->thread)) { @@ -118,6 +121,11 @@ EXPORT_SYMBOL(sst_destroy); int sst_produce_question(sst_info_t *info, char *value) { int err = 0; + + if (!info) { + return -1; + } + sst_debug("%s:info=%lx, questions=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->questions); spin_lock_bh(&info->lock_questions); err = produce(&info->questions, value); spin_unlock_bh(&info->lock_questions); @@ -131,6 +139,11 @@ EXPORT_SYMBOL(sst_produce_question); int sst_produce_answer(sst_info_t *info, char *value) { int err = 0; unsigned long flags; + + if (!info) { + return -1; + } + sst_debug("%s:info=%lx, answers=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->answers); spin_lock_irqsave(&info->lock_answers, flags); err = produce(&info->answers, value); spin_unlock_irqrestore(&info->lock_answers, flags); @@ -141,6 +154,11 @@ EXPORT_SYMBOL(sst_produce_answer); int sst_consume_question(sst_info_t *info, char **value) { int err = 0; + + if (!info) { + return -1; + } + sst_debug("%s:info=%lx, questions=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->questions); spin_lock_bh(&info->lock_questions); err = consume(&info->questions, value); spin_unlock_bh(&info->lock_questions); @@ -151,6 +169,11 @@ EXPORT_SYMBOL(sst_consume_question); int sst_consume_answer(sst_info_t *info, char **value) { int err = 0; unsigned long flags; + + if (!info) { + return -1; + } + sst_debug("%s:info=%lx, answers=%lx\n", __func__, (uintptr_t)cur_sst_info, (uintptr_t)&info->answers); if (down_trylock(&info->answers_rdy)) { sst_debug("Sry. No answer for you!\n"); return -2;