Create threads for equal time intervals

I run this program where I have several threads. Three threads generate signals for the same parent process. There are four processor streams for processing the signals generated by the signal conditioning streams. I have a monitoring thread that also receives signals and processes as per. However, I have a situation. I see that the signals are not divided evenly. I mean, the signals are aimed at the same process. I have four handler threads and one monitoring thread waiting for a signal. Therefore, any of them can receive a signal. I expected this to be evenly distributed. However, I could see that at that time whole bursts of signals were being received by the handler threads. The next time the entire packet of signals is processed by the monitor stream. Why is it not homogeneous. I added a sleep call after the handler / monitor threads completed processing a single signal. Therefore, as soon as the handler / monitor completes one signal, it should give another opportunity to process the next signal. However, the output does not display a case

#include <pthread.h> #include <signal.h> #include <stdlib.h> #include <iostream> #include <unistd.h> #include <sys/types.h> #include <sys/time.h> #include <signal.h> #include <cstdio> #include <stdlib.h> #define NUM_SENDER_PROCESSES 3 #define NUM_HANDLER_PROCESSES 4 #define NUM_SIGNAL_REPORT 10 #define MAX_SIGNAL_COUNT 100000 using namespace std; volatile int usrsig1_handler_count = 0; int usrsig2_handler_count = 0; int usrsig1_sender_count = 0; int usrsig2_sender_count = 0; int monitor_count = 0; int usrsig1_monitor_count = 0; int usrsig2_monitor_count = 0; double time_1[10]; double time_2[10]; int lock_1 = 0; int lock_2 = 0; int lock_3 = 0; int lock_4 = 0; int lock_5 = 0; double timestamp() { struct timeval tp; gettimeofday(&tp, NULL); return (double)tp.tv_sec + tp.tv_usec / 1000000.; } void sleepMs(double seconds) { usleep((unsigned int)(seconds*1000000)); } void *senderfunc(void *parm) { srand(time(0)); while(true) { int signal_id = rand()%2 + 1; if(signal_id == 1) { while(__sync_lock_test_and_set(&lock_3,1) != 0) { } usrsig1_sender_count++; lock_3 = 0; kill(getpid(), SIGUSR1); } else { while(__sync_lock_test_and_set(&lock_4,1) != 0) { } usrsig2_sender_count++; lock_4 = 0; kill(getpid(), SIGUSR2); } int r = rand()%10 + 1; double s = (double)r/100; sleepMs(s); } } void *handlerfunc(void *parm) { int *index = (int *)parm; sigset_t set; sigemptyset(&set); //cout << (*index) << endl; if((*index) % 2 == 0) { sigaddset(&set, SIGUSR1); } else { sigaddset(&set, SIGUSR2); } int sig; while(true) { sigwait(&set, &sig); //cout << "Handler" << endl; if (sig == SIGUSR1) { while(__sync_lock_test_and_set(&lock_1,1) != 0) { } usrsig1_handler_count++; lock_1 = 0; } else if(sig == SIGUSR2) { while(__sync_lock_test_and_set(&lock_2,1) != 0) { } usrsig2_handler_count++; lock_2 = 0; } sleepMs(0.0001); } } void *monitorfunc(void *parm) { sigset_t set; sigemptyset(&set); sigaddset(&set, SIGUSR1); sigaddset(&set, SIGUSR2); int sig; while(true) { sigwait(&set, &sig); //cout << "Monitor" << endl; if(sig == SIGUSR1) { time_1[usrsig1_monitor_count] = timestamp(); usrsig1_monitor_count++; } else if(sig == SIGUSR2) { time_2[usrsig2_monitor_count] = timestamp(); usrsig2_monitor_count++; } monitor_count++; //cout << monitor_count << endl; if(monitor_count == NUM_SIGNAL_REPORT) { double difference_1 = 0; double difference_2 = 0; if(usrsig1_monitor_count > 1) { for(int i=0; i<usrsig1_monitor_count-1; i++) { difference_1 = difference_1 + time_1[i+1] - time_1[i]; } cout << "Interval SIGUSR1 = " << difference_1/(usrsig1_monitor_count-1)<< endl; } if(usrsig2_monitor_count > 1) { for(int i=0; i<usrsig2_monitor_count-1; i++) { difference_2 = difference_2 + time_2[i+1] - time_2[i]; } cout << "Interval SIGUSR2 = " << difference_2/(usrsig2_monitor_count-1) << endl; } cout << "Count SIGUSR1 = " << usrsig1_sender_count << endl; cout << "Count SIGUSR2 = " << usrsig2_sender_count << endl; monitor_count = 0; usrsig1_monitor_count = 0; usrsig2_monitor_count = 0; } sleepMs(0.001); } } int main(int argc, char **argv) { if(argc != 2) { cout << "Required parameters missing. " << endl; cout << "Option 1 = 1 which means run for 30 seconds" << endl; cout << "Option 2 = 2 which means run until 100000 signals" << endl; exit(0); } int option = atoi(argv[1]); int i; pthread_t handlers[NUM_HANDLER_PROCESSES]; pthread_t generators[NUM_SENDER_PROCESSES]; pthread_t monitor; sigset_t set; sigset_t oldset; sigemptyset(&oldset); sigemptyset(&set); sigaddset(&set, SIGUSR1); sigaddset(&set, SIGUSR2); pthread_sigmask(SIG_BLOCK, &set, &oldset); int handler_mask[4] = {0,1,2,3}; //Initializing the handler threads for(i=0; i<NUM_HANDLER_PROCESSES; i++) { pthread_create(&handlers[i], NULL, handlerfunc, (void *)&handler_mask[i]); } pthread_create(&monitor, NULL, monitorfunc, NULL); sleep(5); for(i=0; i<NUM_SENDER_PROCESSES; i++) { pthread_create(&generators[i], NULL, senderfunc, NULL); } if(option == 1) { cout << "Option 1 " << endl; //sleep(30); while(true){ } exit(0); } else { while(true) { if((usrsig1_handler_count + usrsig2_handler_count) >= MAX_SIGNAL_COUNT) { cout << "Count SIGUSR1 = " << usrsig1_handler_count << endl; cout << "Count SIGUSR2 = " << usrsig2_handler_count << endl; exit(0); } else { pthread_yield(); } } } } 

Here is my conclusion

 HandlerHandler Handler Handler Monitor Monitor ... whole bunch of Monitor messages Monitor Monitor Handler Handler ... whole bunch of Handler messages Handler Handler 

You can see a splash in the monitor, followed by a pop-up handler window. However, in the code, when the handler / monitor processes the signal and switches to a sigwait, I added a sleep call so that the rotation is transmitted to the next available stream. However, this does not help. I think it should have been uniform. However, the monitor is still torn and printed. Despite the fact that I put a dream on the monitor after it finished working on the signal

+8
c multithreading operating-system
source share
2 answers

What OS are you using? This task requires a real-time operating system (RTOS). I had good results using a very small RTOS called On Time RTOS-32 to control the robot controller. It can perform temporary processing with a guaranteed delay, or you can choose joint scheduling. It has a window emulation suite for a subset of the Win API. We used Visual Studio / VC ++ as an IDE. Now there can be a lot of different RTOS. That was almost 10 years ago. Google for RTOS and the "real-time operating system."

An alternative that can be good enough on a fast, dedicated computer is to write your own "OS in OS" to schedule threads "manually." You will have to change the way you wait for streams for appointments.

I shoot in the dark. Why do you need to balance the load between threads? What is the task? What is the budget? Do I need to work on certain equipment? On a specific OS? If so? What happens if this happens? Does someone mutter a bad word and go for lunch, or does the nose of the space probe dive into the sun?

+3
source share

The OS does not know that you want to distribute the JOB between several threads, so the OS starts the first available thread with the highest priority, it continues to run this thread until the current thread waits for something (user input, disk or network activity, or ...) or another thread with a higher priority becomes available. - To improve performance and avoid excessive context switching, the OS tries to send a request to the same thread (unlike your needs).

For example, consider a MonitorThread scheduled to run, and its sigwait call sigwait executed, now it performs its action (while this thread of its own processor, the OS does not have the ability to schedule other threads), when its action is completed (while terminating), it calls sigwait if there is any waiting signal, the OS will pick up this signal and cycle through again, this thread will perform this process until there is no more waiting signal, and sigwait block its operation, and the next time the operation will be repeated with another scheduled thread.

Now, to send signals the same way, I have to implement my own mechanism (since the OS does not have a mechanism for this). I can create a condition_variable for each thread and make each of them wait for its own condition_variable first and then call sigwait , and after completion of execution it will set the condition_variable next thread, and the operation will go as it is !.

+1
source share

All Articles