I am trying to implement a low-level thread lock without the use of dynamic memory allocation; this code will basically be used on a completely bare-bones kernel.
However, I am running into the problem of receiving a seg fault when I am trying to dereference a member inside this global static struct. My code is as such
My wrapper struct
/** LOCKING STRUCT & FUNCTIONS **/
struct lock {
int free;
struct thread_list* wait_list;
struct thread* current_holder;
};
The nested struct(intended as a linked list sort of deal)
struct thread_list {
struct thread *head;
};
And the member inside this list
struct thread {
void *top; // top of the stack for this thread
void *sp; // current stack pointer for this thread (context)
void (*start_func)(void *);
void *arg;
int state;
int exit_value;
struct thread *join_thread;
struct thread *next_thread;
int id;
};
The method I'm trying to implement is as such
void lock_init (struct lock *lk) {
lk->free = 1; //Set lock as free
struct thread_list waiting = lk->wait_list; //Get waitlist, works fine
waiting->head = NULL; //Set waitlist's head to null, SEGFAULTS HERE
}
I am not super proficient at C, but I can't seem to figure out the correct methodology/syntax to make my code work like this.
struct thread_list waiting = lk->wait_list; //Get waitlist, works fine
waiting->head = NULL; //Set waitlist's head to null, SEGFAULTS HERE
waiting is not a struct pointer but a struct variable . To access member using it you need to use . operator -
waiting.head = NULL;
Or to use -> operator declare it as a struct pointer .
Related
I am attempting to implement my own version of a semaphore into a linux vm and am running into a crash when I attempt to lock a spinlock inside the down function. Using GDB I found that the down is called immediately after the create function so the problem is definitely there.
Here is the create function:
asmlinkage long sys_create(int value, char name[32], char key[32]){
struct sem *new_sem = (struct sem*) kmalloc(sizeof(struct sem), GFP_ATOMIC);
struct sem_node *new_sem_node = (struct sem_node*) kmalloc(sizeof(struct sem_node), GFP_ATOMIC);
struct sem_node *curr_sem = sem_list_head;
new_sem_node->sem = new_sem;
spin_lock(&sem_lock);
new_sem->sem_id = IDcntr++;
spin_lock_init(&(new_sem->lock));
strncpy(new_sem->key, key, 32);
strncpy(new_sem->name, name, 32);
if(curr_sem == NULL)
{
sem_list_head = new_sem_node;
}
else
{
while(curr_sem->next != NULL)
{
curr_sem = curr_sem->next;
}
curr_sem->next = new_sem_node;
}
spin_unlock(&sem_lock);
return new_sem->sem_id;
}
Functions spin_lock, spin_unlock, and spin_lock_init are working as intended. The down function calls:
spin_lock(&(sem_list_head->sem->lock));
right at the beginning and freezes. To be more specific, in the gdb terminal, I try and get to the next line and it stops and in the actual machine it's completely stopped. No other functions are called between the create and down function. Below is the header file that defines the sem_node, process_node, and sem objects used in the create and down functions:
int IDcntr = 1;
DEFINE_SPINLOCK(sem_lock);
struct sem_node
{
struct sem* sem;
struct sem_node* next;
};
struct process_node
{
struct process_node* next;
struct task_struct* task;
};
struct sem
{
int value;
long sem_id;
spinlock_t lock;
char key[32];
char name[32];
struct process_node* head;
struct process_node* tail;
};
struct sem_node* sem_list_head = NULL;
Through independent testing the function DEFINE_SPINLOCK and object spinlock_t are working as intended. After thorough debugging the problem is in the create function. I freely admit that I am still learning how semaphores work so chances are I didn't set variables correctly or define things correctly. Any help in pointing me the right way would be greatly appreciated.
I'm try to make simple kernel module with multithreading.
So I'm using linux/kthread.h, kernel v. 5.2.11
Problem: I can't passing the char array into thread: Segmentation fault.
That's what I'm doing:
typedef struct {
int num;
char origin[MAXSTR]; //part of input for current thread
struct completion wait_for_thread; //completion struct
} kthread_arg;
Then:
struct task_struct *task;
static kthread_arg kta_first_thread;
kta_first_thread.num = 1;
strncpy(kta_first_thread.origin, dat1, MAXSTR );
//Here I have normal char array 'origin'
init_completion(&kta_first_thread.wait_for_thread);
task = kthread_run(&thread_function, (void*)&kta_first_thread, "one");
And after that I have the error. Moreover, if you remove the array from struct, then everything works.
I'm sure doing something wrong?
The args passed to kernel_run must be kmalloced, your args is in stack. I have met the same problem, your code should like this:
struct your_struct* test=NULL;
struct task_struct* t=NULL;
test=(struct your_struct*)kmalloc(sizeof(struct your_struct),GFP_KERNEL);
t=kthread_run(your_function,(void*)test,name);
I have a while loop, and for each iteration of the loop, I am creating and populating a struct, and creating a thread while passing in that struct as an argument to the threaded function.
This is causing some issues - My while loop updates the data in the struct before my threaded function has a chance to make local copies of the struct data.
Does anyone know a good way to go about reusing a struct for multiple threads? I thought about using some kind of flag to make the main thread wait until the threaded function grabs its own copy, but this seems like it would introduce unnecessary waiting.
Here is an example of what I am trying to accomplish:
struct parameters {
int val1;
int val2;
int val3;
};
int main() {
...
while (readLine(file)) {
...
struct parameters *myParameters = malloc(sizeof(struct parameters));
myParameters.val1 = line.val1;
myParameters.val2 = line.val2;
myParameters.val3 = line.val3;
pthread_t myThread;
pthread_create(&myThread, NULL, &print, myParameters);
free(myParameters);
}
}
void *print(void *param) {
struct parameters *localParameters = param;
int threadVal1 = localParameters->val1;
int threadVal2 = localParameters->val2;
int threadVal3 = localParameters->val3;
}
The following function doesn't work. pin_thread_function sometimes receive garbage instead of the struct data. What is wrong? I know that is some basic scope related problem, but I can't explain.
typedef void (*state_callback_t)(int state);
struct pin_thread_params
{
char pin[3 + 1];
state_callback_t callback_onchange;
};
extern int pin_monitor_create(const char * pin,
state_callback_t callback_onchange)
{
int ret;
unsigned long int thread;
struct pin_thread_params params;
//Setup struct
strcpy(params.pin, "123");
params.callback_onchange = callback_onchange;
//Create thread with struc as parameter
ret = pthread_create(&thread, NULL, pin_thread_function, ¶ms);
if (!ret)
{
ret = pthread_detach(thread);
}
return ret;
}
static void * pin_thread_function(void * context)
{
struct pin_thread_params params;
memcpy(¶ms, context, sizeof(params));
//Sometimes the correct string, most time garbage
printf("Started monitoring %s", params.pin);
}
When params is malloc'ed before pthread_create, everything works fine, like this:
...
struct pin_thread_params * params;
//Setup struct with malloc
params = malloc(sizeof(struct pin_thread_params));
strcpy(params->pin, "123");
params->callback_onchange = callback_onchange;
...
struct pin_thread_params params is statically allocated and the address of it is not safe to use once the scope of it is over (i.e. after pin_monitor_create has returned). It may happen that sometimes the thread execution starts before the pin_monitor_create has exited and you see the valid data in params. However, the dynamically allocated memory is from heap and will be usable until you free it, so you always get valid data in params within pin_thread_function .
I'm not particularly knowledgeable about pthreads (can't just comment quite yet), but you are passing a pointer to stack allocated memory to the thread which will eventually be clobbered by proceeding function calls.
I'm creating a threadpool in C with pthreads, and while I have an idea of how it works, I have a few questions about the intricacies.
I've created a struct which is supposed to be my representation of a threadpool, containing a list of function pointers to run, we'll call it the work_list. The threadpool struct also holds mutex's(?) and conditions to syncronize access, an int for the number of threads and an array holding the thread id's of each worked thread.The work_list itself holds structs that represent functions to be completed, each instance of those structs holds a void* to a function, a void* for args and a void* to place results. When coded this idea fleshes out like this:
typedef struct threadpool
{
list work_list;
pthread_t* tidArray;
int num_threads;
pthread_mutex_t lock;
pthread_cond_t condition;
} threadpool;
and:
typedef struct fuFunction
{
void* functionCall;
void* functionArgs;
void* returnValue;
list_elem elem;
} fuFunction;
I currently have a thread which initializes the a pool. It takes in a int num_of_threads, and returns a pointer to instance of a threadpool with all the members initialized. The body I've created looks like this:
threadpool * threadpool_init(int num_of_threads)
{
threadpool* retPool = (threadpool*) malloc(sizeof(threadpool));
//Initialize retPool members
int x;
for(x = 0; x < num_of_threads; x++)
{
pthread_t tid;
if( pthread_create(&tid, NULL, thread_start, retPool) != 0)
{
printf("Error creating worker thread\nExting\n");
exit(1);
}
retPool->tidArray[x] = tid;
}
return retPool;
}
The function that each thread runs when started, the worker function, thread_star, looks like this so far:
void *thread_start(void* args)
{
threadpool* argue = (threadpool*) args;
pthread_mutex_lock(&(argue->lock));
while(\* threadpool not shut down*\)
{
if(!list_empty(&argue->work_list))
{
fuFunction* tempFu = list_entry(list_pop_front(&argue->workQ), fuFunction, elem);
\\WHAT TO PUT HERE
}
pthread_cond_wait(&argue->condition, &argue->lock);
}
pthread_mutex_unlock(&(argue->lock));
}
My question is, assuming this code I currently have is right, how would I get the worker threads to run the function in the tempFu that it makes in the worker function? Sorry if this is long or confusing, I find this much easier to explain in conversation. If this is FUBAR, let me know as well.
the struct element signiture "void* functionCall;" is wrong.
use a function pointer instead.
Eg:
typedef struct fuFunction
{
void* (*functionCall)( void* arg);
void* functionArgs;
void* returnValue;
list_elem elem;
} fuFunction;
then put there:
tempfu->returnValue = (*tempfu->functionCall)(tempfu->functionArgs);