Skip to content

Instantly share code, notes, and snippets.

@sutyum
Created December 13, 2021 07:56
Show Gist options
  • Save sutyum/430ab9f7ff3cb6f4bf85344e0910c739 to your computer and use it in GitHub Desktop.
Save sutyum/430ab9f7ff3cb6f4bf85344e0910c739 to your computer and use it in GitHub Desktop.
Use FIFO scheduling policy and Core affinity in linux
#define _GNU_SOURCE
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <syslog.h>
#define NUM_OF_THREADS 128
#define SCHED_POLICY SCHED_FIFO
typedef struct
{
int threadIdx;
} threadParams_t;
struct sched_param fifo_param;
pthread_attr_t fifo_sched_attr;
// POSIX thread declarations and scheduling attributes
//
pthread_t threads[NUM_OF_THREADS];
threadParams_t threadParams[NUM_OF_THREADS];
void print_scheduler(void)
{
int schedType = sched_getscheduler(getpid());
switch(schedType)
{
case SCHED_FIFO:
printf("SCHED_FIFO\n");
break;
case SCHED_OTHER:
printf("SCHED_OTHER\n");
break;
case SCHED_RR:
printf("SCHED_RR\n");
break;
default:
printf("UNKNOWN\n");
}
}
void set_scheduler(int procno, int prio)
{
int scope, rc, cpuidx;
cpu_set_t cpuset;
printf("INITIAL "); print_scheduler();
//SCHED_POLICY is set to SCHED_FIFO
pthread_attr_init(&fifo_sched_attr);
pthread_attr_setinheritsched(&fifo_sched_attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&fifo_sched_attr, SCHED_POLICY);
//zero out the set o CPU cores
CPU_ZERO(&cpuset);
//Here we assign the threads to run ONLY on single core
cpuidx=procno;
CPU_SET(cpuidx, &cpuset);
pthread_attr_setaffinity_np(&fifo_sched_attr, sizeof(cpu_set_t), &cpuset);
//Set priority according to function parameter
fifo_param.sched_priority=prio;
if ((rc=sched_setscheduler(getpid(), SCHED_POLICY, &fifo_param)) < 0)
perror("sched_setscheduler");
pthread_attr_setschedparam(&fifo_sched_attr, &fifo_param);
printf("ADJUSTED "); print_scheduler();
}
void *Thread(void *threadp)
{
threadParams_t *threadParams = (threadParams_t *)threadp;
int gsum = 0; //Local variable (for every task)
char str[100]; //Memory allocation for string
for(int i=0; i<=threadParams->threadIdx; i++) //Calculate sum from 0 to the n, where n is the task number
gsum=gsum+i;
sprintf(str, "Thread idx=%d, sum[1..%d]=%d Running on core:%d\n", threadParams->threadIdx, threadParams->threadIdx, gsum, sched_getcpu()); //Fill the string with calculated data
syslog(LOG_INFO, str); //Log the data
}
int main (int argc, char *argv[])
{
volatile int i=0;
openlog("[COURSE:1][ASSIGNMENT:3]:", LOG_NOWAIT, LOG_SYSLOG); //Open logger file
system("uname -a | logger -t '[COURSE:1][ASSIGNMENT:3]:'"); //Use system function for OS details and stream it to logger
for(i=0; i < NUM_OF_THREADS; i++)
{
set_scheduler(1, 99-i); //Set scheduler to FIFO runing on core 1 with priority from 99 to 0
threadParams[i].threadIdx=i; //Set thread identification number
pthread_create(&threads[i], //Pointer to thread descriptor
&fifo_sched_attr, //Use default attributes
Thread, //Thread function entry point
(void *)&(threadParams[i]) //Parameters to pass in
);
}
for(i=0; i < NUM_OF_THREADS; i++)
pthread_join(threads[i], NULL);
printf("TEST COMPLETE\n");
}
/* --=== COMMENTS ON THE OUTPUT DATA ===--
*
* Below please find few lines from the syslog file
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173145]: Linux diodetetor 5.15.5-arch1-1 #1 SMP PREEMPT Thu, 25 Nov 2021 22:09:33 +0000 x86_64 GNU/Linux
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=0, sum[1..0]=0 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=1, sum[1..1]=1 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=2, sum[1..2]=3 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=3, sum[1..3]=6 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=4, sum[1..4]=10 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=5, sum[1..5]=15 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=6, sum[1..6]=21 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=7, sum[1..7]=28 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=8, sum[1..8]=36 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=9, sum[1..9]=45 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=10, sum[1..10]=55 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=11, sum[1..11]=66 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=12, sum[1..12]=78 Running on core:1
* gru 11 12:35:21 diodetetor [COURSE:1][ASSIGNMENT:3]:[173142]: Thread idx=13, sum[1..13]=91 Running on core:1
*
* As we can see, the tasks are in the same order as the creation sequence. This is because
* of assymetric fifo schedduler SCHED_FIFO and proper priority settings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment