User level thread - c

I am trying to create user level thread. Here is a sample of my code. Can any body help me what is the problem in this program.
#include<stdio.h>
#include<ucontext.h>
int thread_counter = 0;
int thread1, thread2;
int who_am_i;
struct TCB {
ucontext_t context;
void (* fun_ptr)();
};
struct TCB tcb[3];
char stack[2][8192];
//----------------------
int thread_create(void (*fun)()) {
static volatile int s;
thread_counter++;
s = 0;
getcontext(&tcb[thread_counter].context);
if(!s) {
tcb[thread_counter].context.uc_stack.ss_sp = stack[thread_counter];
tcb[thread_counter].context.uc_stack.ss_size = sizeof(stack[thread_counter]);
tcb[thread_counter].context.uc_link = &tcb[0].context;
tcb[thread_counter].fun_ptr = fun;
s = 1;
}
else {
tcb[who_am_i].fun_ptr();
}
return thread_counter;
}
void thread_yield(int next_thread) {
static volatile int switched;
switched = 0;
getcontext(&tcb[who_am_i].context);
if(!switched) {
switched = 1;
who_am_i = next_thread;
setcontext(&tcb[next_thread].context);
}
}
//----------------------
void f1() {
printf("start f1\n");
thread_yield(thread2);
printf("finish f1:\n");
}
void f2() {
printf("start f2\n");
thread_yield(thread1);
printf("finish f2\n");
}
//----------------------
int main() {
thread1 = thread_create(f1);
thread2 = thread_create(f2);
who_am_i = 0;
thread_yield(thread1);
return 0;
}
Thread is not switching properly. When I run it, it gives following output:
start f1
start f2
finish f2
Thank you

You have an undefined behavior situation.
In thread_create you increase thread_counter the first thing you do. So when you create the second thread thread_counter will be 2. Then you access stack[2] which will give you undefined behavior.
You also hardcode the uc_link member of the context to &tcb[0].context, which is never initialized due to your "premature" increment of thread_counter.
But the main problem is that you don't actually create a new context, you just get the context for the current thread. You should use makecontext for each thread instead.

Related

C: Having a global variable why the value is not saved when it is called in main function,

I'm new to C programming. In my main.c file I declare a global variable and initialize it to 0. This variable will run in pthread function and there it should be updated so I can reuse it main function again.
static int gResult = 0;
void* pthreadTask(){
gResult= readValue(); // It gives 1. gResult should be 1 now.
// But it gives 0.
}
int main(){
if(gResult == 1)printf("Passed test");
}
The problem looks like is that the thread is created but it is not scheduled immediately. So, the thread doesn't run any code and before that you check the value of your global variable. Try checking the variable after your thread has finished running. So, check the variable after pthread_join(). Do not use pthread_exit(). Try the following code (I tried it and it works):
#include <stdio.h>
#include <pthread.h>
static int gRes0 = 0;
static void *pthreadTask5(void* ctx)
{
gRes0 = 1;
printf("Value of gRes0 in thread = %d\n", gRes0);
}
int main(void)
{
pthread_t pt;
pthread_create(&pt, NULL, pthreadTask5, NULL);
// join pthread.
pthread_join(pt, NULL);
printf("Value of gRes0 in main = %d\n", gRes0);
return 0;
}

Timer 0 interruption on PIC18F

I am trying to make a program, that use a interruption for timer 0. The problem is I have to add a function with 2 variables.
Timer configuration will be performed by defining a function with the following prototype: void int_tmr0 (int conf_int, int conf_T0), which I did it in that form:
void conf(int p1, int p2)
{
T0CON=p1;
INTCON=p2;
}
I try to put the records: T0CON, INTCON in these 2 variables: p1 and p2.
I am not sure if I can call these 2 variables in the main function by:
void main()
{
WDTCONbits.ADSHR = 1;
MEMCONbits.EBDIS = 1;
TRISD = 0x0;
INTCONbits.GIE = 1;
p1=0b10001000;
INTCONbits.TMR0IE = 0;
}
Here is the whole code:
#include <xc.h>
unsigned char counter;
void interrupt f1()
{
if(INTCONbits.TMR0IE && INTCONbits.TMR0IF)
{
counter++;
INTCONbits.TMROIF=0
}
void conf(int p1, int p2)
{
T0CON=p1;
INTCON=p2;
}
void main()
{
WDTCONbits.ADSHR = 1;
MEMCONbits.EBDIS = 1;
TRISD = 0x0;
INTCONbits.GIE = 1;
p1=0b10001000;
INTCONbits.TMR0IE = 0;
}
while(1){
LATD= counter;
}
}
If I understood it right,
You need to have a function called by the Timer0 interrupt
Your SDK defines this function as void int_tmr0(int conf_int, int conf_T0)
You need your function to receive some other arbitrary parameters
A solution would be to create the function as the SDK requires and store the parameters in global variables. Then, you can call your function from inside the 'callback' function using these variables as parameters:
int volatile param_1 = 0, param_2 = 0;
void int_tmr0(int conf_int, int conf_T0)
{
conf(param_1, param_2);
}
void conf(int p1, int p2)
{
T0CON=p1;
INTCON=p2;
}
int main()
{
WDTCONbits.ADSHR = 1;
MEMCONbits.EBDIS = 1;
TRISD = 0x0;
INTCONbits.GIE = 1;
param_1=0b10001000;
INTCONbits.TMR0IE = 0;
while(1){
LATD= counter;
}
}

pthread semaphore display nothing on linux

I'm new to linux thread semaphore.
There is no error, no warning, and result output.
What cause this happen?
I suspect semaphore is blocked or infinite loop.
Anyone can see logic incorrect in some place?
initialise sem vlaue : bin_sem = 0, pile_sem = 0, fuel_sem = 0
sem_t bin_sem, pile_sem, fuel_sem;
int pile=0, fuel=0, wantedMineralVal=3, foundMineral=-1;
int isFound(void){
srand(time(NULL));
return (rand()%8+1);
}
void checkResource(){
if(fuel!=0 && pile!=0)
sem_post(&bin_sem);
}
void *deliverFuel(void *args){
while(foundMineral!=wantedMineralVal){
sem_wait(&fuel_sem);
fuel+=24;
checkResource();
}
}
void *deliverPile(void *args){
while(foundMineral!=wantedMineralVal){
sem_wait(&pile_sem);
pile+=12;
checkResource();
}
}
void *drilling(void *args){
do{
foundMineral = isFound();
if(pile == 0 || fuel==0){
sem_post(&pile_sem);
sem_post(&fuel_sem);
sem_wait(&bin_sem);
}
pile-=2;
fuel-=4;
}while(foundMineral!=wantedMineralVal);
}

Thread pool - handle a case when there are more tasks than threads

I'm just entered multithreaded programming and as part of an exercise trying to implement a simple thread pool using pthreads.
I have tried to use conditional variable to signal working threads that there are jobs waiting within the queue. But for a reason I can't figure out the mechanism is not working.
Bellow are the relevant code snippets:
typedef struct thread_pool_task
{
void (*computeFunc)(void *);
void *param;
} ThreadPoolTask;
typedef enum thread_pool_state
{
RUNNING = 0,
SOFT_SHUTDOWN = 1,
HARD_SHUTDOWN = 2
} ThreadPoolState;
typedef struct thread_pool
{
ThreadPoolState poolState;
unsigned int poolSize;
unsigned int queueSize;
OSQueue* poolQueue;
pthread_t* threads;
pthread_mutex_t q_mtx;
pthread_cond_t q_cnd;
} ThreadPool;
static void* threadPoolThread(void* threadPool){
ThreadPool* pool = (ThreadPool*)(threadPool);
for(;;)
{
/* Lock must be taken to wait on conditional variable */
pthread_mutex_lock(&(pool->q_mtx));
/* Wait on condition variable, check for spurious wakeups.
When returning from pthread_cond_wait(), we own the lock. */
while( (pool->queueSize == 0) && (pool->poolState == RUNNING) )
{
pthread_cond_wait(&(pool->q_cnd), &(pool->q_mtx));
}
printf("Queue size: %d\n", pool->queueSize);
/* --- */
if (pool->poolState != RUNNING){
break;
}
/* Grab our task */
ThreadPoolTask* task = osDequeue(pool->poolQueue);
pool->queueSize--;
/* Unlock */
pthread_mutex_unlock(&(pool->q_mtx));
/* Get to work */
(*(task->computeFunc))(task->param);
free(task);
}
pthread_mutex_unlock(&(pool->q_mtx));
pthread_exit(NULL);
return(NULL);
}
ThreadPool* tpCreate(int numOfThreads)
{
ThreadPool* threadPool = malloc(sizeof(ThreadPool));
if(threadPool == NULL) return NULL;
/* Initialize */
threadPool->poolState = RUNNING;
threadPool->poolSize = numOfThreads;
threadPool->queueSize = 0;
/* Allocate OSQueue and threads */
threadPool->poolQueue = osCreateQueue();
if (threadPool->poolQueue == NULL)
{
}
threadPool->threads = malloc(sizeof(pthread_t) * numOfThreads);
if (threadPool->threads == NULL)
{
}
/* Initialize mutex and conditional variable */
pthread_mutex_init(&(threadPool->q_mtx), NULL);
pthread_cond_init(&(threadPool->q_cnd), NULL);
/* Start worker threads */
for(int i = 0; i < threadPool->poolSize; i++)
{
pthread_create(&(threadPool->threads[i]), NULL, threadPoolThread, threadPool);
}
return threadPool;
}
int tpInsertTask(ThreadPool* threadPool, void (*computeFunc) (void *), void* param)
{
if(threadPool == NULL || computeFunc == NULL) {
return -1;
}
/* Check state and create ThreadPoolTask */
if (threadPool->poolState != RUNNING) return -1;
ThreadPoolTask* newTask = malloc(sizeof(ThreadPoolTask));
if (newTask == NULL) return -1;
newTask->computeFunc = computeFunc;
newTask->param = param;
/* Add task to queue */
pthread_mutex_lock(&(threadPool->q_mtx));
osEnqueue(threadPool->poolQueue, newTask);
threadPool->queueSize++;
pthread_cond_signal(&(threadPool->q_cnd));
pthread_mutex_unlock(&threadPool->q_mtx);
return 0;
}
The problem is that when I create a pool with 1 thread and add a lot of jobs to it, it does not executes all the jobs.
[EDIT:]
I have tried running the following code to test basic functionality:
void hello (void* a)
{
int i = *((int*)a);
printf("hello: %d\n", i);
}
void test_thread_pool_sanity()
{
int i;
ThreadPool* tp = tpCreate(1);
for(i=0; i<10; ++i)
{
tpInsertTask(tp,hello,(void*)(&i));
}
}
I expected to have input in like the following:
hello: 0
hello: 1
hello: 2
hello: 3
hello: 4
hello: 5
hello: 6
hello: 7
hello: 8
hello: 9
Instead, sometime i get the following output:
Queue size: 9 //printf added for debugging within threadPoolThread
hello: 9
Queue size: 9 //printf added for debugging within threadPoolThread
hello: 0
And sometimes I don't get any output at all.
What is the thing I'm missing?
When you call tpInsertTask(tp,hello,(void*)(&i)); you are passing the address of i which is on the stack. There are multiple problems with this:
Every thread is getting the same address. I am guessing the hello function takes that address and prints out *param which all point to the same location on the stack.
Since i is on the stack once test_thread_pool_sanity returns the last value is lost and will be overwritten by other code so the value is undefined.
Depending on then the worker thread works through the tasks versus when your main test thread schedules the tasks you will get different results.
You need the parameter passed to be saved as part of the task in order to guarantee it is unique per task.
EDIT: You should also check the return code of pthread_create to see if it is failing.

kprobe, function scheduling - processor lockup - Linux kernel

I've a function I wrote in order to run a given function on all processors. It works perfectly well in all cases except the following case:
When I try to use it within a kprobe that I registered.
Here's some code:
static DEFINE_MUTEX(entryMutex);
static struct kretprobe my_kprobe = {
.entry_handler = (kprobe_opcode_t *) NULL,
.handler = (kprobe_opcode_t *) process_entry_callback,
.maxactive = 1000,
.data_size = 0
};
static int driver_init(void)
{
my_kprobe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("sys_execve");
if ((ret = register_kretprobe(&my_kprobe)) < 0)
return -1;
return 0;
}
void foo(void* nothing)
{
printk("In foo\n");
}
static int process_entry_callback(struct kretprobe_instance* instance, struct pt_regs* regs)
{
mutex_lock(&entryMutex);
for(int i = 0; i < 4; ++i) // assumes there are 4 processors
run_func(foo, NULL, i);
mutex_unlock(&entryMutex);
return 0;
}
void run_func_wrap(struct function_data* data)
{
data->func(data->context);
wake_up_process(data->waiting_task);
*(data->condition) = TRUE;
}
void run_func(SCHEDULED_FUNC func, void *context, int processor)
{
struct function_data data;
struct task_struct* th;
BOOLEAN condition = FALSE;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
data.func = func;
data.waiting_task = current;
data.context = context;
data.condition = &condition;
th = kthread_create(sched_func_wrap, &data, "th");
kthread_bind(th, processor);
wake_up_process(th);
wait_event(queue, condition);
}
F
After the call to 'run_func' in process_entry_callback I can no longer run any programs. Every time I start a new program it just stuck. After a while I get 'processor lockup' warning in the system log.
I suspect that it has something to do with the IRQ levels.
Any suggestions ?
EDIT:
It also happens when using the following function:
smp_call_function_single
which can be found in smp.c # the Linux kernel source code.
instead of my function:
run_func

Resources