Writing and reading from a buffer with pthread - c

I am trying to use pthread. In my code below I have defined two global variables (arg1 and arg2) and in the main function I start filling each element of arg2 with 1. I want the pthread to print the 101-th element of arg2 as soon as it is filled by main. But the pthread prints nothing. Actually the changes of arg1 is not followed by pthread and the pthread assumes that arg1 is 0. How can I activate a pthread so that when I write in a buffer in main, the pthread starts reading from buffer simultaneously?
Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <pthread.h>
struct arg_struct {
int arg1;
int arg2[1000];
};
//volatile int arg1;
//int arg2[1000];
void *ProcessThread (void *arguments){
struct arg_struct *args = arguments;
if( args -> arg1==100) {
printf("%d", args -> arg2[ args -> arg1]);
}
pthread_exit(NULL);
return NULL;
}
void main(){
struct arg_struct args;
pthread_t thread1;
void *thread_status;
pthread_create(&thread1, NULL, ProcessThread, (void *)&args);
for ( args.arg1=0; args.arg1<1000; args.arg1++){
args.arg2[args.arg1] =1;
}
pthread_join(thread1,&thread_status);
}

The thread is terminated by the time you get to the for loop. arg1 is still not initialized in ProcessThread. You can use a while loop with the sleep function to test periodically the condition.

Related

How to safely end threads and get back to main?

I'm trying to write multithread program to calculate usage of processor. The problem is that i don't know how to safely end threads. I have to end them by signal SIGTERM and I tried
while(flag), phread_exit(), exit(), return(void*)0 but non of them work. I need to end infinite loop and return to main function. I've got two results: Exiting the whole program or program stopped and do nothing.
How can I solve it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <ctype.h>
#include <malloc.h>
#include <time.h>
#include <semaphore.h>
#include "cpudata.h"
#include"cpu_result.h"
#include "reader.h"
#include "analyzer.h"
#include "writer.h"
#define NUM_THREADS 3 //Number of threads
//Declaring variables as volatile
volatile struct cpu_data *datax1;
volatile struct cpu_data *datax2;
volatile struct cpu_result *result;
//Declaring semaphores
sem_t sem1;
sem_t sem2;
sem_t sem3;
volatile int flag=1;
volatile int val[NUM_THREADS]={0,0,0};
void handle_sigterm(int signum)
{
flag=0;
}
void *reader(void *ptr) //Thread to read
{ while(flag){
sem_post(&sem3);
sem_wait(&sem1);
sleep(1); //Make sure that semaphores changes value
load_data(datax1);
sleep(1); //Making sure that values datax1 and datax2 are different
load_data(datax2);
if(datax1==datax2) //checking if values are different
{
perror("Datas are the same \n");
}
}
pthread_exit(val[0]);
}
void *analyzer(void *ptr)//Thread to calculate data
{ while(flag){
sem_post(&sem1);
sem_wait(&sem2);
sleep(1);//Make sure that semaphores changes value
for(int i=0;i<NOPT+1;i++)
{
result[i]=calculate(datax1[i],datax2[i]);//calculating data
}
}
pthread_exit(val[1]);
}
void *writer(void *ptr)//thread to write data
{ while(flag){
sem_post(&sem2);
sem_wait(&sem3);
sleep(1);//Make sure that semaphores changes value
writeresult(result);
printf("\n\n\n\n\n\n");
}
pthread_exit(val[2]);
}
int main(int argc, char **argv)
{
struct sigaction action;
memset(&action,0,sizeof(struct sigaction));
action.sa_handler=handle_sigterm;
sigaction(SIGTERM,&action,NULL);
//Allocating memory for data
datax1=(struct cpu_data *)malloc((NOPT+1)*sizeof(struct cpu_data));
datax2=(struct cpu_data *)malloc((NOPT+1)*sizeof(struct cpu_data));
result=(struct cpu_result *)malloc((NOPT+1)*sizeof(struct cpu_result));
pthread_t thread[NUM_THREADS];//declaring threads
//Initializing semaphores
sem_init(&sem1,0,1);
sem_init(&sem2,0,1);
sem_init(&sem3,0,1);
//creating threads
pthread_create(&thread[0],NULL, &reader, NULL);
pthread_create(&thread[1],NULL, &analyzer, NULL);
pthread_create(&thread[2],NULL, &writer, NULL);
//make sure threads are working
for(int i=0;i<NUM_THREADS;i++){
pthread_join(thread[0],NULL);
pthread_join(thread[1],NULL);
pthread_join(thread[2],NULL);
}
//stopping threads
for(int i=0;i<NUM_THREADS;i++){
pthread_cancel(thread[0]);
pthread_cancel(thread[1]);
pthread_cancel(thread[2]);
}
//freeing memory
sem_destroy(&sem1);
sem_destroy(&sem2);
sem_destroy(&sem3);
free(datax1);
free(datax2);
free(result);
printf("SAFETY CLOSING");
return 0;
}

Printing the default thread's priority

I'd like to write a code which prints the default thread's priority, but I don't know if this is possible. So far I created a thread with default attributes, but I didn't find any statement which allows me to store and print its default priority.
// main.c
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include "task.h"
int main()
{
pthread_attr_t attr;
struct sched_param prio;
pthread_t tid;
int create = 1;
// default attributes
pthread_attr_init(&attr);
create = pthread_create(&tid, &attr, task, NULL);
if (create != 0) exit(EXIT_FAILURE);
pthread_join(tid, NULL);
return(0);
}
// task.h
#ifndef TASK_H
#define TASK_H
void *task();
#endif
// task.c
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "task.h"
void *task()
{
printf("I am a simple thread.\n");
pthread_exit(NULL);
}
I didn't find any statement which allows me to store and print its default priority.
It's pthread_attr_getschedparam and sched_param has scheduling priority (at least).
struct sched_param prio;
pthread_attr_getschedparam(&attr, &prio);
printf("sched_priority = %d\n", prio.sched_priority);

c - can't understand pthread_join()

I can not figure out where I'm wrong, after running the code arrived in the for where it runs the pthread_join() , many pthread_join() return with value 3 instead of 0. Furthermore, printing the value of i is not always consistent and this causes segmentation fault and printing several times of the same position.
Code modified as required in the comments
all the includes are for other parts of the program. Testing only this piece of code creates segmentation fault at error 3 on pthread_join()
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <config.h>
#include <sys/select.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
void *threadF(){
printf("hello\n");
pthread_exit((void*)0);
}
int main(int argc, char *argv[]) {
FILE *fileconf=fopen(argv[2],"r");
if(fileconf==NULL){
fprintf(stderr, "Fopen\n",argv[2]);
return -1;
}
set_conf(fileconf); //parse fileconf and set THREADSINPOOL correctly
pthread_t array[THREADSINPOOL];
int i,err,s=0;
for(i=0;i<THREADSINPOOL;i++){
if((err=pthread_create(&array[i],NULL,&threadF,NULL))!=0){
fprintf(stderr,"thread\n");
exit(errno);
}
}
int tmp;
for(i=0;i<THREADSINPOOL;i++){
tmp=pthread_join(array[i],(void *)&s);
printf("thread: %lu terminated\n tmp: %d\n",array[i],tmp);
}
return 0;
}
The problem is that you are passing the address of an int to a function that expects the address of a void *. On a 64-bit system, there's a good chance that an int is only 32-bits whereas a void * is 64-bits. So pthread_join ends up writing 64-bits into a location that is only big enough for 32-bits. The result is that you overwrite memory that shouldn't being changed, and all sorts of undefined behavior follows.
Here's a way to write the code so that the second argument to pthread_join is actually a pointer to a void *
for (i = 0; i < THREADSINPOOL; i++)
{
void *value;
if (pthread_join(array[i], &value) == 0)
printf("thread %d returned %" PRIiPTR "\n", i, (intptr_t)value);
else
printf("thread %d failed\n", i);
}

pthread_mutex_lock and EAGAIN

I've use pthread for multithreded program and I've got the following situation.
When I run the code without sleep command it causes error at run time, and when I add the sleep command program runs as expected.
With sleep:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t m_writer = PTHREAD_MUTEX_INITIALIZER;
void *print_str(void *args) {
sleep(12);
char *str = (char*) args;
pthread_mutex_lock(&m_writer);
printf("%s", str);
pthread_mutex_unlock(&m_writer);
pthread_exit(NULL);
}
int main(int argc, char **argv) {
pthread_t t1;
pthread_create(&t1, NULL, print_str, "Hello\n");
pthread_mutex_lock(&m_writer);
printf("LOL\n");
pthread_mutex_unlock(&m_writer);
pthread_join(t1, NULL);
return 0;
}
Without sleep:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t m_writer = PTHREAD_MUTEX_INITIALIZER;
void *print_str(void *args) {
char *str = (char*) args;
pthread_mutex_lock(&m_writer);
printf("%s", str);
pthread_mutex_unlock(&m_writer);
pthread_exit(NULL);
}
int main(int argc, char **argv) {
pthread_t t1;
pthread_create(&t1, NULL, print_str, "Hello\n");
pthread_mutex_lock(&m_writer);
printf("LOL\n");
pthread_mutex_unlock(&m_writer);
pthread_join(t1, NULL);
return 0;
}
Error:
futex(0x559c3d3df0a0, FUTEX_WAIT_PRIVATE, 2, NULLHello
) = -1 EAGAIN (Resource temporarily unavailable)
strace shows results of system calls. Pthread functions in Linux are not system calls, they are libc functions implemented on top of (potentilally non-trivial) system calls. You are not interested in what internal system calls return. A single successfull call to ptread_mutex_lock may and sometimes does entail several failing syscalls.
In particular, pthread_mutex_lock cannot possibly result in EAGAIN in this program because there are no attempts to lock the mutex recursively, and the default mutex is not recursive in Linux anyway. The FUTEX_WAIT_PRIVATE syscall that pthread_mutex_lock uses internally can and will result in EAGAIN. This is of no interest whatsoever to the application programmer.

Kill() function between two processes

Can I use the kill() function to send a signal to another process? It should be possible, but kill() fails and I can't understand why.
I have two programs (process_1 and process_2). The first one should set a signal handler to increase a variable, than create a child that uses execve and loads process_2. The other program should send the signal using kill(). I used the shared memory to share process_1's pid through a struct (because I have other variables to share). The code of the first program is as follows:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define KEY_SM 1234
static int value_to_change=0;
typedef struct keys{
pid_t pid_process;
}keynote;
static void test_handler(int signo){
if(signo=SIGUSR1){
printf("received SIGUSR1\n");
value_to_change++;
}
}
int main(){
if((signal(SIGUSR1, test_handler))==SIG_ERR) perror("Errore allocazione SIGUSR1");
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
size_t shm_size = sizeof(keynote);
int shm_id = shmget(KEY_MC, shm_size, flags);
keynote *chv = shmat(shm_id, NULL, 0);
chv->pid_process=getpid();
printf("%d\n",chv->pid_process);
int process_2;
process_2=fork();
if(process_2==0){
char* argv[]={"process_1", "process_2", NULL};
if((execve("process_2", argv, NULL))<0) perror("execve error");
exit(0);
}else if(process_2<0)perror("fork error");
return 0;
}
The second program code is:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define KEY_SM 1234
typedef struct keys{
pid_t pid_process;
}keynote;
static void signal_to_send(pid_t process){
int ret=kill(process, SIGUSR1);
printf("%d", ret);
}
}
int main(int argc, char **argv){
int pid_of_process_1;
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
size_t shm_size = sizeof(keynote);
int shm_id = shmget(KEY_MC, shm_size, flags);
keynote *chv = shmat(shm_id, NULL, 0);
signal_to_send(chv->pid_process);
return 0;
}
process_1 does not wait for process_2. It just exits immediately. At which point process_2 may not even have started. So when process_2 sends the signal, process_1 is likely to not exist anymore.
– kaylum

Resources