Applying C - Deadline Scheduling
Written by Harry Fairhead   
Monday, 12 August 2019
Article Index
Applying C - Deadline Scheduling
Example

An Example

To see how this works let’s implement a simple task that prints “sensor” every two seconds. The first problem is specifying the times to allocate. Currently these have to satisfy:

sched_runtime <= sched_deadline <= sched_period

and all times have to be greater than 1024 ns and smaller than 263 ns. Notice that this implies that the uncertainty in when the task runs is at least the execution times – which means a small execution time is best.

We have selected two seconds for sched_period and the runtime to print the message is likely to be less than 10 ms, so the deadline can be 11 ms. Thus the struct can be initialized as:

struct sched_attr attr = {
    .size = sizeof (attr),
    .sched_policy = SCHED_DEADLINE,
    .sched_runtime = 10 * 1000 * 1000,
    .sched_period = 2 * 1000 * 1000 * 1000,
    .sched_deadline = 11 * 1000 * 1000
};

The task will be repeated every two seconds and can be up to 11 ms late.

The thread function is simply:

sched_setattr(0, &attr, 0);
for (;;) {
    printf("sensor\n");
    fflush(0);
    sched_yield();
};

Notice that after we set the scheduling policy the thread simply loops printing the message. The key point is that in this case the yield causes the thread to be suspended until the start of its next time period.

Putting all of this together gives:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <linux/sched.h>
#include <pthread.h>
#include <stdint.h>
struct sched_attr {
    uint32_t size;
    uint32_t sched_policy;
    uint64_t sched_flags;
    int32_t sched_nice;
    uint32_t sched_priority;
    uint64_t sched_runtime;
    uint64_t sched_deadline;
    uint64_t sched_period;
};
int sched_setattr(pid_t pid, 
const struct sched_attr *attr, unsigned int flags) { return syscall(__NR_sched_setattr, pid, attr, flags); } void * threadA(void *p) { struct sched_attr attr = { .size = sizeof (attr), .sched_policy = SCHED_DEADLINE, .sched_runtime = 10 * 1000 * 1000, .sched_period = 2 * 1000 * 1000 * 1000, .sched_deadline = 11 * 1000 * 1000 }; sched_setattr(0, &attr, 0); for (;;) { printf("sensor\n"); fflush(0); sched_yield(); }; } int main(int argc, char** argv) { pthread_t pthreadA; pthread_create(&pthreadA, NULL, threadA, NULL); pthread_exit(0); return (EXIT_SUCCESS); }

In this case the main program simply stops its thread leaving the Deadline thread to run every two seconds. In a real instance the main program could continue to run using any of the other scheduling policies.

If you try and run the above program the chances are you will simply see “sensor” printed as fast as your machine can print it. The reason is that to use Deadline scheduling you have to run the program with root privileges. The setattr fails, and the thread is run under the default scheduling policy. , You should always test the return value of setattr for an error.

To make the program work it has to be run as root or similar. This is easy to arrange in a production environment, but during development it can be more difficult. If you are running the program using NetBeans and a remote build machine then simplest solution is to arrange for SSH to work with root as the user.

To do this log on to the machine using SSH and use:

sudo passwd root

to set a password for root. Next edit the ssh.config file:

sudo nano /etc/ssh/sshd_config

to allow root to log on via SSH. Find PermitRootLogin and uncomment the line and set it to yes:

PermitRootLogin yes

Save the file, reboot and set NetBeans up to use a remote Build Host using root and the password to log in.

Now if you run the program you should see the message printed every two seconds. The advantage of logging in as root is that you can also make use of the debug facilities without making any changes.

Deadline scheduling means you really don’t need to use a full realtime version of Linux or an RT operating system. It is good enough for most situations where you have a set of short duration repetitive tasks.

Summary

 

  • Multi-tasking is becoming increasingly common, even on small machines.

  • The original way of creating new processes is to use a fork which creates a new copy of the currently running process. Today it is more common to use threads, which are more efficient and closer bound than a fork.

  • Although C11 has a standard for threading, the original Pthreads library is still the most common way of implement threading.

  • Pthreads supports joinable and detached threads. A joinable thread can return a result to a thread that waits on its completion, whereas a detached thread cannot do this.

  • To avoid simultaneous access to resources you need to use locking. The mutex is one of the most basic locking devices.

  • A more complex locking device is the condition variable, which can be used to synchronize threads that can wait on the condition variable.

  • Threads and processes need to be scheduled by the operating system. Linux has a real time scheduling policy called FIFO, which is worth using, but the slightly less commonly used earliest deadline scheduling (EDS) is better.

 

Now available as a paperback or ebook from Amazon.

Applying C For The IoT With Linux

  1. C,IoT, POSIX & LINUX
  2. Kernel Mode, User Mode & Syscall
  3. Execution, Permissions & Systemd
    Extract Running Programs With Systemd
  4. Signals & Exceptions
    Extract  Signals
  5. Integer Arithmetic
    Extract: Basic Arithmetic As Bit Operations
  6. Fixed Point
    Extract: Simple Fixed Point Arithmetic
  7. Floating Point
  8. File Descriptors
    Extract: Simple File Descriptors 
    Extract: Pipes 
  9. The Pseudo-File System
    Extract: The Pseudo File System
    Extract: Memory Mapped Files ***NEW
  10. Graphics
    Extract: framebuffer
  11. Sockets
    Extract: Sockets The Client
    Extract: Socket Server
  12. Threading
    Extract:  Pthreads
    Extract:  Condition Variables
    Extract:  Deadline Scheduling
  13. Cores Atomics & Memory Management
    Extract: Applying C - Cores 
  14. Interupts & Polling
    Extract: Interrupts & Polling 
  15. Assembler
    Extract: Assembler

Also see the companion book: Fundamental C

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

Related Articles

Remote C/C++ Development With NetBeans

Raspberry Pi And The IoT In C

Getting Started With C/C++ On The Micro:bit

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


GitHub Introduces Code Scanning
26/03/2024

GitHub has announced a public beta of a code scanner that automatically fixes problems. The new feature was announced back in November, but has now moved to public beta status.  



Explore SyncFusion's Blazor Playground
16/04/2024

Syncfusion has provided an in-browser environment where you can write, compile and run code that uses Blazor components and get it previewed live.


More News

raspberry pi books

 

Comments




or email your comment to: comments@i-programmer.info

 

 



Last Updated ( Monday, 12 August 2019 )