Good day everyone !
I am trying to get a 2nd thread (the serial thread) to run as near real time as possible.
Within my 2nd spawned serial thread I select() with timeout of 3 mS on a serial port.
I also get real time before select() … and then after to get select() delta time.
Problem is that sometimes I get no indication of select returning 0 (what I call a timeout due to the 3 mS elapsing) … but I do occasionally get a total time much greater than the 3 mS (4.447 for example).
I have to conclude that the serial thread is getting preempted?
Any ideas?
What Linux commands can I use to see if the thread is preempted?
Thanks!
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <pthread.h> #include <signal.h> #include <termios.h> #include <fcntl.h> #include <sys/time.h> #include <sys/types.h> #include <sys/resource.h> //----------------------------------- // signal Handler stuff. //----------------------------------- static struct sigaction mySigActTerm; volatile int myTerminate = 0; void terminateHandler(int signum, siginfo_t *info, void *ptr) { // set a flag here and get out. myTerminate = 1; } void getNowTime(char* str) { time_t rawtime; time(&rawtime); ctime_r(&rawtime, str); // clobber the unwanted newline. str[24] = ''; } void myResLimit() { struct rlimit procLimit; char strNowTime[26]; getrlimit(RLIMIT_RTTIME, &procLimit); getNowTime(strNowTime); fprintf(stderr, "%s - RLIMIT_RTTIME: soft=%lld, hard=%lldn", strNowTime, (long long) procLimit.rlim_cur, (long long)procLimit.rlim_max); getrlimit(RLIMIT_RTPRIO, &procLimit); getNowTime(strNowTime); fprintf(stderr, "%s - RLIMIT_RTPRIO: soft=%lld, hard=%lldn", strNowTime, (long long) procLimit.rlim_cur, (long long) procLimit.rlim_max); getrlimit(RLIMIT_CPU, &procLimit); getNowTime(strNowTime); fprintf(stderr, "%s - RLIMIT_CPU: soft=%lld, hard=%lldn", strNowTime, (long long) procLimit.rlim_cur, (long long) procLimit.rlim_max); } void* serialThread(void* arg) { int sfd; // serial file descriptor. char myChar; int rtn; fd_set myfds; struct timeval tm_out, start, end, delta; struct termios oldtio, newtio; sfd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); tcgetattr(sfd, &oldtio); newtio = oldtio; cfmakeraw(&newtio); newtio.c_cflag |= CREAD; newtio.c_cflag |= CLOCAL; newtio.c_cflag &= ~CSTOPB; newtio.c_cflag &= ~CRTSCTS; newtio.c_cflag &= ~CSIZE; newtio.c_cflag |= CS7; newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; newtio.c_cc[VTIME] = 1; newtio.c_cc[VMIN] = 1; tcflush(sfd, TCIFLUSH); while (1) { FD_ZERO(&myfds); FD_SET(sfd, &myfds); tm_out.tv_sec = 0; tm_out.tv_usec = 3000; // get sys call start time. gettimeofday(&start, NULL); rtn = select(sfd+1 ,&myfds, NULL, NULL, &tm_out); // get sys call end time. gettimeofday(&end, NULL); timersub(&end, &start, &delta); if (rtn == 0) { fprintf(stderr, "tm_out = %02d.%06d delta = %02d.%06dn", tm_out.tv_sec, tm_out.tv_usec, delta.tv_sec, delta.tv_usec); } else read(sfd, &myChar, 1); } } //----------------------------------- // the one and only MAIN. //----------------------------------- int main() { //----------------------------------------------- // locals. int rtn; char strNowTime[26]; pthread_t serialThdID; pthread_attr_t serialAttr; struct sched_param serialParam; //----------------------------------------------- // Log OS resource limits. myResLimit(); //----------------------------------------------- // initialize the signals struct. // ... and setup signals. memset(&mySigActTerm, 0, sizeof(mySigActTerm)); mySigActTerm.sa_sigaction = terminateHandler; mySigActTerm.sa_flags = SA_SIGINFO; sigaction(SIGTERM, &mySigActTerm, NULL); //----------------------------------------------- // set initial default pthread attr values. if ((rtn = pthread_attr_init(&serialAttr)) != 0) { getNowTime(strNowTime); fprintf(stderr, "%s - main() - pthread_attr_init()n%sn", strNowTime, strerror(rtn)); exit(EXIT_FAILURE); } //----------------------------------------------- // set for best near real time policy. if ((rtn = pthread_attr_setschedpolicy(&serialAttr, SCHED_FIFO)) !=0) { getNowTime(strNowTime); fprintf(stderr, "%s - main() - pthread_attr_setschedpolicy()n%sn", strNowTime, strerror(rtn)); exit(EXIT_FAILURE); } //----------------------------------------------- // set to explicit inherit or attr obj will be ignored. if ((rtn = pthread_attr_setinheritsched(&serialAttr, PTHREAD_EXPLICIT_SCHED)) !=0) { getNowTime(strNowTime); fprintf(stderr, "%s - main() - pthread_attr_setinheritsched()n%sn", strNowTime, strerror(rtn)); exit(EXIT_FAILURE); } //----------------------------------------------- // set to un-limited thread priority. serialParam.sched_priority = 0; if ((rtn = pthread_attr_setschedparam(&serialAttr, &serialParam)) !=0) { getNowTime(strNowTime); fprintf(stderr, "%s - main() - pthread_attr_setschedparam()n%sn", strNowTime, strerror(rtn)); exit(EXIT_FAILURE); } //----------------------------------------------- // start the new thread. if ((rtn = pthread_create(&serialThdID, &serialAttr, serialThread, NULL)) == 0) { getNowTime(strNowTime); fprintf(stderr, "%s - starting serial thread.n", strNowTime); } else { getNowTime(strNowTime); fprintf(stderr, "%s - main() - pthread_create() returned %dn%sn", strNowTime, rtn, strerror(rtn)); exit(EXIT_FAILURE); } //----------------------------------------------- // no need to keep this junk if pthread_create() succeeded. if ((rtn = pthread_attr_destroy(&serialAttr)) != 0) { getNowTime(strNowTime); fprintf(stderr, "%s - main() - pthread_attr_destroy()n%sn", strNowTime, strerror(rtn)); } while (myTerminate == 0) { } }
Advertisement
Answer
Well no one seems to know why this is happening to me but … … after nearly a year struggling … … I found a post that is exactly what is happening to me.
I post a link so no one else will suffer my fate.