I have written a program with a function that prints a character received as an argument continuously, and made 2 threads running that function. The program runs as intended and keeps printing 2 characters interlaced indefinitely. Here is the code:
#include <pthread.h>
#include <stdio.h>
void* print_char(void* th_param) {
char* ch = (char*)th_param;
while(1)
printf("%c", *ch);
return NULL;
}
int main() {
char* c1 = "a";
char* c2 = "b";
pthread_t th_id;
pthread_create(&th_id, NULL, &print_char, (void*)c1);
pthread_t th_id2;
pthread_create(&th_id2, NULL, &print_char, (void*)c2);
return 0;
}
Now I have to modify this program so the print function takes a number argument as well, and prints the character that number of times. What I try is this:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct Params {
char* ch;
int num;
};
void* print_char(void* th_param) {
int i;
struct Params* par = (struct Params*)th_param;
for(i=0; i<par->num; i++) {
printf("%s", par->ch);
}
return NULL;
}
int main() {
struct Params* p1 = (struct Params*)malloc(sizeof(struct Params));
p1->ch = "a"; p1->num = 5;
struct Params* p2 = (struct Params*)malloc(sizeof(struct Params));
p2->ch = "b"; p2->num = 10;
pthread_t th_id;
pthread_create(&th_id, NULL, &print_char, (void*)p1);
pthread_t th_id2;
pthread_create(&th_id2, NULL, &print_char, (void*)p2);
while(1) {}
return 0;
}
But to no avail. Doesn't print a single character, the cursor just stands there blinking doing nothing. I have tried tampering with the code for hours and nothing has worked.
Note that there's not a problem with the struct, because the program works if I remove the for loop and put while(1) instead, and prints the character given to par->ch infinite times again.
The problem is buffered I/O.
Your main()-function loops infinitely, so the process doesn't terminate properly (only by being killed via an external signal), so the stdout-buffer is never flushed by regular process termination.
Since stdout is line-buffered by default, and your printf()s don't contain any newlines, and the amount of characters you try to print is smaller than the I/O-buffer, your program never writes out the buffer, so nothing is printed.
One approach would be to add fflush(stdout); after the printf()s in your thread function, or include a '\n' in the output.
Another (more sane) approach would be to have main() actually wait for the threads to finish, and gracefully terminate when they are done:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct Params {
char* ch;
int num;
};
void* print_char(void* th_param) {
int i;
struct Params* par = (struct Params*)th_param;
for(i=0; i<par->num; i++) {
printf("%s", par->ch);
//fflush(stdout);
}
return NULL;
}
int main() {
struct Params* p1 = (struct Params*)malloc(sizeof(struct Params));
p1->ch = "a"; p1->num = 5;
struct Params* p2 = (struct Params*)malloc(sizeof(struct Params));
p2->ch = "b"; p2->num = 10;
pthread_t th_id;
pthread_create(&th_id, NULL, &print_char, (void*)p1);
pthread_t th_id2;
pthread_create(&th_id2, NULL, &print_char, (void*)p2);
//while(1) {}
pthread_join(th_id, NULL);
pthread_join(th_id2, NULL);
free(p1); //make LeakSanitizer happy, don't leak memory
free(p2);
puts(""); //one newline for command-line beautification
fflush(stdout); //redundant after the puts(""), unless stdout is redirected to a non-interactive stream
return 0;
}
Thanks everyone, using fflush did the job.
To answer the person who asked what platform I ran this on, I was running this on Linux terminal. This was the homework for my OS lab class and pthread_create is all they have taught us so far, pthread_join and more thread management stuff come in later sessions.
Because of your while loop, stdout never get's flushed
Try this :
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct Params {
char* ch;
int num;
};
void* print_char(void* th_param) {
int i;
struct Params* par = (struct Params*)th_param;
for(i=0; i<par->num; i++) {
printf("%s", par->ch);
}
return NULL;
}
int main() {
struct Params* p1 = malloc(sizeof(struct Params));
p1->ch = "a"; p1->num = 5;
struct Params* p2 = malloc(sizeof(struct Params));
p2->ch = "b"; p2->num = 10;
pthread_t th_id;
pthread_create(&th_id, NULL, &print_char, p1);
pthread_t th_id2;
pthread_create(&th_id2, NULL, &print_char, p2);
fflush(stdout);
while(1) {;}
return 0;
}
Related
How should i properly sync threads with mutex?
I'm trying a simple "sync" using mutex, something really small, like just printing a string containing the number of the thread. snippet here:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define MAX_RESOURCE 5
#define NO_THREADS 5
int res_available = MAX_RESOURCE;
pthread_mutex_t mtx;
struct count { int no;};
void *
use_res(void *v) {
pthread_mutex_lock(&mtx);
struct count *p = (struct count *) v;
printf("--thread no %d :" p->nr);
return NULL;
}
int main(){
pthread_t thr[NO_THREADS];
pthread_mutex_init(&mtx, NULL);
for(int i=0; i<N0_THREADS; i++){
struct count *c = malloc(sizeof(struct count));
c->nr = i;
pthread_create(thr[i], NULL, use_res, c))
}
for(int i=0; i<NO_THREADS; i++) {
pthread_join(thr[i], NULL);
}
return 0;
}
Fact is, when executed, the sync doesn't actually occur, actually, what it does occur, is still that "race condition", making the program to print something else everytime.
My question is, how do i stop this race condition? I don't know if i'm using correctly this lock and unlock thing.
You need to release mutex when your thread function finish, also add \n at the end of print, because stdout will buffer this text:
void *
use_res(void *v) {
pthread_mutex_lock(&mtx);
struct count *p = (struct count *) v;
printf("--thread no %d :\n" p->no);
pthread_mutex_unlock(&mtx);
return NULL;
}
I am trying to simulate map-reduce. I have a problem with thread management and passing by reference. When sending a single character it works, but sending a whole struct gives me a segmentation fault.
Each sentence in text.txt is separated by a newline (\n).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <stdbool.h>
typedef struct sentencetype
{
char *sentence;
int length;
}sentencetype;
void *map(void *ptr){
sentencetype allQueuesSingle = *((sentencetype*) ptr);
printf("%c", allQueuesSingle.sentence[0]);
//why doesnt this print the first letter in each line
pthread_exit(NULL);
}
int main(void) {
char letter;
int mapthreadsSize = 0, sentenceSTRSize = 0;
pthread_t *mapthreads = malloc(sizeof(pthread_t));
sentencetype *sentenceSTR;
int fd = open("text.txt", O_CREAT | O_RDONLY, 0777);
sentenceSTRSize = 1;
sentenceSTR = malloc(sentenceSTRSize * sizeof(sentencetype));
sentenceSTR[0].sentence = malloc(sizeof(char));
sentenceSTR[0].length = 0;
while (read(fd, &letter, 1)){
sentenceSTR[sentenceSTRSize-1].length++;
sentenceSTR[sentenceSTRSize-1].sentence = realloc(
sentenceSTR[sentenceSTRSize-1].sentence,
sentenceSTR[sentenceSTRSize-1].length * sizeof(char));
sentenceSTR[sentenceSTRSize-1].sentence[sentenceSTR[sentenceSTRSize-1].length-1] = letter;
if(sentenceSTR[sentenceSTRSize-1].sentence[sentenceSTR[sentenceSTRSize-1].length-1] == '\n'){
//send sentence
mapthreadsSize++;
mapthreads = realloc(mapthreads, mapthreadsSize * sizeof(pthread_t));
pthread_create(&mapthreads[mapthreadsSize-1], NULL, map, &sentenceSTR[sentenceSTRSize-1]);
sentenceSTRSize++;
sentenceSTR = realloc(sentenceSTR, sentenceSTRSize * sizeof(sentencetype));
sentenceSTR[sentenceSTRSize-1].sentence = malloc(sizeof(char));
sentenceSTR[sentenceSTRSize-1].length = 0;
}
}
//send last sentence
mapthreadsSize++;
mapthreads = realloc(mapthreads, mapthreadsSize * sizeof(pthread_t));
pthread_create(&mapthreads[mapthreadsSize-1], NULL, map, &sentenceSTR[sentenceSTRSize-1]);
for (int i = 0; i < mapthreadsSize; i++) {
pthread_join(mapthreads[i], NULL);
}
}
realloc() is allowed to reseat the array. So the pointer that your threads are holding are potentially getting invalidated when you realloc sentenceSTR.
A fairly straightforward way to fix this would be to not create the pthreads until you are done processing the entire file.
I am having some trouble understanding this code since I am new to pthread programming. From what I understand, we create N threads and execute the run function on them, which only prints the thread number. Am I missing something?
Is there any advantage of using snprintf (with buffers) over printf in this particular case? Could this program be improved any further?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg)
{
int *i = (int *) arg;
char buf[123];
snprintf(buf, sizeof(buf), "thread %d", *i);
return buf;
}
int main(int argc, char *argv[])
{
int i;
pthread_t *pt = NULL;
for (i = 0; i < N; i++) {
pthread_create(pt, NULL, run, &i);
}
return EXIT_SUCCESS;
}
First of all, your threads return garbage. Deferencing the pointer returned would be Undefined Behaviour because it points to storage that no longer exists after the function returns. Good thing nothing used the pointer.
Next, the threads don't print anything because snprintf outputs to an array, not stdout.
Furthermore, the threads would print garbage if you switched to printf because the same pointer is passed to to all threads.
And that's assuming the threads have a chance to run since main doesn't wait for the threads to finish. You gotta join them.
Fixed:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define N 5
static void *run(void *arg) {
size_t job = *(size_t*)arg;
printf("Job %zu\n", job);
return NULL;
}
int main(int argc, char *argv[]) {
size_t jobs[N];
pthread_t threads[N];
for (size_t i=0; i<N; ++i) {
jobs[i] = i;
pthread_create(threads+i, NULL, run, jobs+i);
}
for (size_t i=0; i<N; ++i) {
pthread_join(threads[i]);
}
return EXIT_SUCCESS;
}
It's also common to pass an integer cast to a pointer.
#include <inttypes.h>
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
static void *run(void *arg) {
size_t job = *(uintptr_t*)arg;
printf("Job %" PRIuPTR "\n", job);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t threads[N];
for (uintptr_t i=0; i<N; ++i) {
pthread_create(threads+i, NULL, run, (void*)i);
}
for (uintptr_t i=0; i<N; ++i) {
pthread_join(threads[i]);
}
return EXIT_SUCCESS;
}
I wrote the following program to test some assumptions I have about pthreads:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
typedef struct threadArgs * ThreadArgs;
void *foo( void * argStruct );
struct threadArgs{
int pingBool;
};
int main(int argc, char const *argv[]){
pthread_t t1;
int pingBool = 1;
int ch;
ThreadArgs args = (ThreadArgs)malloc(sizeof(struct threadArgs));
args->pingBool = pingBool;
pthread_create(&t1, NULL, foo, args);
while((ch = getchar()) != EOF ){
if( ch == 'q' ){
pingBool = 0;
printf("pingBool now 0\n");
break;
}
}
pthread_join(t1, NULL);
printf("whole program terminating\n");
return 0;
}
void *foo( void * argStruct ){
ThreadArgs args = argStruct;
while( args->pingBool == 1 ){
printf("t1 still going\n");
sleep(1);
}
printf("t1 finished\n");
return NULL;
}
Basically, it sets a variable int pingBool = 1 in main(), passes it into a thread which loops until pingBool == 0. main() then sets pingBool = 0, however, the thread continues to run. I'm pretty sure this is happening because pingBool is getting copied when it is put into the struct and only the copy local to main() is being modified.
Is there a way to share and modify variables between threads like this? I am aware that I can simply make pingBool a global variable rather than pass it into foo(). However, I would prefer not to do that.
Note: If you want to test the code you need to compile with -pthread or -lpthread depending on your compiler. i.e. gcc -Wall -Werror -pthread -o test test.c
You already are sharing the variable between two threads - it's just that you're not referring to the shared copy in main. To refer to the shared copy, main needs to use args->pingBool.
However, your code will then not be correct, because it will have a data race - two threads aren't allowed to access a shared variable without using a synchronisation function. To fix that, you can use a mutex:
struct threadArgs {
pthread_mutex_t lock;
int pingBool;
};
It will need to be initialised:
ThreadArgs args = (ThreadArgs)malloc(sizeof(struct threadArgs));
pthread_mutex_init(&args->lock, NULL);
main should lock the mutex when changing args->pingBool:
if ( ch == 'q' ) {
pthread_mutex_lock(&args->lock);
args->pingBool = 0;
pthread_mutex_unlock(&args->lock);
printf("pingBool now 0\n");
break;
}
and the thread should lock it while reading it:
pthread_mutex_lock(&args->lock);
while ( args->pingBool == 1 ) {
pthread_mutex_unlock(&args->lock);
printf("t1 still going\n");
sleep(1);
pthread_mutex_lock(&args->lock);
}
pthread_mutex_unlock(&args->lock);
Nevermind, solved it myself. The trick was to pass in a pointer to the original variable and access the value of that pointer from foo(). Ammended code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
typedef struct threadArgs * ThreadArgs;
void *foo( void * argStruct );
struct threadArgs{
int *pingBool; // Now a pointer, not an int
};
int main(int argc, char const *argv[]){
pthread_t t1;
int pingBool = 1;
int ch;
ThreadArgs args = (ThreadArgs)malloc(sizeof(struct threadArgs));
args->pingBool = &pingBool; // pass in a pointer to the variable, rather than the variable itself
pthread_create(&t1, NULL, foo, args);
while((ch = getchar()) != EOF ){
if( ch == 'q' ){
pingBool = 0;
printf("pingBool now 0\n");
break;
}
}
pthread_join(t1, NULL);
printf("whole program terminating\n");
return 0;
}
void *foo( void * argStruct ){
ThreadArgs args = argStruct;
int * pingBool = args->pingBool;
while( *pingBool == 1 ){ // access the value of the pointer
printf("t1 still going\n");
sleep(1);
}
printf("t1 finished\n");
return NULL;
}
Try passing args by reference to pthread_create(). It would look like:
pthread_create(&t1, NULL, foo, &args);
I am attempting on creating multiple threads that each thread calculates a prime. I am trying to pass a second argument to a function using thread create. It keeps throwing up errors.
void* compute_prime (void* arg, void* arg2)
{
here is my main() with the create thread. &primeArray[i] after &max_prime is giving me the errors.
for(i=0; i< num_threads; i++)
{
primeArray[i]=0;
printf("creating threads: \n");
pthread_create(&primes[i],NULL, compute_prime, &max_prime, &primeArray[i]);
thread_number = i;
//pthread_create(&primes[i],NULL, compPrime, &max_prime);
}
/* join threads */
for(i=0; i< num_threads; i++)
{
pthread_join(primes[i], NULL);
//pthread_join(primes[i], (void*) &prime);
//pthread_join(primes[i],NULL);
//printf("\nThread %d produced: %d primes\n",i, prime);
printf("\nThread %d produced: %d primes\n",i, primeArray[i]);
sleep(1);
}
the error i get is:
myprime.c: In function âmainâ:
myprime.c:123: 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 * (*)(void *, void *)â
myprime.c:123: error: too many arguments to function âpthread_createâ
It works fine if i take out the second argument.
You can only pass a single argument to the function that you are calling in the new thread. Create a struct to hold both of the values and send the address of the struct.
#include <pthread.h>
#include <stdlib.h>
typedef struct {
//Or whatever information that you need
int *max_prime;
int *ith_prime;
} compute_prime_struct;
void *compute_prime (void *args) {
compute_prime_struct *actual_args = args;
//...
free(actual_args);
return 0;
}
#define num_threads 10
int main() {
int max_prime = 0;
int primeArray[num_threads];
pthread_t primes[num_threads];
for (int i = 0; i < num_threads; ++i) {
compute_prime_struct *args = malloc(sizeof *args);
args->max_prime = &max_prime;
args->ith_prime = &primeArray[i];
if(pthread_create(&primes[i], NULL, compute_prime, args)) {
free(args);
//goto error_handler;
}
}
return 0;
}
In case of std::thread, the user can pass arguments to the thread function in the following method
std::thread(funcName,arg1,arg2);
for instance,
//for a thread function,
void threadFunction(int x,int y){
std::cout << x << y << std::endl;
}
// u can pass x and y values as below
std::thread mTimerThread;
mTimerThread = std::thread(threadFunction,1,12);
This is the code of Manakarse , everything is really good but you need a
pthread_join(thread[i],NULL)
just to be sure all of threads will successfully execute before end of main thread("main will "waiting" while all of threads aren't finished yet)
;
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
int stop_flag;
char name[30];
} _process_data;
typedef struct
{
int meter_no;
int port_no;
} _process_control;
typedef struct
{
_process_data *process_data;
_process_control *process_control;
} compute_prime_struct;
void *compute_prime (void *args)
{
compute_prime_struct *actual_args = args;
printf("actual_args->process_data->stop_flag [%d]\n",actual_args->process_data->stop_flag);
printf("actual_args->process_data->name [%s]\n",actual_args->process_data->name);
printf("actual_args->process_control->meter_no [%d]\n",actual_args->process_control->meter_no);
printf("actual_args->process_control->port_no [%d]\n",actual_args->process_control->port_no);
free(actual_args);
return 0;
}
void fill_data(_process_data *process_data,_process_control *process_control)
{
process_data->stop_flag=1;
process_data->name[0]='P';
process_control->meter_no=6;
process_control->port_no=22;
pthread_t tid;
compute_prime_struct *args = malloc(sizeof (*args));
args->process_data = malloc(sizeof (*args->process_data));
args->process_control = malloc(sizeof (*args->process_control));
memcpy (args->process_data, process_data, sizeof (args->process_data));
memcpy (args->process_control, process_control, sizeof (*args->process_control));
if(pthread_create(&tid, NULL, compute_prime, args))
{
free(args);
printf("Error here");
}
sleep(1);
}
int main()
{
_process_data process_data;
_process_control process_control;
fill_data(&process_data,&process_control);
return 0;
}