I have some problem with my code. In my code i solve the reader writers problem using RCU, when i load the module (insmod) everything works ok, and it works as i expected, but when i unload module (rmmod) my program freezes and I have to restart Ubuntu. In this program i have to use call_rcu() to delete previous version of the shared resource and i think that problem is here, because if i have not if I do not use this function and simply delete via kmalloc () then the program works as it should
#include<linux/module.h>
#include<linux/kthread.h>
#include<linux/wait.h>
#include<linux/slab.h>
#include<linux/rcupdate.h>
enum thread_index {WAKING_THREAD, WRITER_THREAD, FIRST_READER_THREAD, SECOND_READER_THREAD};
static struct thread_structure
{
struct task_struct *thread[4];
} threads;
struct st
{
int number;
struct rcu_head rcu;
};
static wait_queue_head_t wait_queue;
static bool condition;
static struct st *number_pointer = NULL;
static const int first_reader_number = 1, second_thread_number = 2;
static int reader_thread(void *data)
{
struct st *local_number_pointer = NULL;
for(;;) {
rcu_read_lock();
local_number_pointer = rcu_dereference(number_pointer);
if(local_number_pointer)
pr_info("[reader_number: %d] Value of \"number\" variable: %d\n",
*(int *)data,local_number_pointer->number);
rcu_read_unlock();
if(kthread_should_stop())
return 0;
set_current_state(TASK_INTERRUPTIBLE);
if(schedule_timeout(HZ>>2))
pr_info("Signal received!\n");
}
}
static void remove(struct rcu_head *x)
{
struct st *pntr = container_of(x, struct st, rcu);
kfree(pntr);
}
static int writer_thread(void *data)
{
struct st *local_number_pointer = NULL;
int number = 0;
DEFINE_WAIT(wait);
for(;;) {
struct st *old_pointer = NULL;
local_number_pointer = kmalloc(sizeof(*local_number_pointer),GFP_KERNEL);
if(IS_ERR(local_number_pointer)) {
pr_alert("Error allocating memory: %ld\n",PTR_ERR(local_number_pointer));
return 0;
}
local_number_pointer->number = number++;
old_pointer = number_pointer;
rcu_assign_pointer(number_pointer,local_number_pointer);
synchronize_rcu();
if(old_pointer)
call_rcu(&old_pointer->rcu, remove);
add_wait_queue(&wait_queue,&wait);
while(!condition) {
prepare_to_wait(&wait_queue,&wait,TASK_INTERRUPTIBLE);
if(kthread_should_stop())
return 0;
pr_info("[writer_thread]: awake\n");
schedule();
}
condition=false;
finish_wait(&wait_queue,&wait);
}
}
static int waking_thread(void *data)
{
for(;;) {
if(kthread_should_stop())
return 0;
set_current_state(TASK_INTERRUPTIBLE);
if(schedule_timeout(HZ))
pr_info("Signal received!\n");
condition=true;
wake_up(&wait_queue);
}
}
static int __init threads_init(void)
{
init_waitqueue_head(&wait_queue);
threads.thread[WRITER_THREAD] = kthread_run(writer_thread,NULL,"writer_thread");
threads.thread[WAKING_THREAD] = kthread_run(waking_thread,NULL,"waking_thread");
threads.thread[FIRST_READER_THREAD] =
kthread_run(reader_thread,(void *)&first_reader_number,"first_reader_thread");
threads.thread[SECOND_READER_THREAD] =
kthread_run(reader_thread,(void *)&second_thread_number,"second_reader_thread");
return 0;
}
static void __exit threads_exit(void)
{
kthread_stop(threads.thread[WAKING_THREAD]);
kthread_stop(threads.thread[WRITER_THREAD]);
kthread_stop(threads.thread[FIRST_READER_THREAD]);
kthread_stop(threads.thread[SECOND_READER_THREAD]);
}
module_init(threads_init);
module_exit(threads_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("An example of using the kernel linux threads and an RCU mechanism.");
MODULE_AUTHOR("Arkadiusz Chrobot <a.chrobot#tu.kielce.pl>");
Related
#include <stdlib.h>
typedef struct stackObject
{
void* obj;
struct stackObject *next;
} StackObject_t;
typedef struct stackMeta
{
StackObject_t *stack;
size_t objsize;
int numelem;
} StackMeta_t;
//CREATE
StackMeta_t *mystack_create(size_t objsize)
{
StackMeta_t *elem;
elem = (StackMeta_t*)malloc(sizeof(StackMeta_t));
if(elem == NULL)
{
return NULL;
}
else
{
elem->stack = NULL; // my actual stack basically the first elem(the top)
elem->objsize = objsize; // size of the datatype
elem->numelem = 0; // total count of elem inside the stack
}
return elem;
}
//PUSH
int mystack_push(StackMeta_t *data_stack, void* obj)
{
if(data_stack == NULL)
{
return -1;
}
StackObject_t *nodeObject = NULL;
nodeObject = (StackObject_t*)malloc(sizeof(StackObject_t));
if(nodeObject == NULL)
{
return -1;
}
if(data_stack->stack == NULL)
{
nodeObject->next = NULL;
memcpy(nodeObject->obj, obj, data_stack->objsize);
data_stack->stack = nodeObject;
data_stack->numelem++;
}
else
{
nodeObject->next = data_stack->stack;
memcpy(nodeObject->obj, obj, data_stack->objsize);
data_stack->stack = nodeObject;
data_stack->numelem++;
}
return 0;
}
int main() {
StackMeta_t *METADATA = NULL;
int obj = 1;
METADATA = mystack_create(sizeof(int));
mystack_push(METADATA, &obj);
return 0;
}
This code is Stack with Linked List inside.
So I am trying to copy int obj value to void* obj. from my understanding objcan be any data type so i chose it to be an int type. I am using a visual online tool to see my heap memory and I saw that the value of the 3rd parameter is size_t objsize = 4.
I cannot pin point where my problem is and I have not tested if this has memory leaks.
can someone explain this to me with an example on how to copy void pointers?
i am writing a Generic ADT using C and i keep getting a segmentation fault when i free an element
PairResult pairClear(Pair pair)
{
if(pair == NULL)
{
return PAIR_NULL_ARGUMENT;
}
KeyElement key=pair->key;
DataElement data=pair->data;
if(key)
pair->free_key(key);//i get the Error here
if(data)
pair->free_data(data);
return PAIR_SUCCESS;
}
the memory for key and data is allocated :
Pair pairCreate( KeyElement key, DataElement data,
copyDataElements copy_data,
freeDataElements free_data,
copyKeyElements copy_key,
freeKeyElements free_key)
{
Pair pair = malloc(sizeof(*pair));
if(pair == NULL)
{
return NULL;
}
pair->copy_data=copy_data;
pair->copy_key=copy_key;
pair->free_data=free_data;
pair->free_data=free_key;
KeyElement new_string_key = copy_key(key);
DataElement new_string_data = copy_data(data);
if((new_string_key == NULL) || (new_string_data == NULL))
{
pairDestroy(pair);
return NULL;
}
pair->key = new_string_key;
pair->data = new_string_data;
return pair;
}
this pairDestroy
void pairDestroy(Pair pair)
{
if(pair == NULL)
{
return;
}
#ifndef NDEBUG
PairResult result =
#endif
pairClear(pair);
assert(result == PAIR_SUCCESS);
free(pair);
}
these are the copy functions used:
static KeyElement copyKeyInt(KeyElement n) {
if (!n) {
return NULL;
}
int *copy = malloc(sizeof(*copy));
if (!copy) {
return NULL;
}
*copy = *(int *) n;
return copy;
}
static DataElement copyDataChar(DataElement n) {
if (!n) {
return NULL;
}
char *copy = malloc(sizeof(*copy));
if (!copy) {
return NULL;
}
*copy = *(char *) n;
return (DataElement) copy;
}
and these are the free functions used
static void freeInt(KeyElement n) {
free(n);
}
static void freeChar(DataElement n) {
free(n);
}
and here is the struct of pair
struct Pair_t {
KeyElement key;
DataElement data;
copyDataElements copy_data;
freeDataElements free_data;
copyKeyElements copy_key;
freeKeyElements free_key;
};
these are all the typedef used :
typedef struct Pair_t* Pair;
typedef enum PairResult_t {
PAIR_SUCCESS,
PAIR_OUT_OF_MEMORY,
PAIR_NULL_ARGUMENT,
} PairResult;
typedef void *DataElement;
typedef void *KeyElement;
typedef DataElement(*copyDataElements)(DataElement);
typedef KeyElement(*copyKeyElements)(KeyElement);
typedef void(*freeDataElements)(DataElement);
typedef void(*freeKeyElements)(KeyElement);
and a main function so that u could reproduce it
int main()
{
Pair pair;
for (int i = 1; i < 1000; ++i) {
char j = (char) i;
++j;
pair=pairCreate(&i,&j,copyDataChar,freeChar,copyKeyInt,freeInt);
pairDestroy(pair);
}
I added everything I could for a reproducible code
if anything should be edited please tell me in the comments
Pair pairCreate(...) {
...
pair->free_data = free_data;
pair->free_data = free_key;
// ^^^^^^^^^ UH OH
...
You owe me 15 mins of debugging time.
I'm currently learning how to create USB drivers for Linux, and I absolutely love it so far! However, I've come across an issue when trying to insert my .ko file. I keep receiving the following error: "Unknown symbol in module".
Below, you will find my code. What is weird is if I comment out the code in my __init function, the module loads just fine, however after going through my code, and comparing it to other USB driver code, I am unable to locate any issues. Could you please help me out? Thanks so much for your help
struct xb1_controller {
struct usb_device *udev;
struct usb_interface *interface;
unsigned char minor;
char *int_in_buffer;
struct usb_endpoint_descriptor *endpoint;
struct urb *int_in_urb;
};
static struct usb_device_id xb1_table [] = {
{USB_DEVICE(xb1_vendor_id, xb1_product_id) },
{}
};
MODULE_DEVICE_TABLE(usb, xb1_table);
static int xb1_open(struct inode *inode, struct file *file) {
//Sys call
}
static int xb1_release(struct inode *inode, struct file *file) {
//Sys call
}
static ssize_t xb1_read(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos) {
//Sys call
}
static struct file_operations xb1_fops = {
.owner = THIS_MODULE,
.open = xb1_open,
.release = xb1_release,
.read = xb1_read,
};
static struct usb_class_driver xb1_class = {
.name = "xb1driver",
.fops = &xb1_fops,
.minor_base = MINOR_BASE,
};
static int xb1_probe(struct usb_interface *interface, const struct
usb_device_id *id) {
printk(KERN_INFO "xb1driver probe function called");
}
static void xb1_disconnect(struct usb_interface *interface) {
printk(KERN_INFO "xb1driver disconnect function called");
}
static struct usb_driver xb1_driver = {
.name = "xb1driver",
.id_table = xb1_table,
.probe = xb1_probe,
.disconnect = xb1_disconnect,
};
static int __init xb1_init(void) {
int result;
result = usb_register(&xb1_driver);
if(result) {
printk(KERN_INFO "usb_register has failed..");
return 5;
}
return result;
}
static void __exit xb1_exit(void) {
usb_deregister(&xb1_driver);
}
module_init(xb1_init);
module_exit(xb1_exit);
I wrote the following code to handle a joystick on Linux:
static int fd;
int joystick_init(void)
{
struct js_event event;
if((fd = open("/dev/input/js1", O_RDONLY | O_NONBLOCK)) == -1)
return ERROR;
//ignore all init events
while(read(fd, &event, sizeof(struct js_event)) == sizeof(struct js_event)){
}
return SUCCESS;
}
void joystick_end(void)
{
close(fd);
}
const struct js_event *joystick_get_event(void)
{
static struct js_event event;
if(read(fd, &event, sizeof(struct js_event)) == sizeof(struct js_event))
return &event;
return NULL;
}
And the following to print the events:
void joy_input(const struct js_event *event)
{
switch(event->type){
case JS_EVENT_BUTTON:
printf("button number = %d\n", event->number);
break;
case JS_EVENT_AXIS:
printf("axis number = %d\n", event->number);
break;
}
printf("event time = %d\n", event->time);
printf("event value = %d\n", event->value);
printf("event type = %d\n", event->type);
puts("joy_input called");
}
And this is what is printed every time a button is pressed:
event time = 6348112
event value = 0
event type = 0
joy_input called
What's the problem? Why doesn't it report JS_EVENT_BUTTON or JS_EVENT_AXIS? Why doesn't time change?
Edit:
//void * can't point to functions
typedef struct Joystick_Listener {
void (*cb)(const struct js_event *event);
} Joystick_Listener;
static void dispatch_joy_events(Node *node, void *arg)
{
Joystick_Listener *listener = node->content;
listener->cb(arg);
}
void video_and_input_run(void)
{
const struct js_event *event;
while(1){
/* ... */
//Call joystick listeners
pthread_mutex_lock(&joy_listener_lock);
while((event = joystick_get_event()) != NULL)
list_iterate_arg(&joy_listener, dispatch_joy_events, &event);
pthread_mutex_unlock(&joy_listener_lock);
/* ... */
}
}
void list_iterate_arg(const List *list, void(*function)(Node*, void *), void *arg)
{
Node *next; //store in case the node changes
for(Node *ite = list->first; ite != NULL; ite = next){
next = ite->next;
function(ite, arg);
}
}
Silly mistake, I was passing the address of event but it's already a pointer to the event and not the event itself, so it makes no sense.
void video_and_input_run(void)
{
const struct js_event *event;
while(1){
/* ... */
//Call joystick listeners
pthread_mutex_lock(&joy_listener_lock);
while((event = joystick_get_event()) != NULL)
list_iterate_arg(&joy_listener, dispatch_joy_events, event);
pthread_mutex_unlock(&joy_listener_lock);
/* ... */
}
}
I've a long version of a program that uses this code and a short version. This is the short version and oddly, this code runs perfectly fine in short version program, but because I get an access violation in the larger version, I get the feeling something is wrong. Does anyone see anything terribly wrong (that might lead to data corruption and/or access violation errors) with the following code? Or is this alright?
char strlist[5][11] = {
{ "file01.txt" },
{ "file02.txt" },
{ "file03.txt" },
{ "file04.txt" },
{ "file05.txt" }
};
typedef struct DYNAMEM_DATA {
char *string;
int strlen;
} DYNAMEM_DATA;
typedef struct DYNAMEM_STRUCT {
struct DYNAMEM_DATA **data;
int num_elements;
} DYNAMEM_STRUCT;
DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist)
{
DYNAMEM_STRUCT *ds = (DYNAMEM_STRUCT *)calloc(1, sizeof(DYNAMEM_STRUCT));
wchar_t wstring[128];
char len[3];
int i;
ds->data = (DYNAMEM_DATA **)calloc(num_elements, sizeof(DYNAMEM_DATA *));
ds->num_elements = num_elements;
for(i = 0; i < num_elements; i++) {
ds->data[i] = (DYNAMEM_DATA *)calloc(1, sizeof(DYNAMEM_DATA));
ds->data[i]->string = (char *)calloc(1, strlen(&strlist[i*11])+5);
ds->data[i]->strlen = strlen(&strlist[i*11]);
sprintf(ds->data[i]->string, "%s, %d", &strlist[i*11], ds->data[i]->strlen);
mbstowcs(wstring, ds->data[i]->string, 128);
MessageBox(NULL, wstring, TEXT("Error"), MB_OK);
}
return ds;
}
This code runs, produces 5 'Error' messages (which is to be expected), and doesn't leak any memory. Running valgrind (3.7.0) on Mac OS X 10.7.4 (using GCC 4.7.1), it is given a clean bill of health.
The problem is not, apparently, in this version of the code.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <wchar.h>
char strlist[5][11] = {
{ "file01.txt" },
{ "file02.txt" },
{ "file03.txt" },
{ "file04.txt" },
{ "file05.txt" }
};
typedef struct DYNAMEM_DATA {
char *string;
int strlen;
} DYNAMEM_DATA;
typedef struct DYNAMEM_STRUCT {
struct DYNAMEM_DATA **data;
int num_elements;
} DYNAMEM_STRUCT;
enum { MB_OK = 0 };
static void destroy_dynamem_data(DYNAMEM_DATA *dd)
{
free(dd->string);
free(dd);
}
static void destroy_dynamem_struct(DYNAMEM_STRUCT *ds)
{
for (int i = 0; i < ds->num_elements; i++)
destroy_dynamem_data(ds->data[i]);
free(ds->data);
free(ds);
}
static void MessageBox(const void *null, const wchar_t *wcs, const char *ncs, int status)
{
if (null == 0 || status == MB_OK)
fprintf(stderr, "%s\n", ncs);
else
fwprintf(stderr, L"%s\n", wcs);
}
static const char *TEXT(const char *arg) { return arg; }
extern DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist);
DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist)
{
DYNAMEM_STRUCT *ds = (DYNAMEM_STRUCT *)calloc(1, sizeof(DYNAMEM_STRUCT));
wchar_t wstring[128];
//char len[3];
int i;
ds->data = (DYNAMEM_DATA **)calloc(num_elements, sizeof(DYNAMEM_DATA *));
ds->num_elements = num_elements;
for(i = 0; i < num_elements; i++) {
ds->data[i] = (DYNAMEM_DATA *)calloc(1, sizeof(DYNAMEM_DATA));
ds->data[i]->string = (char *)calloc(1, strlen(&strlist[i*11])+5);
ds->data[i]->strlen = strlen(&strlist[i*11]);
sprintf(ds->data[i]->string, "%s, %d", &strlist[i*11], ds->data[i]->strlen);
mbstowcs(wstring, ds->data[i]->string, 128);
MessageBox(NULL, wstring, TEXT("Error"), MB_OK);
}
return ds;
}
int main(void)
{
DYNAMEM_STRUCT *ds = create_dynamem_struct(5, strlist[0]);
destroy_dynamem_struct(ds);
return 0;
}