I need to create two private keys and two threads and then I need to make these threads "exchange" keys
I already created the keys and initialized them and I can also print their value, but I do not know how to make them exchange keys. Maybe someone will tell you something. maybe for this I need to call the same thread several times, but I also don’t know how to do this. I do not ask you to give me a ready-made program, maybe just some little hint or advice
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_key_t key, key2;
void get_data()
{
int *x = (int*)pthread_getspecific(key2);
if(x == NULL)
printf("The value is NULL\n");
else
printf("Key value is %d\n", *x);
}
void get_data2()
{
int *x = (int*)pthread_getspecific(key);
if(x == NULL)
printf("The value is NULL\n");
else
printf("Key value is %d\n", *x);
}
void *func(void *data)
{
int *num;
int *x;
printf("Thread №%ld\n", pthread_self());
num = (int*)data;
get_data();
pthread_setspecific(key, (void*)num);
get_data();
}
void *func2(void *data)
{
int *num;
int *x;
printf("Thread №%ld\n", pthread_self());
num = (int*)data;
get_data2();
pthread_setspecific(key2, (void*)num);
get_data2();
}
int main()
{
int ret_code, type = 3;
pthread_t th, th2;
ret_code = pthread_key_create(&key, NULL);
if(ret_code != 0)
fprintf(stderr, "ptrhead_key_create() error %d\n", ret_code);
ret_code = pthread_key_create(&key2, NULL);
if(ret_code != 0)
fprintf(stderr, "ptrhead_key_create() error %d\n", ret_code);
printf("type: %d\n", type);
ret_code = pthread_create(&th, NULL, func, (void*)&type);
if(ret_code != 0)
fprintf(stderr, "pthread_create() error %d\n", ret_code);
sleep(1);
type = 10;
printf("type: %d\n", type);
ret_code = pthread_create(&th2, NULL, func2, (void*)&type);
if(ret_code != 0)
fprintf(stderr, "pthread_create() error %d\n", ret_code);
ret_code = pthread_join(th, NULL);
ret_code = pthread_join(th2, NULL);
}
Related
I am trying to make race condition and fix it with mutex lock. My code is working correct which is no race condition. Should not it make race condition?
#define MAX_RESOURCES 10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int available_resources = 10;
void* decrease_count(void count);
void increase_count(void *count);
pthread_t thread1;
pthread_t thread2;
int main () {
int decrease = 8;
int increase = 3;
pthread_create(&thread1, NULL, decrease_count, (void*) &decrease);
pthread_create(&thread2, NULL, increase_count, (void*) &increase);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("amount of resource: %d",available_resources);
return 0;
}
void* decrease_count(void *count){
available_resources -= *((int *)count);
return NULL;
}
void* increase_count(void *count){
if(available_resources + *((int *)count) <= MAX_RESOURCES) {
available_resources += *((int *)count);
return 0;
}
return NULL;
}
Well, here, you are declaring in your thread function that you are going to be passed a reference to the increment/decrement value, so you can control how many counts each thread does when it runs.
The idea is to create a mutex in main, and use it in both threads to lock the resource, before doing the increment/decrement.
#define MAX_RESOURCES 10
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int available_resources = 10;
void* decrease_count(void *count);
void* increase_count(void *count);
pthread_t thread1;
pthread_t thread2;
pthread_mutex_t the_mutex;
int main () {
int decrease = 8;
int increase = 3;
/* create the mutex before any of the threads has access to it */
int res = pthread_mutex_init(&the_mutex, NULL);
if (res < 0) {
fprintf(stderr, "pthread_create_mutex: %s\n",
strerror(errno));
}
pthread_create(&thread1, NULL, decrease_count, &decrease);
pthread_create(&thread2, NULL, increase_count, &increase);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("amount of resource: %d\n",available_resources);
return 0;
}
void* decrease_count(void *_count){
int count = *(int *)_count;
int res = pthread_mutex_lock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex lock: %s\n",
__func__,
strerror(errno));
}
available_resources -= count;
res = pthread_mutex_unlock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex unlock: %s\n",
__func__,
strerror(errno));
}
return NULL;
}
void* increase_count(void *_count){
int count = *(int *)_count;
int res = pthread_mutex_lock(&the_mutex);
int overflow = 0;
if (res < 0) {
fprintf(stderr,
"%s: mutex lock: %s\n",
__func__,
strerror(errno));
}
if(available_resources + count <= MAX_RESOURCES) {
overflow = 1;
available_resources += count;
}
res = pthread_mutex_unlock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex unlock: %s\n",
__func__,
strerror(errno));
}
if (overflow) {
printf("got over the top(%d resources)\n",
MAX_RESOURCES);
}
return NULL;
}
I'm writing a project, in which there are two programs, client and server, client sends a string to server, server process it and then sends it back to the client(there can be multiple clients at the same time, and this is where lies my problem). I'm sending process ID from client in the same string that needs to be processed, server extracts process ID. However I'm getting random Core dumps, which arent consistant. Most of the time it works fine. It happens right before invoking strtol() call in receive_message(...) function.
Server receive_message(...) function:
int receive_message(struct message *x){
int ret_val, z;
ret_val = msgrcv(msg_q_id, x, MAX, 0, 0);
if (ret_val == -1){
if (signal_detection == 1){
exit(0);
}
perror("COULDNT receive a message!");
exit(-1);
} else {
int c = 0;
while (x->mtext[c] != '!'){
++c;
}
int h = c;
char tab[strlen(x -> mtext) - c];
int s = 0;
for (int counter = c + 1; counter < strlen(x->mtext); ++counter){
tab[s++] = x->mtext[counter];
}
printf("\n%s\n", tab);
z = strtol(tab, NULL, 10);
memset((x -> mtext) + h, 0, strlen(x -> mtext) - 1 - c);
printf("message received: %s\n", x -> mtext);
}
return z;
}
Whole server code:
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <signal.h>
#define MAX 255
#define CLIENT 1
#define SERVER 2
int signal_detection = 0;
int msg_q_id;
key_t msg_q_key;
struct message;
void create_queue();
void send_message(struct message *x, int pid);
int receive_message(struct message *x);
void delete_message_q();
void to_upper_case(struct message *x);
void signal_handler(int signum, siginfo_t *info, void *ptr);
struct message{
long int mtype;
char mtext[MAX];
};
int main(){
struct message member_of_message;
struct message *ptr;
struct sigaction sig;
int sig_ret;
ptr = &member_of_message;
sig.sa_sigaction = signal_handler;
sig_ret = sigaction(SIGINT, &sig, NULL);
if (sig_ret == -1){
perror("sigaction fail");
}
create_queue();
while (1){
int pid;
memset(member_of_message.mtext, 0, strlen(member_of_message.mtext));
printf("waiting for message\n");
pid = receive_message(ptr);
to_upper_case(ptr);
printf("After uppering: %s\n", member_of_message.mtext);
send_message(ptr, pid);
sleep(1);
}
}
void create_queue(){
printf("starting to create queue\n");
msg_q_key = ftok(",", 4);
msg_q_id = msgget(msg_q_key, 0700|IPC_CREAT);
if (msg_q_id == -1){
perror("COULDNT create msgq");
exit(-1);
} else {
printf("succesfully created: %d !\n", msg_q_id);
}
}
void send_message(struct message *x, int pid){
int ret_val;
x -> mtype = pid + 1;
wysylanie:
ret_val = msgsnd(msg_q_id, x, strlen(x -> mtext) + 1, 0);
if (ret_val == -1){
if (errno == EAGAIN){
perror("message queue is full!");
goto wysylanie;
}
perror("COULDNT send a message");
exit(-1);
} else {
printf("message sent!\n");
}
}
int receive_message(struct message *x){
int ret_val, z;
ret_val = msgrcv(msg_q_id, x, MAX, 0, 0);
if (ret_val == -1){
if (signal_detection == 1){
exit(0);
}
perror("COULDNT receive a message!");
exit(-1);
} else {
int c = 0;
while (x->mtext[c] != '!'){
++c;
}
int h = c;
char tab[strlen(x -> mtext) - c];
int s = 0;
for (int counter = c + 1; counter < strlen(x->mtext) - 1; ++counter){
tab[s++] = x->mtext[counter];
}
printf("\n%s\n", tab);
z = strtol(tab, NULL, 10);
memset((x -> mtext) + h, 0, strlen(x -> mtext) - 1 - c);
printf("message received: %s\n", x -> mtext);
}
return z;
}
void delete_message_q(){
int ret_val;
ret_val = msgctl(msg_q_id, IPC_RMID, 0);
if (ret_val == -1){
perror("COULDNT remove message queue");
exit(-1);
} else {
printf("message queue deleted!\n");
}
}
void to_upper_case(struct message *x){
for (int counter = 0; counter < strlen(x->mtext); ++counter){
x->mtext[counter] = toupper(x->mtext[counter]);
}
}
void signal_handler(int signum, siginfo_t *info, void *ptr){
signal_detection = 1;
printf("\nReceived a signal!\nstopping iteration\n");
delete_message_q();
}
Client code:
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <string.h>
#define MAX 255
#define CLIENT 1
#define SERVER 2
#define M_SENT 3
int msg_q_id;
key_t msg_q_key;
struct message;
int pid;
void create_queue();
void *send_message();
void *receive_message(void *arg);
struct message{
long int mtype;
char mtext[MAX];
};
int main(){
struct message member_of_message;
struct message *ptr;
int thread_val;
ptr = &member_of_message;
pthread_t pid1, pid2;
create_queue();
sleep(1);
printf("creating thread1......\n");
thread_val = pthread_create(&pid1, NULL, send_message, NULL);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
printf("creating thread2......\n");
thread_val = pthread_create(&pid2, NULL, receive_message, ptr);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
thread_val = pthread_join(pid1, NULL);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
thread_val = pthread_join(pid2, NULL);
if (thread_val != 0){
perror("couldnt create thread");
exit(-1);
}
}
void create_queue(){
printf("starting creation of a queue\n");
msg_q_key = ftok(",", 4);
msg_q_id = msgget(msg_q_key, 0700|IPC_CREAT);
if (msg_q_id == -1){
perror("COULDNT create msgq");
exit(-1);
} else {
printf("succesfully created: %d !\n", msg_q_id);
}
}
void *send_message(){
int last_val;
struct message member_of_message;
int ret_val;
char rub[10000];
for (int message_counter = 0; message_counter < M_SENT; ++message_counter){
pid = getpid();
member_of_message.mtype = pid;
char arr[MAX];
if (fgets(arr, MAX - 20, stdin) == NULL){
perror("not a single char read, message sent is empty");
}
if (strlen(arr) == 1){
perror("cannot send empty message!");
exit(-1);
}
if (strchr(arr, '\n') == NULL){
perror("Przepelniono komunikat!");
fgets(rub, 10000, stdin);
}
char temp_arr[20];
int sp_retval;
sp_retval = sprintf(temp_arr, "%d", pid);
if (sp_retval == 0){
perror("0 bytes read");
exit(-1);
}
for (int counter = 0; counter < strlen(arr) - 1; ++counter){
member_of_message.mtext[counter] = arr[counter];
last_val = counter;
}
member_of_message.mtext[last_val + 1] = '!';
strcat(member_of_message.mtext, temp_arr);
wysylanie:
ret_val = msgsnd(msg_q_id, (struct message*)&member_of_message, strlen(member_of_message.mtext), 0);
if (ret_val == -1){
if (errno == EAGAIN){
perror("message queue is full!");
goto wysylanie;
}
perror("COULDNT send a message");
exit(-1);
} else {
printf("message sent!, PID: %d \n", pid);
memset(member_of_message.mtext, 0, strlen(member_of_message.mtext));
}
}
}
void *receive_message(void *arg){
int ret_val;
for (int message_counter = 0; message_counter < M_SENT; ++message_counter){
sleep(1);
((struct message*)arg)->mtype = pid + 1;
ret_val = msgrcv(msg_q_id, (struct message*)arg, MAX, ((struct message*)arg)->mtype, 0);
if (ret_val == -1){
perror("COULDNT receive a message!");
exit(-1);
} else {
printf("message received: %s\n", ((struct message*)arg)->mtext);
memset(((struct message*)arg)->mtext, 0, strlen(((struct message*)arg)->mtext));
}
}
}
ret_val = msgsnd(msg_q_id, (struct message*)&member_of_message, strlen(member_of_message.mtext), 0);
This line shows most clearly the problem with this code. You are sending messages that consist of a message type and message text. The size of a message cannot possibly equal the length of the message text because there also needs to be some number of bytes sent to hold the message type.
The following code is supposed to create one Producer thread and one Consumer thread. The Producer creates random numbers, adds them to a circular buffer(push_back()) and then writes them in an output txt called prod_out.txt. The Consumer "consumes" these numbers by poping them (pop_front()) and then writing them in an output txt called cons_out.txt. For a call like this ./a.out 1 1 10 20 1 the arguements are as follows: there will be 1 producer, 1 consumer, 10 is circular buffer's capacity, 20 random numbers will be generated and the seed for rand_r is 1.
If the buffer's capacity is smaller than the ammount of random nums to be generated the program only writes 9 numbers in the consumers' txt, while the producers' txt is just fine. If they are the same then the consumers' txt does not get created and producers' txt misses one number (namely the last one, just like the consumer txt does when the capacity is smaller than the numbers generated).
This is the main function
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "prodcons.h"
FILE * fp;
int rc;
circular_buffer* cb;
int fileW, my_random;
pthread_mutex_t Mutex;
pthread_cond_t Condition;
args* t_args;
void* Producers(void* fargs){
printf("I am Producer and I am not locked\n");
args* f_args= fargs;
rc = pthread_mutex_lock(&Mutex);
printf("I am Producer and I am locked\n");
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_lock() is %d\n", rc);
pthread_exit(&rc);
}
printf(" The ruler of all mutexes has passed from here and shall start
creating random numbers\n");
for(int i=0; i < *(f_args->rand_count); i++){
if(i==cb->capacity){
printf(" Your producer king will now sleep\n");
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n",
rc);
pthread_exit(&rc);
}
rc = pthread_cond_wait(&Condition, &Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n",
rc);
pthread_exit(&rc);
}
}
my_random =rand_r(f_args->seed)%255;
printf ( "Creating random number %d.\n", my_random);
cb_push_back(cb, &my_random);
if(i==0){
fp=fopen("prod_in.txt", "w");
}else{
fp=fopen("prod_in.txt", "a");
}
fprintf(fp, "Producer %d: %d\n", f_args->ID, my_random);
fclose(fp);
}
printf("I am going to go to signal the consumer.\n");
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n", rc);
pthread_exit(&rc);
}
rc = pthread_mutex_unlock(&Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
pthread_exit(&rc);
}
}
void* Consumer(void* t1){
int *threadId = (int *) t1;
printf("I am Consumer and I am NOT locked\n");
rc = pthread_mutex_lock(&Mutex);
printf("I am Consumer and I am locked\n");
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_lock() is %d\n", rc);
pthread_exit(&rc);
}
if(cb->count == 0){
rc = pthread_cond_wait(&Condition, &Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n", rc);
pthread_exit(&rc);
}
}
int counter = cb-> count;
for (int j=0; j<= counter; j++){
printf("Consumer will now consume with items remaining %d.\n", (int)cb-
>count);
if(j==0){
fp=fopen("cons_out.txt", "w");
}else{
fp=fopen("cons_out.txt", "a");
}
printf("I will now write the following %d, %d inside the
file.\n",*threadId,my_random);
fprintf(fp, "Consumer %d: %d\n",*threadId, my_random);
cb_pop_front(cb,&my_random);
if(cb->count == 0){
rc = pthread_cond_signal(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_signal() is %d\n",
rc);
pthread_exit(&rc);
}
rc = pthread_cond_wait(&Condition, &Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_wait() is %d\n",
rc);
pthread_exit(&rc);
}
}
fclose(fp);
}
rc = pthread_mutex_unlock(&Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
pthread_exit(&rc);
}
}
int main(int argc, char *argv[]){
if (argc !=6){
printf("ERROR: the program should take five arguments!\n");
exit(-1);
}
if(atoi(argv[1])!= 1 || atoi(argv[2])!= 1){
printf("ERROR:This program only functions for one producer and
consumer.\n");
exit(-1);
}
int main_seed = atoi(argv[5]);
int main_rand = atoi(argv[4]);
int buffer_size = atoi(argv[3]);
cb=(circular_buffer*) malloc(sizeof(struct circular_buffer));
t_args=(args*)malloc(sizeof(struct args));
cb_init(cb, buffer_size, sizeof(int));
t_args->seed= &main_seed;
t_args->rand_count= &main_rand;
t_args->ID=1;
int t1=1;
pthread_t p1, c1;
printf ( "I am the ruler of all mutexes. I now shall initialise the
mutex\n");
rc = pthread_mutex_init(&Mutex, NULL);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_init() is %d\n", rc);
exit(-1);
}
rc = pthread_cond_init(&Condition, NULL);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_init() is %d\n", rc);
exit(-1);
}
rc = pthread_create(&p1, NULL, Producers, (void*)t_args); //cast σε void????
if (rc != 0) {
printf("ERROR: return code from pthread_create() is %d\n", rc);
exit(-1);
}
rc = pthread_create(&c1, NULL,Consumer, &t1);
if (rc != 0) {
printf("ERROR: return code from pthread_create() is %d\n", rc);
exit(-1);
}
void *status;
rc = pthread_join(p1, &status);
if (rc != 0) {
printf("ERROR: return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main(): Thread %d terminated successfully.\n", *(int *) status);
rc = pthread_join(c1, &status);
if (rc != 0) {
printf("ERROR: return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main(): Thread %d terminated successfully.\n", *(int *) status);
rc = pthread_mutex_destroy(&Mutex);
if (rc != 0) {
printf("ERROR: return code from pthread_mutex_destroy() is %d\n", rc);
exit(-1);
}
rc = pthread_cond_destroy(&Condition);
if (rc != 0) {
printf("ERROR: return code from pthread_cond_destroy() is %d\n", rc);
exit(-1);
}
free(cb);
free(t_args);
return 1;
}
This is a header file with the 2 structs and the circular buffer functions
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "string.h"
typedef struct circular_buffer
{
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
}circular_buffer;
typedef struct args
{
int ID; //Unique ID from 1 to n
int* seed; //The seed used for rand_r
int* rand_count; //The number of random generated numbers
}args;
void cb_push_back(circular_buffer *cb, const void *item);
void cb_pop_front(circular_buffer *cb, void *item);
void cb_init(circular_buffer *cb, size_t capacity, size_t sz);
void cb_free(circular_buffer *cb);
In this file are the implementetions of the circular buffer functions
#include "prodcons.h"
//initialize circular buffer
//capacity: maximum number of elements in the buffer
//sz: size of each element
void cb_init(circular_buffer *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if(cb->buffer == NULL){
printf("Could not allocate memory..Exiting! \n");
exit(1);
}
// handle error
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
}
//destroy circular buffer
void cb_free(circular_buffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
}
//add item to circular buffer
void cb_push_back(circular_buffer *cb, const void *item)
{
if(cb->count == cb->capacity)
{
printf("Access violation. Buffer is full\n");
exit(1);
}
memcpy(cb->head, item, cb->sz);
cb->head = (char*)cb->head + cb->sz;
if(cb->head == cb->buffer_end)
cb->head = cb->buffer;
cb->count++;
}
//remove first item from circular item
void cb_pop_front(circular_buffer *cb, void *item)
{
if(cb->count == 0)
{
printf("Access violation. Buffer is empy\n");
exit(1);
}
memcpy(item, cb->tail, cb->sz);
cb->tail = (char*)cb->tail + cb->sz;
if(cb->tail == cb->buffer_end)
cb->tail = cb->buffer;
cb->count--;
}
I am trying to use pthread mutex variables and barrier to synchronize the output of my program, but it is not working the way I want it to. Each thread is seeing its final value every 20 values (coming from the for loop) which is alright but I'm trying to make them all get to the same final value (if using 5 threads, all of them should see 100 as final value, with 4 threads, 80, etc)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int SharedVariable =0;
void *SimpleThread(void *args)
{
int num,val,rc;
int which =(int)args;
rc = pthread_mutex_lock(&mutex1);
for(num=0; num<20; num++){
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
//pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
//pthread_mutex_lock(&mutex1);
SharedVariable = val+1;
pthread_mutex_unlock(&mutex1);
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
//pthread_mutex_destroy(&mutex1);
//pthread_exit((void*) 0);
//pthread_mutex_unlock(&mutex1);
}
int main (int argc, char *argv[])
{
if(atoi(argv[1]) > 0){
int num_threads = atoi(argv[1]);
//pthread_mutex_init(&mutex1, NULL);
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_mutex_lock(&mutex1);
for(t=0; t< num_threads; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
//pthread_join(thread1);
}
rc= pthread_mutex_unlock(&mutex1);
}
else{
printf("ERROR: The parameter should be a valid positive number.");
exit(-1);
}
pthread_mutex_destroy(&mutex1);
pthread_exit(NULL);
}
Any suggestions or help is greatly appreciated!
Thanks in advanced!
You need to use a barrier (pthread_barrier_wait()) before checking for the final value - this ensures that no thread will proceed until all threads have reached the barrier.
In addition, you should be calling pthread_join() to wait for the threads to finish, and you only need to hold the mutex around the increment:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier1;
int SharedVariable = 0;
void *SimpleThread(void *args)
{
int num,val;
int which = (int)args;
for(num = 0; num < 20; num++) {
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val + 1;
pthread_mutex_unlock(&mutex1);
}
pthread_barrier_wait(&barrier1);
val = SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
return 0;
}
int main (int argc, char *argv[])
{
int num_threads = argc > 1 ? atoi(argv[1]) : 0;
if (num_threads > 0) {
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_barrier_init(&barrier1, NULL, num_threads);
if (rc) {
fprintf(stderr, "pthread_barrier_init: %s\n", strerror(rc));
exit(1);
}
for (t = 0; t < num_threads; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < num_threads; t++) {
pthread_join(threads[t], NULL);
}
}
else {
printf("ERROR: The parameter should be a valid positive number.\n");
exit(-1);
}
return 0;
}
Try to move the pthread_mutext_unlock(&mutext1) out of the for loop in your SimpleThread. You lock once and unlock mutiple(20) times in your original code.
Alternatively, you could move pthread_mutex_lock(&mutext1) into the for loop, just before you read and modify your SharedVariable. In this case, each thread's add-by-one operation may not consecutive but each thread will get the correct final value.
And before you read the final value of the SharedVariable, use a barrier to wait all the threads finish their job.
I am trying to create a thread and from what I remember this should be the right way to do it:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
int SharedVariable =0;
void SimpleThread(int which)
{
int num,val;
for(num=0; num<20; num++){
if(random() > RAND_MAX / 2)
usleep(10);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val+1;
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t< NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
And the error that I'm getting is this one:
test.c: In function ‘main’: test.c:28: warning: passing argument 3 of
‘pthread_create’ from incompatible pointer type
/usr/include/pthread.h:227: note: expected ‘void * (*)(void *)’ but
argument is of type ‘void (*)(int)’
I cannot change the SimpleThread function so changing the type of the parameter is not an option even though I already tried and it didn't work either.
What am I doing wrong?
SimpleThread should be declared as
void* SimpleThread(void *args) {
}
When you pass parameters to your thread, it is best to define a struct for them, pass a pointer to that struct as void*, and cast back to the right type inside the function.
Here's a compiling and "working" version of your program, although I have to admit to not knowing exactly what it's doing. For the critics in the audience, I apologize in advance for the pthread_join loop at the end.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 5
struct my_thread_info {
long which;
};
int SharedVariable = 0;
void *SimpleThread(void *data)
{
int num, val;
struct my_thread_info *info = data;
for (num = 0; num < 20; num++) {
if (random() > RAND_MAX / 2)
usleep(10);
val = SharedVariable;
printf("*** thread %ld sees value %d\n", info->which, val);
SharedVariable = val + 1;
}
val = SharedVariable;
printf("Thread %ld sees final value %d\n", info->which, val);
free(info);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
struct my_thread_info *info;
for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
info = malloc(sizeof(struct my_thread_info));
info->which = t;
rc = pthread_create(&threads[t], NULL, SimpleThread, info);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < NUM_THREADS; t++) {
pthread_join(threads[t], NULL);
}
}