I'm trying to pass an array to thread function so that it has access to the array in the function. For the moment it just contains the name of the threads.
const char *a[2];
char *s = "Thread 1";
char *r = "Thread 2";
a[0] = s;
a[1] = r;
pthread_create(&t, NULL, oddhandler, (void *)a[0]);
pthread_create(&y, NULL, evenhandler, (void *)a[1]);
The intention is to write the create like this
pthread_create(&t, NULL, oddhandler, &a);
pthread_create(&y, NULL, evenhandler, &a);
How would I re-write this function to accommodate this change?
static void *
oddhandler(void *p)
{
char *q = (char *)p;
printf("%s is ready.\n", q);
sigset_t set;
int sig = SIGUSR1;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
while (1) {
/* Wait for SIGUSR1 */
sigwait(&set, &sig);
printf("%s received a SIGUSR1!\n", q);
}
return ((void *)NULL);
}
You could try coupling the thread id with the thread data :
typedef struct thread_info {
int thread_id; // different for every thread
void * thread_data; // the same for every thread
}
As in your example program, you could create one function, handler, and have threads adjust based on their id.
pthread_create(&(t[id], NULL, handler, &(info[i]));
void * handler(void * info) {
thread_info * myInfo = (thread_info *) info;
char *q = ((char *) myInfo->thread_data) + myInfo->thread_id;
// rest of function
}
Related
while(1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(mq_identifier, message_buffer, _mqueue_max_msg_size NULL);
if(message_len == -1) { /* error handling... */}
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if(ret) { /* error handling ... */}
}
void * handle_message (void * message) {
puts((char *) message);
return NULL;
}
The above example is not an MRE but it is extremely simple:
I've got a main thread with a loop that constantly consumes messages from a message queue. Once a new message is received, it is stored in the local message_buffer buffer. Then, a new thread is spawned to "take care" of said new message, and thus the message buffer's address is passed into handle_message, which the new thread subsequently executes.
The problem
Often, 2 threads will print the same message, even though I can verify with a 100% certainty that the messages in the queue were not the same.
I am not completely certain, but I think I understand why this is happening:
say that I push 2 different messages to the mqueue and only then I begin consuming them.
In the first iteration of the while loop, the message will get consumed from the queue and saved to message_buffer. A new thread will get spawned and the address of message_length passed to it. But that thread may not be fast enough to print the buffer's contents to the stream before the next message gets consumed (on the next iteration of the loop), and the contents of message_buffer subsequently overridden. Thus the first and second thread now print the same value.
My question is: what is the most efficient way to solve this? I'm pretty new to parallel programming and threading/pthreads and I'm pretty overwhelmed by the different synchronization primitives.
Mutex trouble
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
while(1) {
char message_buffer[SIZE];
pthread_mutex_lock(&m);
ssize_t message_length = mq_receive(mq_identifier, message_buffer, _mqueue_max_msg_size NULL);
pthred_mutex_unlock(&m);
if(message_len == -1) { /* error handling... */}
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if(ret) { /* error handling ... */}
}
void * handle_message (void * message) {
char own_buffer[SIZE];
pthread_mutex_lock(&m);
strncpy(own_buffer, (char *) message, SIZE);
pthread_mutex_unlock(&m);
puts(own_buffer);
return NULL;
}
I don't think my current mutex implementation is right as the threads are still receiving duplicate messages. The main thread can lock the mutex, consume a message into the buffer, unlock the mutex, spawn a thread, but that thread still may hang and the main one could just rewrite the buffer again (as the buffer mutex was never locked by the new thread), effectively making my current mutex implementation useless? How do I overcome this?
The problem is that you end the loop that contains message_buffer before guaranteeing that the thread has finished with that memory.
while (1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(...);
if (message_len == -1) { /* error handling */ }
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if (ret) { /* error handling */ }
/****** Can't go beyond here until thread is done with message_buffer. ******/
}
void * handle_message (void * message) {
char own_buffer[SIZE];
strncpy(own_buffer, (char *) message, SIZE);
/******* Only now can the caller loop back. ******/
puts(own_buffer);
return NULL;
}
You could use a semaphore or similar.
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int copied = 0;
while (1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(...);
if (message_len == -1) { /* error handling */ }
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if (ret) { /* error handling */ }
// Wait until threads is done with message_buffer.
pthread_mutex_lock(&mutex);
while (!copied) pthread_cond_wait(&cond, &mutex);
copied = 0;
pthread_mutex_unlock(&mutex);
}
void * handle_message (void * message) {
char own_buffer[SIZE];
strncpy(own_buffer, (char *) message, SIZE);
// Done with caller's buffer.
// Signal caller to continue.
pthread_mutex_lock(&mutex);
copied = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
puts(own_buffer);
return NULL;
}
(The added chunks effectively perform semaphore operations. See the last snippet of this answer for a more generic implementation.)
But there's a simpler solution: Make the copy before creating the thread.
while (1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(...);
if (message_len == -1) { /* error handling */ }
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, strdup(message_buffer));
if (ret) { /* error handling */ }
}
void * handle_message (void * message) {
char * own_buffer = message;
puts(own_buffer);
free(own_buffer);
return NULL;
}
I'm building a multi-threaded network chat program, but I can't figure out how to pass variables into pthread_create.
I have the following line of code that creates a thread:
pthread_create(&thread, NULL, receive, (void *) socket_fd);
My receive function looks like this:
void * receive(void * socket) {
int socket_fd, response;
char message[MESSAGE_BUFFER];
socket_fd = (int) socket;
while(true) {
response = recvfrom(socket_fd, message, MESSAGE_BUFFER, 0, NULL, NULL);
if (response) {
printf("\nServer> %s", message);
printf("%s", prompt);
}
}
}
How can I pass a prompt variable into this receive function, when calling receive in pthread_create?
You can pack all of the data you want to pass to your thread on creation in a single struct and pass its pointer through the last parameter of pthread_create. in short:
define a struct:
typedef struct{
char* prompt;
int socket;
} thread_data;
and then call pthread_create:
thread_data data;
// place code here to fill in the struct members...
pthread_create(&thread, NULL, receive, (void *) &data);
in your receive function:
void * receive(void * threadData) {
int socket_fd, response;
char message[MESSAGE_BUFFER];
thread_data* pData = (thread_data*)threadData;
socket_fd = pData->socket;
char* prompt = pData->prompt;
while(true) {
response = recvfrom(socket_fd, message, MESSAGE_BUFFER, 0, NULL, NULL);
if (response) {
printf("\nServer> %s", message);
printf("%s", prompt);
}
}
}
Hope this helps.
I'm very new in C and Linux and English is not my mother language. Sorry in advance.
I'm working on a school project which is implementing thread api and I made the thread_create() function using clone().
The problem is that when I call thread_create(&tid1, NULL, (void *)Testcase1, 0); ,
it creates a new thread but TestCase1 also includes thread_create and it doesn't seem create another thread. Let me explain with my code below:
int foo(void* arg){
printf("Hii");
return 0;
}
int thread_create(thread_t *thread, thread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
void* stack;
stack= malloc( STACK_SIZE );
pid_t pid;
if( stack==0)
{
perror( "malloc : could not allocate stack" );
exit( 1 );
}
pid = clone( &foo ,( char* )stack+STACK_SIZE,SIGCHLD|CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES,0 );
if(pid == -1)
{
perror("clone");
exit(2);
}
kill(pid, SIGSTOP);
Thread* newTCB = (Thread*)malloc(sizeof(Thread));
newTCB->stackSize = malloc(STACK_SIZE);
newTCB->pid = pid;
newTCB->status = THREAD_STATUS_READY;
rEnqueue(newTCB);
rPrintqueue();
free(stack);
printf("Child thread returned and stack freed.\n");
return 0;
}
And this is my test code below:
thread_create(&tid1, NULL, (void*)TestCase1, 0);
TestCase1() below:
int Tc1ThreadProc(int param)
{
int tid = 0;
int count = 0;
tid = thread_self();
count = 3;
while (count > 0)
{
/* sleep for 1 seconds */
sleep(2);
printf("Tc1ThreadProc: my thread id (%d), arg is (%d)\n", tid, param);
count--;
}
}
void TestCase1(void)
{
thread_t tid[TOTAL_THREAD_NUM];
thread_create(&tid[0], NULL, (void*)Tc1ThreadProc, (int*)1);
thread_create(&tid[1], NULL, (void*)Tc1ThreadProc, (int*)2);
thread_create(&tid[2], NULL, (void*)Tc1ThreadProc, (int*)3);
while(1){}
return ;
}
it's supposed to print "Tc1ThreadProc: my thread id (%d), arg is (%d)\n" 3 times but it prints only "Hii" which is because of the call to foo().
How do I fix this?
You pass pointer to function "TestCase1" as argument to "thread_create", but inside "thread_create" you don't use it at all:
thread_create(&tid1, NULL, (void*)TestCase1, 0);
You're calling "clone" syscall only with pointer to "foo" function.
From inside "thread_create" your "TestCase1" pointer is named "start_routine", so you need to call similar "clone" syscall, but instead pointer to "foo" you should pass pointer to "TestCase1". Something like that:
pid = clone( start_routine, (char*) stack + STACK_SIZE, SIGCHLD | CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES, 0);
I am trying to pass a structure when creating a thread but does not seem to work correctly!
Here is the structure:
struct analyse_data {
int verbose; //should be 1 or 0
};
Note that verbose can only be 1 or 0 and nothing else.
Here is the method being called (note it can be called multiple times by another method):
void dispatch(struct pcap_pkthdr *header, const unsigned char *packet,
int verbose) {
static bool thread_settings_initialised = false;
printf("Verbose: %d\n", verbose); //Prints 1 or 0
//Only run the first time dispatch method runs
if (thread_settings_initialised == false){
thread_settings_initialised = true;
//...
//Set mutex for the appropriate variables to remain thread safe
//...
//Set attr so threads are "Detached"
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
//Set pthread_cond_init
//...
}
//Put parameters into a struct so can be sent in a thread
struct analyse_data data;
data.verbose = verbose;
//...
pthread_t tid;
printf("data.verbose: %d\n", data.verbose); //This prints 1 or 0
int rc = pthread_create( &tid, &attr, bar, (void *) &data);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
and this is the method thats being called by the thread:
void analyse(void *thread_data) {
struct analyse_data *data;
data = (struct analyse_data *) thread_data;
int verbose = data->verbose;
printf("Verbose = %d\n", verbose ); //Prints weird numbers like -547845...
}
As you can see from my comments, the value of verbose changes when being used inside the method. Why? What am I doing Wrong?
Many Thanks!
Update (thanks to JS1)
I updated my code to use a pointer:
void dispatch(struct pcap_pkthdr *header, const unsigned char *packet,
int verbose) {
static bool thread_settings_initialised = false;
printf("Verbose: %d\n", verbose); //Prints 1 or 0
//...
//Put parameters into a struct so can be sent in a thread
struct analyse_data *data = malloc(sizeof(struct analyse_data)); //NEW
data->verbose = verbose;
//...
pthread_t tid;
printf("data.verbose: %d\n", data.verbose); //This prints 1 or 0
int rc = pthread_create( &tid, &attr, bar, (void *) data);
//...
}
But now the analyse() method always outputs 0, even when verbose is 1!
You should not pass a stack variable to pthread_create. Notice that data is local to the function dispatch and will be out of scope when dispatch returns. You should instead either use malloc to allocate data, or use a static or global variable.
If you use the malloc method, it will look like this:
struct analyse_data *data = malloc(sizeof(struct analyse_data));
data->verbose = verbose;
int rc = pthread_create( &tid, &attr, bar, data);
You must remember to not call free on data from dispatch. The memory should "belong" to the thread, so you should eventually call free on data from the thread when you are done using the contents of data.
Getting seg-fault when I run this code. I commented where I'm getting the seg-fault (in handler() function). I'm not sure, may be I'm wrapping data twice that's why or what's the problem? It's printing correctly till "start_timer" method.
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
typedef struct _data{
char *name;
}data;
struct timer_list{
void* timer_data;
unsigned long expires;
void (*function)(sigval_t);
};
volatile long int second = 0;
void handler(sigval_t val)
{
data *data_handler = val.sival_ptr;
printf("Handler: address of data: %p\n", data_handler);
printf("Handler: address of &data_handler->name: %p\n", &data_handler->name);
printf("Handler entered with value :%s\n", data_handler->name); `**//**SEG-FAULT HERE****`
}
void timer_handler(union sigval val)
{
printf(" ----- Seconds: %ld\n", ++second);
}
/* start timer with all we got as data is timer */
void start_timer(struct timer_list *timer)
{
printf("\nStart_timer...: Timer->data address: %p\n", timer->timer_data);
data *data_handler = timer->timer_data;
printf("Start_timer...: entered with value :%s\n", data_handler->name);
int Ret;
pthread_attr_t attr;
pthread_attr_init( &attr );
//pthread_t tid;
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sigval_t val;
val.sival_ptr = timer->timer_data;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = timer->function;
// sig.sigev_value.sival_int = val;
sig.sigev_value = val;
sig.sigev_notify_attributes = &attr;
data *data_handler1 = (data *)val.sival_ptr;
printf("From sigval...: handler_data address: %p\n", data_handler1);
printf("From sigval...: handler_data->name address: %p\n", &data_handler1->name);
printf("From sigval...: Handler entered with value :%s\n", data_handler1->name);
//create a new timer.
timer_t timerid;
Ret = timer_create(CLOCK_REALTIME, &sig, &timerid);
if (Ret == 0)
{
struct itimerspec in, out;
in.it_value.tv_sec = timer->expires;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = 0;
in.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &in, &out);
}
}
/* Start_timer_on: wrapping up data into one timer structure, and starting timer */
void start_timer_on(data timer_data, unsigned long expires)
{
struct timer_list *timer = (struct timer_list *)malloc(sizeof(struct timer_list)); //Problem was here ... forgot to use malloc
timer->timer_data = &timer_data;
printf("\nTimer->data address: %p\n", &timer_data);
timer->function = handler;
timer->expires = expires;
start_timer(timer);
}
/* Main */
void main()
{
data handler_data1 = {"Handler Data 1"};
//data handler_data2 = {"Handler Data 2"};
//void *data1 = &handler_data1;
//void *data2 = &handler_data2;
pthread_attr_t attr;
pthread_attr_init( &attr );
struct sched_param parm;
parm.sched_priority = 255;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = timer_handler;
sig.sigev_notify_attributes = &attr;
//create a new timer - clock.
timer_t timerid;
timer_create(CLOCK_REALTIME, &sig, &timerid);
struct itimerspec in, out;
in.it_value.tv_sec = 1;
in.it_value.tv_nsec = 0;
in.it_interval.tv_sec = 1;
in.it_interval.tv_nsec = 0;
printf("*** *** *** Main clock starts *** *** ***\n");
timer_settime(timerid, 0, &in, &out);
printf("***** Start timer for data1 for 2 sec *****\n");
start_timer_on(handler_data1, 2);
// printf("***** Start timer for data1 for 5 sec *****\n");
// start_timer(data2, 5);
sleep(20);
}
This might be the problem. In the code below, timer_data is local to function start_timer_on. The object is destroyed as soon as the function exits. So, when accessing the name in handler, it will segfault.
void start_timer_on(data timer_data, unsigned long expires)
{
struct timer_list *timer;
timer->timer_data = &timer_data;
printf("\nTimer->data address: %p\n", &timer_data);
timer->function = handler;
timer->expires = expires;
start_timer(timer);
}
You should use void start_timer_on(data *timer_data, unsigned long expires), so that the data is not freed until main exits.