C multithreading with pthread - c

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.

Related

Segmentation fault on Dining Philosophers in C with Pthreads

I have this segmentation fault problem in the exercise of the dining philosophers with one thread per philosopher which I can't manage. Each threads think for a random period of time and same with eat. Each philosopher can eat with two forks, he has to pick both forks to eat. To avoid deadlock I made a sort for the picking forks. The philosophers with odd number pick the right fork first. I used a global semaphore which I initialize with the function init at the start of main. Is there someone who can help me please? I tried to put some fprintf(stderr,"HERE\n") but because of concurrency I can't find the problem. Here is the code
'''
//global array of semaphore
pthread_mutex_t *mtx;
//intialize array of semaphore
void init(pthread_mutex_t *mtx){
mtx=malloc(N*sizeof(pthread_mutex_t));
if(!mtx){
perror("malloc fallita\n");
exit(EXIT_FAILURE);
}
for(int i=0;i<N;i++){
if(pthread_mutex_init(&mtx[i],NULL) != 0){
perror("init fallita\n");
exit(EXIT_FAILURE);
}
}
}
void eat(unsigned int *seed){
long r = rand_r(seed) % 800000;
struct timespec t={0,r};
nanosleep(&t,NULL);
}
void think(unsigned int *seed){
long r = rand_r(seed) % 1000000;
struct timespec t={0,r};
nanosleep(&t,NULL);
}
void *filosofo(void *arg){
unsigned int id = *((unsigned int*)arg);
unsigned int seed=id;
int left = id % N;
int right = id-1;
while(1){
think(&seed);
if(id % 2){ //il filosofo di indice dispari prende prima la forchetta di destra
pthread_mutex_lock(&mtx[right]);
pthread_mutex_lock(&mtx[left]);
eat(&seed);
pthread_mutex_unlock(&mtx[left]);
pthread_mutex_unlock(&mtx[right]);
}else{ //il filosofo di indice pari prende prima la forchetta a sinista
pthread_mutex_lock(&mtx[left]);
pthread_mutex_lock(&mtx[right]);
eat(&seed);
pthread_mutex_unlock(&mtx[right]);
pthread_mutex_unlock(&mtx[left]);
}
}
pthread_exit(NULL);
}
int main(void){
init(mtx);
//array of N philosophers
pthread_t *th;
th = malloc(N*sizeof(pthread_t));
if(!th){
perror("Malloc fallita\n");
exit(EXIT_FAILURE);
}
for(unsigned int i=0;i<N;i++){
if(pthread_create(&th[i],NULL,filosofo,(void*)(intptr_t)i) != 0){
perror("create fallita\n");
exit(EXIT_FAILURE);
}
}
for(unsigned int i=0;i<N;i++){
if(pthread_join(th[i],NULL) == -1){
perror("join fallita\n");
}
}
free(th);
free(mtx);
return 0;
}
'''
You need to make init take a pointer to a pointer to a mutex to initialize. Currently, the global mtx isn't changed.
Here's roughly how:
void init(pthread_mutex_t **mtx){ // pointer to pointer
*mtx=malloc(N*sizeof(pthread_mutex_t)); // dereference
if(!*mtx){
perror("malloc fallita\n");
exit(EXIT_FAILURE);
}
for(int i=0;i<N;i++){
if(pthread_mutex_init(&(*mtx)[i],NULL) != 0){ // pointer acrobatics
perror("init fallita\n");
exit(EXIT_FAILURE);
}
}
}
and then pass a pointer to the global mtx in main:
int main(void){
init(&mtx);
I suggest naming your global mutex and your local mutex in init differently so this doesn't confuse you again.
Also, right here you're passing the value of i as a void *, instead of passing its address:
if(pthread_create(&th[i],NULL,filosofo,(void*)(intptr_t)i) != 0){
If you do this (which I actually recommend to avoid race conditions), then you should change filosofo to take input in the same way:
unsigned int id = (unsigned int)arg;

malloc() is returning the same address multiple times, even when I haven't used free()

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.

Running thread simultaneously with program in C

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.

Producer–Consumer & Condition Variables program gets stuck in a infinite loop

When I run my program( running in C ) with usleep it gets stuck in an infinite loop. Without usleep the program doesnt run concurrently though. Any help will be much appreciated.
The program is supposed to allow producers make food while consumers take the food at the same time. My program gets stuck after adding about 5 items and stops. I think it could be a thread not being unlocked but I cant figure it out.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
// rc stands for return code
#define NUM_THREADS 4 // declare consumers
#define NUM_PRODUCERS 2 // declare producers
#define MAX_BUFFER 10 // declare max buffer
pthread_mutex_t bufferBox; // delcare buffer
struct foodItem{ // structure for food
int serialCode;
int producer;
struct foodItem * next;
};
struct buffer{ // Structure for buffer
int size;
struct foodItem * head;
};
struct buffer * myBuffer;
void addFood(int producer, struct buffer * buffer);
void removeItem(struct buffer * buffer);
int serial;
void addFood(int producer, struct buffer * buffer){ // ADD TO BUFFER FUNCTION
struct foodItem * newItem = malloc(sizeof(struct foodItem));
newItem -> producer = producer;
newItem -> serialCode = serial;
if(buffer->size==0){
buffer-> head = newItem;
buffer->size++;
printf("item added serial%d\n",serial);
serial++;
}
else{
struct foodItem * item = buffer ->head;
while(item->next != NULL ){
item = item-> next;
}
item ->next =newItem;
buffer->size++;
printf("item added serial%d\n",serial);
serial++;
}
}
void removeItem(struct buffer * buffer){ //REMOVE FROM BUFFER FUNCTION
if(buffer->size ==1){
free(buffer->head);
}
else{
struct foodItem * temp = buffer -> head;
buffer -> head = buffer ->head->next;
free(temp);
}
buffer->size--;
printf("item removed\n");
}
void *Producers(void *threadid){
int i =11;
while(i>0){
if(myBuffer->size < MAX_BUFFER){
pthread_mutex_lock(&bufferBox);
addFood((int)threadid, myBuffer);
addFood((int)threadid, myBuffer);
pthread_mutex_unlock(&bufferBox);
usleep(20000);
}
else{
printf("OverFlow\n");
}
i--;
}
pthread_exit(NULL);
}
void *Consumers(void *threadid) {
usleep(20000);
int i =6;
while( i >0){
if(myBuffer->size > 0){
pthread_mutex_lock(&bufferBox);
removeItem(myBuffer);
pthread_mutex_unlock(&bufferBox);
usleep(15000);
}
else{
printf("UnderFlow\n");
}
i--;
}
pthread_exit(NULL);
}
int main (int argc, const char * argv[]) {
pthread_t consumers[NUM_THREADS];
pthread_t producers[NUM_PRODUCERS];
long rc,t,i;
int size =0;
myBuffer = malloc(sizeof(struct buffer));
for (t=0;t<NUM_PRODUCERS;t++) {
printf("Creating Producers %ld\n",t);
rc = pthread_create(&producers[t],NULL,Producers,(void *)t); // initial producer
if (rc) {
printf("ERROR return code from pthread_create(): %ld\n",rc);
exit(-1);
}
}
//usleep(10000);
for (t=0;t<NUM_THREADS;t++) {
printf("Creating Consumers %ld\n",t);
rc = pthread_create(&consumers[t],NULL,Consumers,(void *)t); // initial consumers
if (rc) {
printf("ERROR return code from pthread_create(): %ld\n",rc);
exit(-1);
}
}
// wait for threads to exit
for(t=0;t<NUM_THREADS;t++) {
pthread_join(producers[t], NULL);
}
// wait for threads to exit
for(t=0;t<NUM_THREADS;t++) {
pthread_join(consumers[t], NULL);
}
return 0;
}
You need to be careful to initialize any data before using it, for example your addFood(...) routine at the top add a line like this
newItem -> next = NULL;
Similarly in your removeItem(...) function;
if(buffer->size ==1){
free(buffer->head);
buffer->head = NULL;
}
Also as #EOF says in his comment above use the mutex to protect access to buffer->size in your Producers(...) and Consumers(...) routines. For example;
pthread_mutex_lock(&bufferBox);
if(myBuffer->size < MAX_BUFFER) {
....
pthread_mutex_unlock(&bufferBox);
After fixing all of these problems your producers seem to exit last leaving the queue completely full. Not sure what behavior you expect.

return argument (struct) from a thread

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.

Resources