Running pthread multiple times - c++

I want a thread to run infinity times in order to execute the task described on do_work() function that it receives. However, the function is only called on the pthread_create() subroutine.
I've tried to implement the sched_yield() and the pthread_join() routines on a while loop. But it didn't work yet.
Is there any routine in which I can call the existing thread again?
int main (int argc, char ** argv) {
int period;
int priority;
int load;
char schedule[15];
period = atoi(argv[1]);
priority = atoi(argv[2]);
load = atoi(argv[3]);
strncpy(schedule,argv[4],100);
std::cout << " period : " << period <<"\n priority : "<< priority << "\n load : "<< load << "\n schedule : " << schedule <<std::endl;
struct sched_param param;
pthread_t thread;
int rc;
sched_setscheduler (0, SCHED_FIFO , &param);
std::cout << "main() : creating thread " << std::endl;
rc = pthread_create(&thread, NULL, do_work, (void*)load);
if (rc) {
std::cout << "Error:unable to create thread " << rc << std::endl;
exit(-1);
}
int i=0;
struct sigaction action;
struct itimerval timer;
while(i<10000){
pthread_join(thread, NULL);
sched_yield();
i++;
}
pthread_exit(NULL);
}

You do not call a thread, you create a thread. By doing that, you specify a start_routine which will be called 'in' the new thread.
If you want to call repeatedly a function in a loop, then you can do the following in your start_routine:
void* start_routine(void *arg) {
while (active) { // active: atomic global boolean value
do_work();
}
// if no longer active,
// there could be an option to wait to become active again,
// or exit the thread
pthread_exit(NULL);
}
pthread_join() is only called, if you want to join a thread with other thread(s). pthread_join() waits until the target thread has terminated. By joining the thread, all resources are given back to the system (cleanup).

Just wanted to show you the code I implemented.
I was not sure about the meaning of Threads when I made this question and you helped me to understand that I cannot access the function on a thread multiple times, but I have to create it on each use.
My main objective was to find a way of calling the do_work() function on the reception of the signal SIGALRM. Thus, I just assumed the do_wordk() to be my Thread and used a sigaction struct to control the arrival of the signal.
If you guys want to test the code, it returns the execution time of the do_work() function and a message if the deadline set on your period was lost. The purpose of this work was to make an analogy with periodic threads.
To compile:
g++ teste.cpp -o exe -lrt
To run:
sudo taskset -c 0 ./exe 300 1 100000 F
sudo taskset -c 0 ./exe Period Priority Work_Load Scheduller_Policy
#include<signal.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<sys/time.h>
#include<iostream>
#include<string>
#include<string.h>
long load=1;
void deadline();
void do_work();
void wakeup(int j){
struct itimerval aux;
int t1, t2;
getitimer( ITIMER_REAL, &aux); //Get initial resume time
t1 = aux.it_value.tv_usec;
//std::cout << "Hello World! Thread working |Resume Time : " <<t1<< std::endl;
do_work();
getitimer( ITIMER_REAL, &aux);
t2 = aux.it_value.tv_usec; //Get Final resume time
std::cout << "Execution time (usec): " <<t1 - t2<< std::endl;
if (t2==0){
deadline();
}
return;
}
void do_work(){
for ( int i = 0; i < load * 1000; i++) {
/* do nothing , keep counting */
}
}
void deadline() {
std::cout << "Lost deadline!" << std::endl;
}
int main (int argc, char ** argv) {
int i;
int period;
int priority;
char scheduler[5];
period = atoi(argv[1])*1000;
priority = atoi(argv[2]);
load = atoi(argv[3]);
strcpy(scheduler, argv[4]);
std::cout << " period : " << period <<"\n priority : "<< priority << "\n load : "<< load << "\n scheduler : " << scheduler <<std::endl;
struct sched_param param;
param.sched_priority = priority;
if (scheduler[0]=='F'){
int r = sched_setscheduler (0, SCHED_FIFO , &param);
if(r==-1){ perror("scheduller"); return 1;}
std::cout <<"FIFO scheduller: "<<r<<std::endl;
}else{
int r = sched_setscheduler (0, SCHED_RR , &param);
if(r==-1){ perror("scheduller"); return 1;}
std::cout <<"RR scheduller: "<<r<<std::endl;
}
struct itimerval val;
struct sigaction action;
sigset_t mask;
sigemptyset(&action.sa_mask);
action.sa_handler = wakeup;
action.sa_flags=SA_RESTART;
if(sigaction(SIGALRM, &action, 0)==-1){
perror("sigaction");
return 1;
}
val.it_interval.tv_sec=0;
val.it_interval.tv_usec=period;
val.it_value.tv_sec=0;
val.it_value.tv_usec=period;
if(setitimer(ITIMER_REAL, &val, 0)==-1){
perror("setitimer");
return 1;
}
if(sigwait( &mask, &i)==-1){
perror("sigwait");
}
return 0;
}
Finally, I am really grateful for your patience in understanding my problem. This is my first question on this community and I hope I'll improve them over time. Thank you all for your answers and the effort on helping me.

Related

pthread_cond_wait() only wakes when value set to 0

I am somewhat new to threads but have been reading up on pthreads and trying to write a test program that will eventually be used in an application. The basic operation for this test app is to:
spawn two threads,
allow a user to enter a number (sender thread) that is stored in a value of a conditioned variable and then use a signal to wake up a second thread (receiver thread).
I am showing the code and the output screen to show the results of the test output.
Basically, when I enter a number other than 0 the signal does not wake up the second thread. When a 0 is entered the second thread wakes up and performs as expected (i.e. exits).
The question is why does the second thread not wake up for other numbers (i.e. 1 or 2). I have tried this with both a pthread_cond_timedwait() and pthread_cond_wait() but I get the same results in either case.
I would appreciate any and all suggestions. Thanks.
//============================ terminal screen =================================
enter a message to send:
0 - exit
1 - message 1
2 - message 2
1
messageSender: msg.value: 1
messageSender: signal sent!
2
messageSender: msg.value: 2
messageSender: signal sent!
0
messageSender: msg.value: 0
messageSender: signal sent!
exit pthread_cond_timedwait, testVal: 1 value: 0
0
messageReceiverThread msg.value received: 0
exiting
//================= apps/pthread_com_example.h =================================
#ifndef PTHREAD_COM_EXAMPLE_H_INCLUDED
#define PTHREAD_COM_EXAMPLE_H_INCLUDED
// | added for thread com example RLB 04Dec2021
// V
#if(defined PTHREAD_COM_EXAMPLE)
#include <stdio.h> // standard I/O routines
#include <stdlib.h> // rand() and srand() functions
// number of threads used to service requests
#define NUM_HANDLER_THREADS 2
/* format of a message structure */
typedef struct {
pthread_mutex_t mutex; // message mutex
pthread_cond_t cond; // message condition variable
int testVal; // use this as the predicate
int value; // value to be passed
}message_t;
// ^
// | added for thread com example RLB 04Dec2021
#endif
#endif // PTHREAD_COM_EXAMPLE_H_INCLUDED
//=================== pthread_com_example app ==============================
#include <iostream>
#include <pthread.h>
#define PTHREAD_COM_EXAMPLE
#include <apps/pthread_com_example.h>
#include <unistd.h>
#include <sys/time.h> // struct timeval definition
#if(defined PTHREAD_COM_EXAMPLE)
/* global mutex for example. assignment initializes it.
note: a RECURSIVE mutex is used, since a handler
thread might try to lock it twice consecutively. */
#define MSG1 1 // trigger messasge 1
#define MSG2 2 // trigger message 2
#define MSGX 0 // message to exit
std::string message1 = "this is an example message in response to A";
std::string message2 = "this is an example message in response to B";
struct timeval now;
struct timespec timeout;
message_t msg = {
// initialize the message structure.
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, PTHREAD_COND_INITIALIZER, 0, 0
};
#endif
#if(defined PTHREAD_COM_EXAMPLE)
#define DEBUG
// wait for sending thread to signal variable is ready to read
int timedWaitForCond(pthread_cond_t* pCond, pthread_mutex_t* pMutex, int timeToWait)
{
gettimeofday(&now,NULL);
timeout.tv_sec = now.tv_sec + timeToWait;
timeout.tv_nsec = now.tv_usec * 1000;
int retcode = 0;
while((msg.testVal == 0) && (retcode != ETIMEDOUT))
{
// this unlocks the mutux while waiting on signal from another thread
// retcode = pthread_cond_timedwait(pCond, pMutex, &timeout);
retcode = pthread_cond_wait(pCond,pMutex);
// upon return the mutex is locked again
std::cout << "exit pthread_cond_timedwait, testVal: " << msg.testVal << " value: " << msg.value << std::endl;
if(retcode != 0)
{
switch(retcode)
{
case ETIMEDOUT: // exits while loop
std::cout << "Timed Conditional Wait, Timed Out" << std::endl;
return(-1); // conditioned variable is not ready yet
break;
default: // stays in while loop
std::cout << "Unexpected timed conditional wait result: " << retcode << std::endl;
break;
}
}else
{
return(0); // conditioned variable ready to read
break; // exit while if legitimate signal occurred
}
}
return(0);
}
void outputMenu(void)
{
std::cout << std::endl << std::endl;
std::cout << "enter a message to send: " << std::endl;
std::cout << " 0 - exit" << std::endl;
std::cout << " 1 - message 1" << std::endl;
std::cout << " 2 - message 2" << std::endl;
}
int getUserMessage(void)
{
int rc;
std::cin >> rc;
return(rc);
}
/*
* function messageReceiverThread():
* attempts to wait for message wait. If result is good
* sends signal to waiting thread and then performs a
* timed conditioned wait to receive the message from the
* sending thread.
*
* algorithm:
* input: messageWait mutex
* output: character from message_t structure
* memory: shared message_t structure
*/
void* messageReceiverThread(void* arg)
{
int timeToWait = 10; // use 10 second timeout for this example
int rc = 0;
// first, lock the mutex, to assure exclusive access to the conditioned variable
rc = pthread_mutex_lock(&msg.mutex);
if (rc)
{ // an error has occurred
std::cout << "messageReceiver: pthread_mutex_lock error: " << rc << std::endl;
pthread_exit(NULL);
}
// mutex is now locked
outputMenu();
while(1)
{
msg.testVal = 0; // clear signal value
rc = timedWaitForCond( &msg.cond , &msg.mutex, timeToWait); // cond variable is unlocked while waiting
// var is locked again after exit from timedWaitForCond()
if(0 != rc)
{
// Timeout or error, no messasge yet, for this app just loop around...
std::cout << "no message yet, rc = " << rc << std::endl;
}else
{
// return from timed wait with valid signal from sender
std::cout << msg.value << std::endl;
std::cout << "messageReceiverThread msg.value received: " << msg.value << std::endl;
switch(msg.value)
{
case MSG1:
std::cout << message1 << std::endl;
break;
case MSG2:
std::cout << message2 << std::endl;
break;
case MSGX:
std::cout << "exiting" << std::endl;
pthread_exit(arg);
break;
default:
std::cout << "unrecognized message" << std::endl;
break;
}
outputMenu();
}
}
pthread_exit(arg);
}
/*
* function messageSenderThread():
* attempts to wait for user to enter a number at the console.
* When the number is received this thread will attempt a lock
* on the message mutex and, once obtained, write the value
* to the msg.msgNbr. Then this thread will send a signal to
* the messageReceiver thread. Once completed this thread will
* again wait on the user for an additional imput, until the
* value enterd by the user is 0, which will cause an exit.
*
* algorithm:
* input: messageWait mutex
* output: character from message_t structure
* memory: shared message_t structure
*/
void* messageSenderThread(void* arg)
{
int rc = 0,msgCode = 0;
while(1)
{
rc = pthread_mutex_lock(&msg.mutex);
if(rc)
{
std::cout << "messageSender: lock request failed,result: " << rc << std::endl;
pthread_exit(arg);
}
msgCode = getUserMessage();
msg.value = msgCode;
msg.testVal = 1;
std::cout << "messageSender: msg.value: " << msg.value << std::endl;
// signal the condition variable - there's a new message to handle
rc = pthread_cond_signal(&msg.cond);
std::cout << "messageSender: signal sent! " << std::endl;
if(rc)
std::cout << "messageSender: pthread_cond_signal failed,result: " << rc << std::endl;
// unlock mutex
rc = pthread_mutex_unlock(&msg.mutex);
if(rc)
{
std::cout << "messageSender: unlock request failed,result: " << rc << std::endl;
pthread_exit(arg);
}
if(!msgCode) // user entered the exit code
pthread_exit(arg);
}
pthread_exit(arg);
}
#undef DEBUG
#endif
int main(int argc, char *argv[])
{
#if(defined PTHREAD_COM_EXAMPLE)
int thr_id[NUM_HANDLER_THREADS]; // thread IDs
pthread_t thread1,thread2; // thread's structures
// create the message handling threads
thr_id[0] = 0;
(void) pthread_create(&thread1, NULL, messageReceiverThread, (void*)&thr_id[0]);
thr_id[1] = 1;
(void) pthread_create(&thread2, NULL, messageSenderThread, (void*)&thr_id[1]);
// now wait for threads to exit...
(void) pthread_join(thread1, NULL);
(void) pthread_join(thread2, NULL);
return 0;
#endif
}
The problem here is starvation. Your messageSenderThread() function keeps the mutex locked practically all the time. Each time it releases the mutex at the bottom of the loop, the very next thing it does is (if you don't type "0") it re-locks the mutex back at the top of the loop. The messageReceiverThread() always loses the race to lock the mutex.
The reason why the message receiver does print something after you enter the "quit" command (0), is because the messageSenderThread() unlocks the mutex and it exits after you enter a zero. That finally allows the receiver to lock the mutex and do its thing.

Creating 3 children processes and exiting them after a specified number of seconds

image for what output is supposed to look like:My problem is that I need to write a program that will accept the names of 3 processes as command-line arguments. Each of these processes will run for as many seconds as:(PID%10)*3+5 and terminate. After those 3 children terminated, the parent process
will reschedule each child. When all children have been rescheduled 3 times, the parent will terminate. I have used fork to create the three children but am struggling with getting them to exit with that specific criteria?
using namespace std;
int main(){
int i;
int pid;
for(i=0;i<3;i++) // loop will run n times (n=3)
{
if(fork() == 0)
{
pid = getpid();
cout << "Process p" << i+1 << " pid:" << pid << " Started..." << endl;
exit(0);
}
}
for(int i=0;i<5;i++) // loop will run n times (n=3)
wait(NULL);
}
You can use sigtimedwait to wait for SIGCHLD or timeout.
Working example:
#include <cstdio>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>
template<class... Args>
void start_child(unsigned max_runtime_sec, Args... args) {
// Block SIGCHLD.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, nullptr);
// Enable SIGCHLD.
signal(SIGCHLD, [](int){});
pid_t child_pid = fork();
switch(child_pid) {
case -1:
std::abort();
case 0: {
// Child process.
execl(args..., nullptr);
abort(); // never get here.
}
default: {
// paren process.
timespec timeout = {};
timeout.tv_sec = max_runtime_sec;
siginfo_t info = {};
int rc = sigtimedwait(&set, nullptr, &timeout);
if(SIGCHLD == rc) {
std::printf("child %u terminated in time with return code %d.\n", static_cast<unsigned>(child_pid), info.si_status);
}
else {
kill(child_pid, SIGTERM);
sigwaitinfo(&set, &info);
std::printf("child %u terminated on timeout with return code %d.\n", static_cast<unsigned>(child_pid), info.si_status);
}
}
}
}
int main() {
start_child(2, "/bin/sleep", "/bin/sleep", "10");
start_child(2, "/bin/sleep", "/bin/sleep", "1");
}
Output:
child 31548 terminated on timeout with return code 15.
child 31549 terminated in time with return code 0.
With these changes your program produces the desired output:
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
int main()
{
for (int round = 0; ++round <= 4; )
{
int i;
cout << "*** ROUND: " << round << " ***\n";
for (i=0; i<3; i++) // loop will run n times (n=3)
{
if (fork() == 0)
{
int pid = getpid();
cout << "Process p" << i+1 << " pid:" << pid << " started...\n";
unsigned int seconds = pid%10*3+5;
cout << "Process " << pid << " exiting after "
<< seconds-sleep(seconds) << " seconds\n";
exit(0);
}
}
while (i--) // loop will run n times (n=3)
{
int status;
cout << "Process " << wait(&status);
cout << " exited with status: " << status << endl;
}
}
}
As Serge suggested, we're using sleep() for every child before exiting it. it will pause the process for a number of seconds.
To get the actual status information, we call wait(&status) instead of wait(NULL).
We're doing this all for the first scheduling round plus the desired 3 times of rescheduling.

Implementing a Semaphore

I have the following code below. I want only half of the threads to enter the threadedfunction at a time. How do I create a Semaphore to block the other processes? And how would I go about unblocking the previously blocked processes whenever the threads have finished using the function?
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
using namespace std;
#define NUM_THREADS 4
long int sharedcount;
pthread_mutex_t count_mutex;
//Function that will be run by multiple threads
//Needs to return a void pointer and if it takes arguments
//it needs to be a void pointer
void *ThreadedFunction(void *threadid)
{
int success;
long id = (long)threadid;
//Lock mutex preventing the other threads from ru nning
success = pthread_mutex_lock( &count_mutex );
cout << "Thread " << id << " beginning.\n";
for(int i = 0; i < 100000000; i++)
sharedcount++;
cout << "Thread " << id << " exiting.\n";
cout << sharedcount << endl;
//Unlock the mutex after the thread has finished running
pthread_mutex_unlock( &count_mutex );
//Kill the thread
pthread_exit(NULL);
}
int main ()
{
//Initialize mutex
pthread_mutex_init(&count_mutex, NULL);
//Create an array of threads
pthread_t threads[NUM_THREADS];
int rc;
int i;
sharedcount = 0;
for( i=0; i < NUM_THREADS; i++ )
{
cout << "main() : creating thread, " << i << endl;
//Create thread by storing it in a location in the array. Call the
//function for the threads to run inside. And pass the argument (if any).
//If no arguments pass NULL
rc = pthread_create(&threads[i], NULL, ThreadedFunction, (void *)i);
if (rc)
{
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
//Have main thread wait for all other threads to stop running.
for(i = 0; i < NUM_THREADS; i++)
pthread_join(threads[i], NULL);
//cout << sharedcount << endl;
pthread_exit(NULL);
}
What you could do is use a counting semaphore (as opposed to a binary semaphore). A counting semaphore has an initial value greater than 1, allowing for multiple threads to call "wait" on the semaphore and not have those threads actually blocked and put in the semaphore queue.
What I would have done in your case is initialize a semaphore in the main function with an initial value of NUM_THREADS/2. Then I would insert a line at the beginning of threadedFunction where I do a wait(semaphore) and a line at the end of the function where you do a signal(semaphore). This way, when a thread is about to exit the function, it signals a thread that was blocked after having called wait on the semaphore and it lets this thread in.
Hope this helps.

Infinite loop multi-threading

I have written this Producer/Consumer Problem solution. It seems to be working, other than the infinite loop. I was under the impression that pthread_exit(NULL); would make it stop, but honestly, I've become lost and confused. Could someone point me in the right direction of how to stop the loop?
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<iostream>
#include<semaphore.h>
#define BUFFSIZE 10
using namespace std;
int buffer[BUFFSIZE];
int size; //current buffer size
int n = 0, m = 0;
pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t Available;
sem_t Buffer; //indicates if buffer is full
//----------------------------------------------------------------//
void *Consumers(void *argument)
{
int con_id = *((int *) argument);
while(1)
{
if(size == 0)
{
cout << "Queue is empty." << endl;
}
sem_wait(&Available);
pthread_mutex_lock(&Mutex);
size--;
cout << "Con " << con_id << ": Product removed from buffer" << endl;
//for(int i = 0; i < size; i++)
//{
// cout << Buffer[i] << " ";
//}
cout << endl;
pthread_mutex_unlock(&Mutex);
sem_post(&Buffer);
}
return(NULL);
}
//----------------------------------------------------------------//
void *Producers(void *argument)
{
int item = 8;
int pro_id = *((int *) argument);
while(1)
{
sem_wait(&Buffer);
pthread_mutex_lock(&Mutex);
//Buffer[size] = item;
cout << "Item added" << endl;
size++;
pthread_mutex_unlock(&Mutex);
sem_post(&Available);
}
return(NULL);
}
//----------------------------------------------------------------//
int main()
{
cout << "Enter number of producers: " << endl;
scanf("%d", &n);
cout << "Enter number of consumers: " << endl;
scanf("%d", &m);
//get number of producers(int n), and consumers(int m)
sem_init(&Available, 0, 0);
sem_init(&Buffer, 0, BUFFSIZE);
pthread_t *con = new pthread_t[m];
int *thread_args_c = new int[m];
for(int i = 0; i < n; i++)
{
thread_args_c[i] = i;
pthread_create(&con[i], NULL, Consumers, (void*) &i);
}
pthread_t *pro = new pthread_t[n];
int *thread_args_p = new int[n];
for(int i = 0; i < n; i++)
{
thread_args_p[i] = i;
pthread_create(&pro[i], NULL, Producers, (void*) &i);
pthread_join(con[i], NULL);
}
pthread_exit(NULL);
}
Not sure what you are expecting. pthread_exit appears in the end of the main (and completely not needed there, since main is exiting anyways), but your enless loops inside thread will never let main reach this point (since you are joining the consumers thread).
Also, your creation and joining model makes litle sense - what's the point of joining consumer thread after you've created a producer?
And last, but not the lease, you fail to join producer thread.
The loops will not stop because there is no logic in the code to actually exit the loop.
The process is stuck because pthread_join suspends the calling thread till the target exits. See documentation for pthread_join
If you don't care about actually terminating the threads and returning to the main thread, just remove the call to pthread_join. The process should terminate because the main thread exited.
To actually properly terminate the loops, you need to set an internal or external trigger. You could internally have the loops exit after a set number of iterations. For this, you will do while(x<=y) instead of while(1).
You could also make it more complicated and have the main thread signal the other threads externally that it wants the other threads to shut down. You can have the main thread set a (volatile) boolean when you are ready to exit and have the other threads break the loop based on it. If you care about the Atomicity of the exit, you will need to protect the boolean with a lock.

portable pthread_setschedparam with SCHED_OTHER

I'm putting together a Unix/Linux semi-portable thread class (i.e. using the pthread library) for a project I'm working on. Part of the project requires the ability to set the priority of certain threads to allow other threads in the same process more CPU time; which is where the pthread_setschedparam function comes in and my class hits a brick wall.
Below is a simple test I put together to illustrate my issue:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include <string.h>
#include <errno.h>
pthread_mutex_t m_mtx;
bool m_goahead;
void dosleep(int millis)
{
usleep(millis*1000);
}
void domsg(const char *msg)
{
pthread_mutex_lock(&m_mtx);
std::cout << msg << std::endl;
pthread_mutex_unlock(&m_mtx);
}
void dowait() {
while (!m_goahead) {
dosleep(1);
}
}
void *fn1(void *param)
{
domsg("in fn1...waiting");
dowait();
while (m_goahead) {
dosleep(1000);
domsg("in fn1 loop");
}
}
void *fn2(void *param)
{
domsg("in fn2...waiting");
dowait();
while (m_goahead) {
dosleep(1000);
domsg("in fn2 loop");
}
}
int main(int argc, char **argv)
{
// min prio = -2, max prio = 2
int t1_pri = 2, t2_pri = 0, main_pri = 1;
//SCHED_RR, SCHED_FIFO, SCHED_OTHER (POSIX scheduling policies)
int sched = SCHED_OTHER; // standard
// get the range between min and max and set the priorities base on split range
int min = sched_get_priority_min(sched);
int max = sched_get_priority_max(sched);
int skip = (max - min) / 5; // 5 since -2...2
struct sched_param main_param, t1_param, t2_param;
memset(&main_param, 0, sizeof(sched_param));
memset(&t1_param, 0, sizeof(sched_param));
memset(&t2_param, 0, sizeof(sched_param));
main_param.sched_priority = (min + ((main_pri+2) * (skip+1))) + (skip / 2);
t1_param.sched_priority = (min + ((t1_pri+2) * (skip+1))) + (skip / 2);
t2_param.sched_priority = (min + ((t2_pri+2) * (skip+1))) + (skip / 2);
std::cout << "main thread will have a prio of " << main_param.sched_priority << std::endl;
std::cout << "t1 thread will have a prio of " << t1_param.sched_priority << std::endl;
std::cout << "t2 thread will have a prio of " << t2_param.sched_priority << std::endl;
m_goahead = false;
pthread_mutex_init(&m_mtx, NULL);
pthread_t t1, t2;
// Create the threads
if (pthread_create(&t1, NULL, fn1, NULL) != 0) {
std::cout << "couldn't create t1" << std::endl;
return -1;
}
if (pthread_create(&t2, NULL, fn2, NULL) != 0) {
std::cout << "couldn't create t2" << std::endl;
return -1;
}
dosleep(1000); // sleep a second before setting priorities
// --main thread--
if (pthread_setschedparam(pthread_self(), sched, &main_param) != 0) {
std::cout << "error setting priority for main thread: (" << errno << "), " << strerror(errno) << std::endl;
}
// --t1 thread--
if (pthread_setschedparam(t1, sched, &t1_param) != 0) {
std::cout << "error setting priority for T1: (" << errno << "), " << strerror(errno) << std::endl;
}
// --t2 thread--
if (pthread_setschedparam(t2, sched, &t2_param) != 0) {
std::cout << "error setting priority for T2: (" << errno << "), " << strerror(errno) << std::endl;
}
m_goahead = true; // all start
// loop until user interupt
for (;;) {
dosleep(1000);
domsg("in main loop");
}
pthread_mutex_destroy(&m_mtx);
return 0;
}
Base on this code, if I compile this and run it on an OpenBSD system, I get the following:
main thread will have a prio of 24
t1 thread will have a prio of 31
t2 thread will have a prio of 17
in fn1...waiting
in fn2...waiting
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
Note how it goes in the order of the thread priority, fn1, main, fn2...
If I run this same test on an Ubuntu 10.04LTS system, I get the following:
main thread will have a prio of 3
t1 thread will have a prio of 4
t2 thread will have a prio of 2
in fn1...waiting
in fn2...waiting
error setting priority for main thread: (22), Invalid argument
error setting priority for T1: (22), Invalid argument
error setting priority for T2: (22), Invalid argument
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
I understand that the invalid argument is because I'm specifying the SCHED_OTHER priority class and trying to assign it any number other than 0; what I cannot figure is how can I make this work properly?
I've tried 'assuming' a SCHED_FIFO or SCHED_RR priority class to get the min/max values, which gives me valid min/max values and I don't get the 'invalid argument' error, but the function loop output is not in the prioritized order, it is instead in whatever order the function happened to get called (to be expected if no priority was set).
Ideally I would get the current process' priority class, then assign the thread on that class too, however, if the current process' priority is SCHED_OTHER then setting a thread based on that produces the invalid results I don't want.
Is there a more 'portable' way to set a thread's priority or grab the valid min/max values? Can I even set a thread's priority under SCHED_OTHER in certain environments, or is that functionality left to said environment?
I'm at an impasse with this problem and would appreciate any insight or pointers in the right direction.
Thanks and please let me know if my code/explanation is unclear.
Refer this if it helps increase understanding. But what little I learned, SCHED_OTHER is their only to mean that all the non real time thread will have equal priority. But then in the question referred BSD give max and min 0 and 99 even in case of SCHED_OTHER, didn't understand why, but one thing is clear, it is not a very portable and to rely on its exact value will not help. In that case putting special handling will do much better, like if range is [0-0] then using nice(if thread priority can be fixed by nice,please let me know) be used to set the priority.
Thanks