{"id":8677,"date":"2018-05-07T09:25:57","date_gmt":"2018-05-07T08:25:57","guid":{"rendered":"https:\/\/blogs.mentor.com\/colinwalls\/?p=8677"},"modified":"2018-05-07T09:25:57","modified_gmt":"2018-05-07T08:25:57","slug":"task-scheduling-with-a-real-time-operating-system","status":"publish","type":"post","link":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/2018\/05\/07\/task-scheduling-with-a-real-time-operating-system\/","title":{"rendered":"Task scheduling with a real time operating system"},"content":{"rendered":"<p>From time to time, I like to poke around at some RTOS feature or functionality. Today I want to ponder the real core of any operating system: the scheduler. Every embedded system is different and it is, therefore, unsurprising that there are a number of different types of scheduler that might be employed. Different RTOS products offer different options, but I want to try to cover the spectrum of possibilities \u2026<!--more--><\/p>\n<p>As any software engineer knows, a conventional CPU can only execute one program at a time. The apparent simultaneous execution of multiple threads is achieved by control of the CPU being rapidly swapped between a number of code threads. This swapping process is managed by the scheduler.<\/p>\n<p>A scheduler need not be particularly complex. I have written a few in the course of my career and have never quite forgotten the first time I could clearly observe some code of mine unambiguously multitasking; it seemed somewhat magical, even though I knew exactly what was going on [as I had written every instruction of code involved].<\/p>\n<p>Although it is a slight simplification, I can identify five broad types of scheduler:<\/p>\n<h3>Run to completion [RTC]<\/h3>\n<p>An RTC scheduler is very simple. Indeed, I have previously [and only slight inaccurately] referred to one as a \u201c<a href=\"https:\/\/blogs.mentor.com\/colinwalls\/blog\/2010\/09\/06\/the-one-line-rtos\/\" target=\"_blank\" rel=\"noopener noreferrer\">one line RTOS<\/a>\u201d. The idea is that one task runs until it has completed its work, then terminates. Then the next task runs similarly. And so forth until all the tasks have run, when the sequence starts again.<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/RTC.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-8680\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/RTC-520x118.png\" alt=\"\" width=\"520\" height=\"118\" \/><\/a><\/p>\n<p>The simplicity of this scheme is offset by the drawback that each task\u2019s allocation of time is totally affected by all the others. The system will not be very deterministic. But, for some applications, this is quite satisfactory. An added level of sophistication might be support for task suspend, which means that one or more tasks may be excluded from the execution sequence until they are required again.<\/p>\n<h3>Round robin [RR]<\/h3>\n<p>An RR scheduler is the next level of complexity. Tasks are run in sequence in just the same way [with task suspend being a possibility], except that a task does not need to complete its work, it just relinquishes the CPU when convenient to do so. When it is scheduled again, it continues from where it left off.<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/RR.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-8681\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/RR-520x191.png\" alt=\"\" width=\"520\" height=\"191\" \/><\/a><\/p>\n<p>The greater flexibility of an RR scheduler comes at the cost of complexity. When a task relinquishes the CPU, its context [basically machine register values] needs to be saved so that it can be restored next time the task is scheduled. This process is required for all the other scheduler varieties that I will discuss.<\/p>\n<p>As with RTC, an RR scheduler still relies of each task behaving well and not hanging on to the processor for too long. Both RTC and RR are \u201ccooperative multitasking\u201d.<\/p>\n<h3>Time slice [TS]<\/h3>\n<p>A TS scheduler is a straightforward example of \u201cpreemptive multitasking\u201d. The idea is to divide time into \u201cslots\u201d, each of which might be, say, 1mS. Each task gets to run in a slot. At the end of its allocated time, it is interrupted and the next task run.<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/TS.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-8682\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/TS-520x188.png\" alt=\"\" width=\"520\" height=\"188\" \/><\/a><\/p>\n<p>The scheduling is not now dependent on tasks being \u201cgood citizens\u201d, as time utilization is managed fairly. A system built with a TS scheduler may be fully deterministic [i.e. predictable] &#8211; it is truly real time.<\/p>\n<h3>Time slice with background task [TSBG]<\/h3>\n<p>Although a TS scheduler is neat and tidy, there is a problem. If a task finds that it has no work to do, its only option is to loop &#8211; burning CPU time &#8211; until it can do something useful. This means that it might waste a significant proportion of its slot and an indefinite number of further slots. Clearly, the task might suspend itself [to be woken again when it is needed], but this messes up the timing of the other tasks.<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/TS-problem.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-8683\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/TS-problem-520x232.png\" alt=\"\" width=\"520\" height=\"232\" \/><\/a><\/p>\n<p>This is unfortunate, as the determinism of the system is compromised. A solution is to enhance the scheduler so that, if a task suspends itself, the remainder of its slot is taken up by a \u201cbackground task\u201d; this task would also use the full slots of any suspended tasks. This restores the timing integrity.<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/TS-background.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-8684\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/TS-background-520x192.png\" alt=\"\" width=\"520\" height=\"192\" \/><\/a><\/p>\n<p>What the background task actually does depends on the application, but broadly it must be non-time-citical code &#8211; like self-testing. There is, of course, the possibility that the background task will never get scheduled. Also, this special task cannot be suspended.<\/p>\n<h3>Priority [PRI]<\/h3>\n<p>A common, more sophisticated scheduling scheme is PRI, which is used in many [most] commercial RTOS products. The idea is that each task has a priority and is either \u201cready\u201d [to run] or \u201csuspended\u201d. The scheduler runs the task with the highest priority that is \u201cready\u201d. When that task suspends, it runs the one with the next highest priority. If an event occurs, which may have readied a higher priority task, the scheduler is run.<\/p>\n<p><a href=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/priority.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-8685\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/51\/2018\/05\/priority-520x260.png\" alt=\"\" width=\"520\" height=\"260\" \/><\/a><\/p>\n<p>Although more complex, a PRI scheduler give most flexibility for many applications.<\/p>\n<p>Commercial RTOS products, like our own <a href=\"https:\/\/www.mentor.com\/embedded-software\/nucleus\/\" target=\"_blank\" rel=\"noopener noreferrer\">Nucleus RTOS<\/a>, tend to use a priority scheduling scheme, but allow multiple tasks at each priority level. A time slice mechanism is then employed to allocate CPU time between multiple \u201cready\u201d tasks of the same priority.<\/p>\n<p><a href=\"http:\/\/www.linkedin.com\/in\/colinwalls\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-6579\" src=\"http:\/\/s3-blogs.mentor.com\/colinwalls\/files\/2014\/01\/linkedin.png\" alt=\"\" width=\"40\" height=\"40\" \/><\/a><a href=\"https:\/\/twitter.com\/colin_walls\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-6583\" src=\"http:\/\/s3-blogs.mentor.com\/colinwalls\/files\/2014\/01\/twitter.png\" alt=\"\" width=\"40\" height=\"40\" \/><\/a><a href=\"https:\/\/www.facebook.com\/colinwalls.author\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-6591\" src=\"http:\/\/s3-blogs.mentor.com\/colinwalls\/files\/2014\/01\/facebook.png\" alt=\"\" width=\"40\" height=\"40\" \/><\/a><a href=\"https:\/\/plus.google.com\/116301748426290440139\/posts?hl=en%3Fhl=en\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-6587\" src=\"http:\/\/s3-blogs.mentor.com\/colinwalls\/files\/2014\/01\/google.png\" alt=\"\" width=\"40\" height=\"40\" \/><\/a><a href=\"http:\/\/www.slideshare.net\/ColinWalls\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-6595\" src=\"http:\/\/s3-blogs.mentor.com\/colinwalls\/files\/2014\/01\/slideshare.jpg\" alt=\"\" width=\"41\" height=\"41\" \/><\/a><a href=\"http:\/\/blogs.mentor.com\/colinwalls\/\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-6599\" src=\"http:\/\/s3-blogs.mentor.com\/colinwalls\/files\/2014\/01\/wordpress.jpg\" alt=\"\" width=\"44\" height=\"44\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>From time to time, I like to poke around at some RTOS feature or functionality. Today I want to ponder&#8230;<\/p>\n","protected":false},"author":71677,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[1],"tags":[300,304,374,378,309,685],"industry":[],"product":[],"coauthors":[],"class_list":["post-8677","post","type-post","status-publish","format-standard","hentry","category-news","tag-embedded-software","tag-nucleus","tag-nucleus-os","tag-nucleus-rtos","tag-rtos","tag-scheduling"],"_links":{"self":[{"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/posts\/8677","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/users\/71677"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/comments?post=8677"}],"version-history":[{"count":0,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/posts\/8677\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/media?parent=8677"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/categories?post=8677"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/tags?post=8677"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/industry?post=8677"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/product?post=8677"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.stage.sw.siemens.com\/embedded-software\/wp-json\/wp\/v2\/coauthors?post=8677"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}