Tag Archives: pthread

RT Periodic Thread Code and Scheduler Policy and Priority

in this post, I am going to share an example code creating two threads running with a periodic cycle in an RT Preempt Linux.

You can download the code in this link.

https://github.com/queristq/rt_periodic_thread/archive/master.zip or you can git clone by git clone https://github.com/queristq/rt_periodic_thread.git

To build the code,

  • mkdir build
  • cd build
  • cmake ..
  • make

RT Performance between SCHED_RT and SCHED_IDLE

In the code, I have created two threads, and tested the RT performance for two different thread schedule policy between SCHED_RT and SCHED_IDLE. The figure below shows the result. The blue line shows the log10-scaled histogram of the loop time, and the orange line shows the log10-scaled histogram of the loop time. As shown in the plot, SCHED_RT made low jitters in the periodic loops. The test environment was not strictly controlled (I did internet browsing… while the loop was running).

1

RT Performance over Different Thread Priorities

I have conducted similar tests with different thread priority. I have selected the same thread policy SCHED_FIFO, and the priority of two threads were chosen to 1 and 99 respectively. The jitters of the each loop is shown in the figure below. As shown in the figure, interestingly the difference was very minor. Once you see the details, you can see the result of Priority 1 is slightly better.

2

If you want a full result, you can see the test result in the attached excel sheet.

Example code

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

#define TIMESPEC_ADD(A,B) /* A += B */ \
    do {                                   \
    (A).tv_sec += (B).tv_sec;          \
    (A).tv_nsec += (B).tv_nsec;        \
    if ( (A).tv_nsec >= 1000000000 ) { \
    (A).tv_sec++;                  \
    (A).tv_nsec -= 1000000000;     \
    }                                  \
    } while (0)

#define TIMESPEC_SUB(A,B) /* A -= B */ \
    do {                                   \
    (A).tv_sec -= (B).tv_sec;          \
    (A).tv_nsec -= (B).tv_nsec;        \
    if ( (A).tv_nsec < 0 ) {           \
    (A).tv_sec--;                  \
    (A).tv_nsec += 1000000000;     \
    }                                  \
    } while (0)


void *thread_func ( void *param )
{
    FILE *fp;
    char filename_fp[50];

    long thread_id = (long) param;

    sprintf (filename_fp, "%ld%s", thread_id, ".txt");
    fp = fopen(filename_fp, "w");//opening file

    struct timespec t_next, period, t_now, t_prev, t_diff;

    /* period = 1 ms * thread_id */
    period.tv_sec = 0;
    period.tv_nsec = ( 1 ) * 500000; // a x ms

    clock_gettime ( CLOCK_MONOTONIC, &t_now );
    t_next = t_now;
    t_prev = t_now;

    int t_jitter[100];
    for (int i=0;i<100;i++) t_jitter[i] = 0;
    int t_j = 0;

    for ( int i = 0; i < 100000; i++ )
    {
        clock_gettime ( CLOCK_MONOTONIC, &t_now );
        t_diff = t_now;
        TIMESPEC_SUB ( t_diff, t_prev );
        t_prev = t_now;
        t_j = t_diff.tv_nsec / 10000;
        if (t_j<0) t_jitter[0]++;
        else if (t_j>99) t_jitter[99]++;
        else t_jitter[t_j]++;
        if(i%10000==1) printf("%d\n",i);
        TIMESPEC_ADD ( t_next, period );
        clock_nanosleep ( CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL );
    }

    for (int i=0;i<100;i++) {
        printf("%d ",t_jitter[i]);
        fprintf(fp, "%d\n",t_jitter[i]);
    }
    fclose(fp);
    return NULL;
}

int main ()
{
    int policy;
    struct sched_param prio;
    pthread_attr_t attr;

    pthread_t tid1;
    pthread_t tid2;

    policy = SCHED_OTHER;
    if (pthread_setschedparam( pthread_self(),policy, &prio )){
        perror ("Error: pthread_setschedparam (root permission?)");
        exit(1);
    }

    pthread_attr_init( &attr);
    pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED);
    policy = SCHED_FIFO;
    pthread_attr_setschedpolicy( &attr, policy);
    prio.sched_priority = 99; // priority range should be btw -20 to +19
    pthread_attr_setschedparam(&attr,&prio);

    if ( pthread_create(&tid1, &attr, thread_func, (void *)(1)) ){
        perror ( "Error: pthread1_create" );
        return 1;
    }

    pthread_attr_init( &attr);
    pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED);
    policy = SCHED_FIFO;
    pthread_attr_setschedpolicy( &attr, policy);
    prio.sched_priority = 1; // priority range should be btw -20 to +19
    pthread_attr_setschedparam(&attr,&prio);

    if ( pthread_create(&tid2, &attr, thread_func, (void *)(2)) ){
        perror ( "Error: pthread2_create" );
        return 1;
    }

    /* wait for threads to finish */
    pthread_join ( tid1, NULL );
    pthread_join ( tid2, NULL );

    return 0;
}

If you are interested in how to make an RT Linux, please see another post of mine.

I found a very good material to study deeper on RT thread.

  • https://csperkins.org/teaching/2004-2005/rtes5/lecture10.pdf
  • http://retis.sssup.it/~lipari/courses/str09/10.rtprogramming-handout.pdf

If you have any questions on this code or this post, please leave a reply. Then, good luck!

[1] Nanosleep, http://man7.org/linux/man-pages/man2/nanosleep.2.html

[2] Timespec basic operation, http://www.zemris.fer.hr/~leonardo/srsv/skripta/src/periodic-tasks-2.c

pthread class implemented in C++ inheritance

I am sharing a set of code generating a thread with pthread by taking an advantage of C++ class inheritance.

You can download the code in this link.

Now, the creation of thread in c++ is easier than before with the standard “thread” class. But still “pthread” is more generic and available in various environments. For my case, I need to control the priority of a thread for real-time applications. In this case, pthread is a good selection.

The creation of pthread in a class environment is very common but it needs some careful implementation because it needs a static function. Hence, the inheritance of C++ can simplify the implementation. We can use a base class including the fundamental functions of pthread, and an application class which needs thread can be created by inheriting the base class.

Simply, You can create your application class using thread like below:

#include <iostream>
#include <unistd.h> // for sleep function

#include "basethreadclass.h"

class MyAppThread: public BaseThreadClass{
    void InternalThreadEntry(){
        int i=0;
        while(1){
            std::cout << i++ << " hello from pthread\n";
            usleep(10000);
        }
    };
};

int main(){
    MyAppThread a;
    a.StartInternalThread();
    int i=0;
    while(1){
        std::cout << i++ << " hello from main\n";
        usleep(10000);
    }
    return 0;
}

The base class, “BaseThreadClass” looks like below:

#ifndef BASETHREADCLASS_H
#define BASETHREADCLASS_H

class BaseThreadClass
{
public:
    BaseThreadClass() {/* empty */}
    virtual ~BaseThreadClass() {/* empty */}

    /** Returns true if the thread was successfully started, false if there was an error starting the thread */
    bool StartInternalThread()
    {
        return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
    }

    /** Will not return until the internal thread has exited. */
    void WaitForInternalThreadToExit()
    {
        (void) pthread_join(_thread, NULL);
    }

protected:
    /** Implement this method in your subclass with the code you want your thread to run. */
    virtual void InternalThreadEntry() = 0;

private:
    static void * InternalThreadEntryFunc(void * This) {((BaseThreadClass *)This)->InternalThreadEntry(); return NULL;}
    pthread_t _thread;
};


#endif // BASETHREADCLASS_H

You can compile them with the included cmake file, and execute the application like below:

crop_thead

I hope this post help your project and understanding. Good luck!

Again you can download the codes link.

 

Reference

[1] https://stackoverflow.com/questions/1151582/pthread-function-from-a-class