I would like to run my thread simultaneously as my main program. How do I do so? Currently the thread is running a never ending loop, but i would like it to run at the same time as when my main program continues running. Here is my code.
This is my thread:
void *LEDReadingsTimer(char *buffer, int clientSocket) //void *arg
{
while(timer!=0)
{
delay(2000);
LEDReadings(buffer, clientSocket);
printf("Data Sent to Android!\n");
}
return 0;
}
Here is my main code:
timer=1;
wiringPiSetupSys () ;
gertboardAnalogSetup (100) ;
pthread_create(&tid, NULL, LEDReadingsTimer(buffer,clientSocket), NULL);
//Receive and send data from and to Android
while(1){
nread = recv(clientSocket,buffer,4096,0);//recvfrom(clientSocket, buffer,1024, 0, (struct sockaddr *) &serverStorage, &addr_size);
buffer[nread] = '\0';
if((atof(buffer)>=0)&&(atof(buffer)<=1)){
printf("Data Received: %s\n", buffer);
LEDBrightness(buffer);
//LEDReadings(buffer, clientSocket);
}
This is my LEDReadings function.
int LEDReadings(char *buffer, int clientSocket){
int x1, x2 ;
double v1, v2 ;
double a;
printf ("| Channel 0 | Channel 1 |\n") ;
// Read the 2 channels:
x1 = analogRead (100) ; //voltage
x2 = analogRead (101) ; //current
// Convert to a voltage:
v1 = (double)x1 / 1023.0 * 3.3 ;
v2 = (double)x2 / 1023.0 * 3.3 ;
a = v2*30;
printf ("%6.3f|%6.3f\n", v1, a) ;
fflush (stdout) ;
snprintf(buffer, 4096,"%6.3fsplit%6.3f\n", v1, a);
send(clientSocket,buffer,strlen(buffer)+1,0);
return 0;
}
Once my pthread runs, it doesn't go into the next while loop to do recv function.
I assume you know you have to pass pthread_create() a function pointer. There's no such thing in C as a "function pointer with arguments", it's just the address of the function. So what you do here is just call a function the normal way, this function never returns, so the pthread_create() is never executed, waiting for evaluation of one of its arguments.
Have a look at the prototype of pthread_create():
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
This means your start_routine must accept and return void *. So you have to change the signature of your function to
void *LEDReadingsTimer(void *args);
Now, how do you pass the parameters? Simply use a struct. Define this struct somewhere:
struct LEDReadingsTimerArgs
{
char *buffer;
int clientSocket;
};
Then you can change your thread function to this:
void *LEDReadingsTimer(void *args)
{
struct LEDReadingsTimerArgs *lrtArgs = args;
while(timer!=0)
{
delay(2000);
LEDReadings(lrtArgs->buffer, lrtArgs->clientSocket);
printf("Data Sent to Android!\n");
}
return 0;
}
The last argument of pthread_create is for passing the arguments, so start your thread like this:
struct LEDReadingsTimerArgs lrtArgs = {buffer, clientSocket};
pthread_create(&tid, NULL, LEDReadingsTimer, &lrtArgs);
You are calling the thread function yourself rather than giving it to pthread_create as a pointer. This means the function will run forever and no thread will ever be created.
You need to create a way to pass parameters, for example a struct
struct params
{
char *buffer;
int clientSocket;
}
Then you change your thread function into one that gets it as a parameter
void *LEDReadingsTimer(void *args)
{
struct params *pars = args;
while(timer!=0)
{
delay(2000);
LEDReadings(pars->buffer, pars->clientSocket);
printf("Data Sent to Android!\n");
}
return 0;
}
And in your main function you define a struct, set values and pass it to the thread funtion through pthread_create;
struct params pars;
pars.buffer = buffer;
pars.clientSocket = clientSocket;
pthread_create(&tid, NULL, LEDReadingsTimer, &pars);
This way your thread function is called by pthread and the parameters you pass to it will be usable from the thread. Of course always make sure the parameter struct doesn't go out of scope and get freed while the thread is running.
Related
EDIT: I did use free(), ignore the title.
The gist is that every time malloc() is called, the address 0x8403620
is returned, which I found out using Gdb.
tellers[i] = create_teller(0, i, NULL);
I first use malloc() on line 72 to create 3 teller structures. The first addressed returned, visible through Gdb, is 0x84003620. The second is
0x84033a0, the third 0x84034e0. Everything seems fine.
clients[i] = create_client(0, i, -1, -1);
Then I use malloc() on line 77 with the create_client() function to
create 100 clients. The first address, assigned to client[0], is ...
0x8403620. The same as tellers[0]. It gets worse. The next address
returned from malloc() is 0x8403620 again for when i = 1, and so
on for i = 3, 4, ..., 99.
It isn't inherently the create_client() or the create_teller() functions, but
instead the malloc() function itself.
This is simply a very odd situation.
Now, I'd like to ask: Am I using malloc() wrong? Or is my version of malloc() bugged and should I somehow reinstall whatever it is? It's most likely my code since it works for creating the tellers, just not for the clients.
Here is the full code:
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <assert.h>
typedef struct teller teller_t;
typedef struct client client_t;
teller_t * create_teller (pthread_t thread_id, int id, client_t *assigned_client);
client_t * create_client (pthread_t thread_id, int id, int operation, int amount);
void * run_teller (void *arg);
void * run_client (void *arg);
/* types of operations */
#define DEPOSIT 0
#define WITHDRAW 1
#define NUM_TELLERS 3
#define NUM_CLIENTS 100
struct client {
pthread_t thread_id;
int id;
int operation;
int amount;
};
struct teller {
pthread_t thread_id;
int id;
bool available;
client_t *assigned_client;
};
client_t *clients[100];
teller_t *tellers[3];
/* only 2 tellers at a time can access */
sem_t safe;
/* only 1 teller at a time can access */
sem_t manager;
/* amount of tellers available, at most 3 */
sem_t line; /* rename to available? */
/* each teller waiting for a client to be assigned to them */
sem_t wait_for_client[3];
int
main (int argc, char **argv) {
(void) argc;
(void) argv;
srand(time(NULL));
/* This also tells us how many clients have been served */
int client_index = 0;
sem_init(&safe, 0, 2);
sem_init(&manager, 0, 1);
sem_init(&line, 0, 0);
for (int i = 0; i < 3; i++)
sem_init(&wait_for_client[i], 0, 0);
for (int i = 0; i < NUM_TELLERS; i++) {
tellers[i] = create_teller(0, i, NULL);
pthread_create(&tellers[i]->thread_id, NULL, run_teller, (void *) tellers[i]);
}
for (int i = 0; i < NUM_CLIENTS; i++) {
clients[i] = create_client(0, i, -1, -1);
pthread_create(&clients[i]->thread_id, NULL, run_client, (void *) clients[i]);
}
/* DEBUG
for (int i = 0; i < NUM_CLIENTS; i++) {
printf("client %d has id %d\n", i, clients[i]->id);
}
*/
// No threads should get past this point!!!
// ==------------------------------------==
// Should all of this below be handled by the clients instead of main?
while (1) {
if (client_index >= NUM_CLIENTS) {
// TODO:
// tell tellers that there are no more clients
// so they should close, then then close the bank.
break;
}
sem_wait(&line);
for (int i = 0; i < 3; i++) {
if (tellers[i]->available) {
int client_id = clients[client_index]->id;
//printf("client_index = %d\n", client_index); // DEBUG
tellers[i]->assigned_client = clients[client_index++];
tellers[i]->available = false;
printf(
"Client %d goes to Teller %d\n",
client_id,
tellers[i]->id
);
sem_post(&wait_for_client[i]);
break;
}
}
//sem_post(&line); // Is this needed?
}
return EXIT_SUCCESS;
}
teller_t *
create_teller (pthread_t thread_id, int id, client_t *assigned_client) {
teller_t *t = (teller_t *) malloc(sizeof(teller_t));
if (t == NULL) {
printf("ERROR: Unable to allocate teller_t.\n");
exit(EXIT_FAILURE);
}
t->thread_id = thread_id;
t->id = id;
t->available = true;
t->assigned_client = assigned_client;
return t;
}
/* TODO: Malloc returns the same address everytime, fix this */
client_t *
create_client (pthread_t thread_id, int id, int operation, int amount) {
client_t *c = malloc(sizeof(client_t));
if (c == NULL) {
printf("ERROR: Unable to allocate client_t.\n");
exit(EXIT_FAILURE);
}
c->thread_id = thread_id;
c->id = id;
c->operation = operation;
c->amount = amount;
return c;
}
void *
run_teller (void *arg) {
teller_t *t = (teller_t *) arg;
printf("Teller %d is available\n", t->id);
while (1) {
/* tell the line that a teller is available */
sem_post(&line);
/* pass when the line assignes a client to this teller */
sem_wait(&wait_for_client[t->id]);
assert(t->assigned_client != NULL);
if (t->assigned_client->operation == WITHDRAW) {
}
else {
}
}
free(arg);
pthread_cancel(t->thread_id);
return NULL;
}
void *
run_client (void *arg) {
client_t *c = (client_t *) arg;
c->operation = rand() & 1;
printf(
"Client %d waits in line to make a %s\n",
c->id,
((c->operation == DEPOSIT) ? "Deposit" : "Withdraw")
);
free(arg);
pthread_cancel(c->thread_id);
return NULL;
}
Then I use malloc() on line 77 with the create_client() function to create 100 clients.
Not exactly, you create one object, then you spawn a thread that manages that object, run_client() and then repeat. But run_client() basically does nothing except free() your client object! So malloc is totally right returning the same address again, as it is now free memory.
It just happens that your client threads are faster than your main one. Your problem here is that you are freeing the objects from secondary threads while leaving the dangling pointers in the global pointer array. If you use that array for debugging purposes, then nothing is actually wrong here, but if you want to use the client objects somewhen in the future, then you should not free your clients in the first place.
I was trying to create 30 threads with pthread_create within a loop.I used proper headers.
struct student_thread{
int id;
char * message;
};
void *student(void *i)
{
struct student_thread *s;
s = (struct student_thread *) i;
printf("%s%d\n",s->message,s->id);
//sleep(1);
pthread_exit(NULL);
}
void creat_student_thread()
{
pthread_t st[N];
struct student_thread stt[N];
int i,ct;
for(i=0;i<N;i++){
stt[i].id =i+1;
stt[i].message = "Created student thread ";
ct = pthread_create(&st[i],NULL,student,(void *) &stt[i].id);
//enqueue(Q1,stt[i].id);
if(ct){
printf("Error!Couldn't creat thread\n");
exit(-1);
}
}
}
int main()
{
creat_student_thread();
}
But the output shows only 28 threads created.output
What am i missing here?Thanks in advance.
Move the parameter array, 'struct student_thread stt[N];' out of 'creat_student_thread()'. Make it global, say.
Prevent main() from exiting early, eg. with an infinite sleep loop, or input request.
below is C snippet from mongoose webserver http event handler I am working on:
static void HttpEventHandler(struct mg_connection *nc, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *) ev_data;
if (mg_vcmp(&hm->method, "POST") == 0) {
pthread_t thread_id;
int rc;
rc = pthread_create(&thread_id, NULL, thr_func, /* Here I want hm body to be passed after its malloced */);
if (rc) { /* could not create thread */
fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
return EXIT_FAILURE;
}
}//if POST
mg_printf(nc, "HTTP/1.1 200 OK\r\n");
nc->flags |= MG_F_SEND_AND_CLOSE;
}
}
the http post message body, accessible as string using below syntax:
"%.*s", (int) hm->body.len,hm->body.p
I want code sample to malloc hm->body and pass it to the thread in snippet above, also it would be great to explain how to cast the passed void *. if its difficult then please malloc ev_data or hm.
You'd malloc() it as in:
hm->body = malloc(sizeof *(hm->body));
hm->body.p = "string";
/* The above assigns a string literal. If you need to copy some
user-defined string then you can instead do:
hm->body = malloc(size); strcpy(hm->body.p, str);
where 'str' is the string you want copy and 'size' is the length of 'str'.
*/
hm->body.len = strlen(hm->body);
and then pass it to:
rc = pthread_create(&thread_id, NULL, thr_func, hm->body);
In thr_func() you would need to convert the argument to whatever the type of hm->body and then access it (because void * can't be dereferenced directly.). Something like:
void *thr_func(void *arg)
{
struct mg_str *hm_body = arg;
printf("str: %s, len: %zu\n", hm_body->p, hm_body->len);
...
return NULL;
}
There's no need to cast anything to void*. The pthread_create() API expects a void * as the last argument and any data
pointer can be directly assigned to void *. The same applies to struct http_message *hm = (struct http_message *) ev_data; statement as well.
It can be just: struct http_message *hm = ev_data;.
Depending how the "webserver" is implemented, you might need to take care of thread(s) completion as well.
P.S: If you show the "hm" structure, it'll be much easier to explain things.
I have a function task1 that is called by the pthread_create in the main (pure C). It works but, whatever I do on my_pair is lost after the thread is over. I mean I would like the created thread task1 do operations and save them on eventT.. is it possible to return my_pair? how?
void task1(void* eventT){
//struct eventStruct *my_pair = (struct eventStruct*)eventT;
// Tried with malloc but same wrong behavior
struct eventStruct *my_pair = malloc(sizeof((struct eventStruct*)eventT));
// do stuff
my_pair->text = TRIAL;
pthread_exit( my_pair );
}
// Global variable
struct eventStruct *eventT = NULL;
//Calling the thread from the main
eventT = (struct eventStruct*)
thpool_add_work(thpool, (void*)task1, (void*) &eventT);
// Expecting eventT changed (not happening..)
pthread_join( thread, &eventT );
Here's an example of one way to return a struct from a thread - by passing in an allocted struct for the thread to return. This example is similar to your posted code, but uses only pthread functions since I don't know anything about the thpool_add_work() API.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct eventStruct
{
char const* text;
char const* more_text;
};
#define TRIAL "this is a test"
void* task1(void* eventT)
{
struct eventStruct *my_pair = (struct eventStruct*)eventT;
// do stuff
my_pair->text = TRIAL;
pthread_exit( my_pair );
}
int main(void)
{
pthread_t thread;
struct eventStruct* thread_arg = malloc(sizeof *thread_arg);
thread_arg->text = "text initialized";
thread_arg->more_text = "more_text_initialized";
//Calling the thread from the main
pthread_create( &thread, NULL, task1, thread_arg);
void* thread_result;
pthread_join( thread, &thread_result);
struct eventStruct* eventT = thread_result;
puts(eventT->text);
puts(eventT->more_text);
free(eventT);
return 0;
}
Another way this could be done is by having the returned structure allocated by the thread instead of by the caller and passing it in. I'm sure there are many other mechanisms that can be used, but this should get you started.
I'm trying to make a function that has to create a series of pthreads. I'm trying to keep track of each thread by assigning it a unique int t. However, when I try to make more than one thread, the value of t changes, every time I increment it in the main function. It should be pass by value so why is it changing?
// Struct //
typedef struct threadArg {
int verbose;
int listSize;
int thread;
int (*list)[];
} threadArg;
// In main //
for(t=0; t < numThreads; t++){
printf("Creating thread %ld...\n", t);
struct threadArg arg = {
.verbose = verbose,
.list = &arr,
.listSize = size,
.thread = t
};
printf("t: %d\n", (arg.thread));
status = pthread_create(&threadID[t], NULL, threadSort, (void*)&arg);
if (status){
printf("ERROR: failed to create thread", t);
exit(-1);
}
}
// Thread Sort function //
void *threadSort(void* arguments) {
// *** Bubble Sort ***
threadArg* arg = (threadArg*) arguments;
int verbose = arg->verbose;
int size = arg->listSize;
int (*arr)[size] = arg->list;
int t = arg->thread;
if (verbose & INIT) { printf("Thread %d initalized!\n", t); }
}
Thank you for your help,
Wally
It should be pass by value
No, this line passes it "by reference", that is passes the address of arg:
status = pthread_create(&threadID[t], NULL, threadSort, (void*)&arg)
The instance of arg in your code is used and destroyed and recreated for each iteration of the loop.
To fix this modfiy you code like follows:
void * threadSort(void * arguments);
[...]
struct threadArg arg = {
.verbose = verbose,
.list = &arr,
.listSize = size,
.thread = 0,
};
struct threadArg args[t] = {0};
for(t=0; t < numThreads; t++)
{
printf("Creating thread %ld...\n", t);
args[t] = arg;
args[t].thread = t;
printf("t: %d\n", arg.thread);
status = pthread_create(threadID + t, NULL, threadSort, args + t);
[...]
This introduces an array of struct arg with an element for each sperate thread, being nitialised by the value of threadArg, which is not used elsewhere but to have a common initialisation of whag is being passed to the thread function.