#include #include #include #include #include #include #include #include MODULE_LICENSE("GPL"); /* Kernel needs this license. */ #define ENTRY_NAME "kitchen" #define KITCHEN_SIZE 20 /* Some global statics to help you print the orders. For example: * printf("%s\n",DISH1) will print Caesar Salad. */ #define DISH1 "Caesar Salad" #define DISH2 "Hamburger" #define DISH3 "Personal Pizza" #define DISH4 "Beef Wellington" /*************** Function declarations ****************/ ssize_t procfile_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); ssize_t procfile_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); static int t_kitchen(void* data); //Your thread! /**************** Global variables go here **************/ static struct file_operations hello_proc_ops = { .owner = THIS_MODULE, .read = procfile_read, .write = procfile_write, }; struct mutex k_mutex; struct task_struct *t; /* TODO: The follow 3 variables need mutex protection. */ int queue[KITCHEN_SIZE]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int current_dish=0; int dishes_processed=0; /************************** Functions **********************/ /* Kitchen thread function. * TODO: This background kitchen thread needs to process dishes * and remove them from the queue. * TODO: Protect global variables with mutexes. */ static int t_kitchen(void* data) { /* Loop until we unload the module */ while(!kthread_should_stop()) { printk("Running looking at slot %i!\n", current_dish); /* This ssleep of 1 second needs to be here no matter what * to slow the kitchen down. It is in addition to the time * you need to process the dish.*/ ssleep(1); /* TODO: Process a dish on the queue */ /* TODO: Update the current_dish variable. It should be the * slot in the queue that you are currently processing. */ } return 0; } /* This funciton is called when the module is loaded into the kernel. * You don't need to modify this function. */ int hello_proc_init(void) { /* Create the /proc file */ proc_create_data(ENTRY_NAME, 0, NULL, &hello_proc_ops, NULL); printk("/proc/%s created\n", ENTRY_NAME); /* Initialize our mutex to unlocked (0) so that it's ready to roll. */ mutex_init(&k_mutex); /* Start our kthread. It runs entirely in the t_kitchen function. */ t = kthread_run(t_kitchen, NULL, "Kitchen_McThreadyFace"); return 0; } /* This function is called when someone reads from /proc/kitchen. * TODO: Protect global variables with mutexes. */ ssize_t procfile_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { static int finished = 0; int ret=0; char ret_buf[80]; /* Are we done reading? If so, we return 0 to indicate end-of-file */ if (finished) { finished=0; return finished; } finished = 1; printk("/proc/%s read called.\n", ENTRY_NAME); /* The following code copies an informational string into the return * buffer ret_buf, which goes back to userspace. You don't need to modify * this code, but you should later protect it with a mutex because it * reads some global variables. */ if(queue[current_dish]==1){ ret = sprintf(ret_buf,"Processing %s at slot %i.\n%i dishes processed.", DISH1,current_dish,dishes_processed); } else if(queue[current_dish]==2){ ret = sprintf(ret_buf, "Processing %s at slot %i\n%i dishes processed.", DISH2,current_dish,dishes_processed); } else if(queue[current_dish]==3){ ret = sprintf(ret_buf, "Processing %s at slot %i\n%i dishes processed", DISH3,current_dish,dishes_processed); } else if(queue[current_dish]==4){ ret = sprintf(ret_buf, "Processing %s at slot %i\n%i dishes processed", DISH4,current_dish,dishes_processed); } else if(queue[current_dish]==0){ ret = sprintf(ret_buf, "Processing nothing at slot %i\n%i dishes processed",current_dish,dishes_processed); } if (copy_to_user(buf, ret_buf, ret)){ return -EFAULT; } return ret; //ret is important, it is the number of characters sent back } /* This function is called when someone writes to /proc/kitchen like this: * echo 2 > /proc/kitchen (this puts a hamburger order on the queue) * * TODO: Implement putting food orders on the queue. * TODO: Protect global variables with mutexes. */ ssize_t procfile_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { char *page; /* don't touch */ int my_data = 0; /* Allocating kernel memory, don't touch. */ page = (char *) vmalloc(count); if (!page) return -ENOMEM; /* Copy the data from the user space. Data is placed in page. * Don't touch.*/ if (copy_from_user(page, buf, sizeof(int))) { vfree(page); return -EFAULT; } /* sscanf copies the string of the number into a decimal data type * into the variable my_data. Now you can directly use and print * the integer my_data to get your order number. */ sscanf( page,"%d",&my_data ); printk( "User has sent the value of %d\n", my_data ); /* TODO: Put the order number *somewhere* in the queue. If there * isn't room, set the return value to -ENOMEM.*/ /* Free the allocated memory, don't touch. */ vfree(page); return count; } /* This is the function called when the module is unloaded. You don't * need to modify it unless you want to change the silly prints. */ void hello_proc_exit(void) { int ret=0; ret=kthread_stop(t); if(ret != -EINTR) printk("Kitchen stopped. WRRRrrrrrgghh. Thump.\n"); remove_proc_entry(ENTRY_NAME, NULL); printk("Removing /proc/%s.\n", ENTRY_NAME); } module_init(hello_proc_init); module_exit(hello_proc_exit);