Shared mutex between process - process

I am learning mutex usage between process. I have a question w.r.t this.
Since each process has its own address space, the mutex defined by one process cannot be seen by another. On googling, I came across usage of pthread_mutex_setpshared() to get this done. I am attaching my code below. But looks like even now, the mutex is not shared between processes. How is this to be modified.
I know this can be achieved using named semaphore. But want to know the usage using mutex.
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <semaphore.h>
#include <fcntl.h>
int main()
{
pid_t pid;
int ch = 0;
//sem_t *s1;
//s1 = sem_open("/sem", O_CREAT, 0666, 0);
pthread_mutex_t m1;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&m1, &attr);
pid = fork();
if(pid == 0)
{
pthread_mutex_lock(&m1);
printf("\nChild process");
printf("\nPress 1 to unlock from child:");
scanf("%d", &ch);
if(ch == 1)
{
pthread_mutex_unlock(&m1);
}
//sem_post(s1);
}
else if (pid > 0)
{
pthread_mutex_lock(&m1);
//sem_wait(s1);
printf("\nParent process");
printf("\nPress 2 to unlock from parent:");
scanf("%d", &ch);
if(ch == 2)
{
pthread_mutex_unlock(&m1);
}
}
else
{
printf("\nError");
}
}

As well as setting the PTHREAD_PROCESS_SHARED attribute, you need to arrange to have the mutex itself (your m1 variable) stored in shared memory, accessible by both processes. A duplicate, as created by your fork(), does not work.
If you use mmap() to create an anonymous mapping with the MAP_SHARED flag, and allocate the mutex within that, then it will be shared between the processes after the fork() and will work.

Related

Does fork() duplicate only the calling thread or all threads?

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int i = 0;
fork();
for(;i<3; ++i)
printf("%d", i);
fork();
return 0;
}
Here is my code. I want to know how many processes do I have after executing the last fork()
Fork splits the current process into 2 processes, so you have 2 after the first fork and 4 after the second.
Edit: After the first fork() there will be two processes, both executing the following statements. The initial process and the forked process will both call fork() the second time, resulting in 4 total processes after that call. For more info check out this link: http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html

Rtos ( when using semaphore or mutex with lcd it run task with low priority first?)

This code for display on LCD according to which keep semaphore, it should begin from task with high priority, but it begin with task with low priority
if I delete the semaphore, it will begin with high priority.
#include <avr/io.h>
#include <avr/interrupt.h>
#include "lcd.h"
#include "macros.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#define F_CPU 16000000
#include <util/delay.h>
/*task function prototype */
void TASK1(void * pvParameters );
void TASK2(void * pvParameters );
//void TASK3(void * pvParameters );
/*create a semaphore handle*/
//xSemaphoreHandle task_sync_sem ;
xSemaphoreHandle Semaphore1;
int main(void)
{
DDRD=0xff;
DDRB=0xff;
/*init LCD*/
LCD_init();
//task_sync_sem = xSemaphoreCreateCounting(1,0);
Semaphore1=xSemaphoreCreateCounting(1,1);
/*create task */
xTaskCreate(TASK1,"task1",400,NULL,8,NULL);
xTaskCreate(TASK2,"task2",400,NULL,6,NULL);
//xTaskCreate(TASK3,"task3",400,NULL,3,NULL);
/*Start OS "Scheduler " */
vTaskStartScheduler();
}
void TASK1(void * pvParameters )
{
for (;;)
{
LCD_Clear();
u8 vale=xSemaphoreTake(Semaphore1,50);
if(vale==1)
{
LCD_WriteData('A');
LCD_WriteData('B');
LCD_WriteData('C');
xSemaphoreGive(Semaphore1);
}
_delay_ms(1000);
vTaskDelay(2000);
}
}
void TASK2(void * pvParameters )
{
for (;;)
{
LCD_Clear();
u8 vale=xSemaphoreTake(Semaphore1,50);
if(vale==1)
{
LCD_WriteData('X');
LCD_WriteData('Y');
LCD_WriteData('Z');
xSemaphoreGive(Semaphore1);
vTaskDelay(2000);
}
}
}
Check your configMAX_PRIORITIES is higher or equal to 8 (your maximum priority).
Task Priorities
For your case, a Mutex seems more appropriate Mutex
You should also include the LCD_Clear() within the semaphore lock.
Behavior:
Your problem is probably related to the fact you create a counting semaphore with a maximum value of 1 and a starting value of 1, so it is already "Taken".
Semaphore1=xSemaphoreCreateCounting(1,1);
My guess, when your Task 1 execute, it is not able to take the semaphore and thus wait for 50 tick, in which the Task 2 will execute, but should also fail to take the semaphore as it is never "given" since it was locked from the begining.
Try to initialize with Semaphore1=xSemaphoreCreateCounting(1,0); , or better, use a mutex.

Find CPU times and system times of process in linux

I have a main program that creates two children and each children calls execlv. At the end of the program how do I calculate the CPU times and system times of the parent and two process?
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int main()
{
pid_t pid1,pid2,wid; // variable for parent and two children
char *my_args[3]; // strign array for containing the arguments for executing sigShooter1
// int aInt = 368; //
char str[15]; // strign to contain the pids of children when passing as command line arguments
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sigperf1";
my_args[1] = "0";
my_args[2] = NULL;
execv("sigshooter1",my_args);
fprintf(stderr,"sigshooter1 cannot be executed by first child...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
sprintf(str, "%d", pid1);
my_args[0] = "sigperf1";
my_args[1] = str;
my_args[2] = NULL;
// printf("this is converted = %s\n",my_args[1]);
//sleep(1);
execv("sigshooter1",my_args);
fprintf(stderr,"sigshooter1 cannot be executed by second child...");
exit(-1);
}
wid = wait(NULL);
}
You'll need a profiler for that. For starters, you can run perf stat ./a.out to get the total CPU time of all three processes, and perf stat -i ./a.out to get the CPU time of parent process only.
If you need something more detailed, take a look at more serious tools like valgrind or gprof.

running gzip on sigle core in muticore environment under unix

I have a requirement to use only single core to test gzip performance in multi-core cpu environment(not sure what is the default settings for gzip in this case). Need help to find out the command to execute gzip compression in single core.
Thanks
gzip is single threaded by default so in effect it will look like it's running on one core ie it might run on several physical cores but it won't be in parallel.
If you absolutely must run on one core and you're on linux you would set affinity to a particular core.
http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html
This is code that I got from the man page.
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
int
main(int argc, char *argv[])
{
cpu_set_t set;
int parentCPU, childCPU;
int nloops, j;
if (argc != 4) {
fprintf(stderr, "Usage: %s parent-cpu child-cpu num-loops\n",
argv[0]);
exit(EXIT_FAILURE);
}
parentCPU = atoi(argv[1]);
childCPU = atoi(argv[2]);
nloops = atoi(argv[3]);
CPU_ZERO(&set);
switch (fork()) {
case -1: /* Error */
errExit("fork");
case 0: /* Child */
CPU_SET(childCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1)
errExit("sched_setaffinity");
for (j = 0; j < nloops; j++)
getppid();
exit(EXIT_SUCCESS);
default: /* Parent */
CPU_SET(parentCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1)
errExit("sched_setaffinity");
for (j = 0; j < nloops; j++)
getppid();
wait(NULL); /* Wait for child to terminate */
exit(EXIT_SUCCESS);
}
}
If you need to test with no interruptions from the kernel you need to write a kernel module for that.

API for handling wait queues are not working

I have to make tasks as processes in Linux but I don't want the process to execute until all the processes are created. So I thought of moving the processes to wait queue soon after creation and wait until all processes are created.
#include <unistd.h> /* Symbolic Constants */
#include <sys/types.h> /* Primitive System Data Types */
#include <errno.h> /* Errors */
#include <stdio.h> /* Input/Output */
#include <stdlib.h> /* General Utilities */
#include <pthread.h> /* POSIX Threads */
#include <string.h> /* String handling */
#include <sched.h>
#include <linux/kernel.h>
#include <time.h>
#include <sys/resource.h>
#include <stddef.h>
#include <linux/sched.h>
#include <linux/wait.h> /* for wait_event_interruptible() & wake_up_interruptible() */
int done = 0;
static DECLARE_WAIT_QUEUE_HEAD(queue);
int main()
{
int pid1, pid2;
if ((pid1 = fork()) < 0) //create a child process
exit(1);
if ((pid2 = fork()) < 0) //create a child process
exit(1);
if (pid1 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 1\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
if (pid2 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 2\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
return 0;
}
But when I tried this sample code it shows these errors.
$ gcc -Wall try.c
try.c:18:8: warning: type defaults to ‘int’ in declaration of ‘DECLARE_WAIT_QUEUE_HEAD’ [-Wimplicit-int]
try.c:18:1: warning: parameter names (without types) in function declaration [enabled by default]
try.c: In function ‘main’:
try.c:33:6: warning: implicit declaration of function ‘wait_event_interruptible’ [-Wimplicit-function-declaration]
try.c:33:31: error: ‘queue’ undeclared (first use in this function)
try.c:33:31: note: each undeclared identifier is reported only once for each function it appears in
try.c:39:2: warning: implicit declaration of function ‘wake_up_interruptible’ [-Wimplicit-function-declaration]
try.c: At top level:
try.c:18:8: warning: ‘DECLARE_WAIT_QUEUE_HEAD’ declared ‘static’ but never defined [-Wunused-function]
When I checked $ man wait_event_interruptible, it says "No manual entry for wait_event_interruptible". So the API is missing in the library. How can I add it to the library? Thanks in advance.
wait_event_interruptible(), wake_up_interruptible() are some of the Kernel's API to create and use wait queues. You cannot use those from the user-land!
If I understand your purpose correctly, what you need to do is to create N processes barrier. If you know the number of the processes (N), you can easily use semaphores: initialize the semaphore with zero, all processes call down() and the last process calls up() N times. You can also use message queues.
You can also use the Linux API for barriers: pthread_barrier_wait and pthread_barrier_init, but I have not used this before.