Bob continues his article series about the open-source FreeRTOS. In Part 5, Bob looks at the FreeRTOS+POSIX library of functions. He explores what POSIX is, what value the POSIX standard provides to embedded developers and how compatible FreeRTOS is to the POSIX standard.
A number of years ago, a book came out entitled Real Men Don’t Eat Quiche. (Figure 1) . In the computer world t his title inspired a number of lists along the lines of “Real Engineers Don’t …” and “Real Programmers Don’t …” Included in those lists were our supposed aversion to reading specifications and manuals (in addition to the fact that “Real Engineers Don’t Know How to Spell Quiche.”) One common joke implied that only novices and cowards actually read specifications and manuals. I have found that there is a slight aversion to reading specifications and manuals among us embedded software and systems designers. But we avoid them only at our peril. In fact, with the advent of our super-complex microprocessor chips, any designer who doesn’t read the datasheets and the errata sheets does so at the peril of the entire project.
Needless to say (perhaps admitting my cowardice and immaturity), I have read countless manuals and specifications in my time. One aphorism that I have found to be true is that “Real Engineers Don’t Write Good Manuals and Specifications.” One reason we accuse ourselves of not reading them is because they are so often wrong, misleading and don’t have the information that we need. So, we instead read the source code or look at the schematics.
This month we are going to look at the POSIX library that can be used with FreeRTOS. We will look at: What is POSIX; why would we want our FreeRTOS design to use POSIX commands; and how compatible is FreeRTOS+POSIX with the POSIX standard. Unfortunately, the FreeRTOS specifications do not tell us how compatible it is with the POSIX standard. Instead we get ambiguous statements like “FreeRTOS+POSIX implements a subset of the POSIX threading API” and “With FreeRTOS+POSIX, an existing POSIX threading compliant application can be ported to run on the FreeRTOS kernel” .
Sounds great—but what if my existing POSIX threading compliant application uses APIs that are not part of the subset? And who has written a POSIX compliant application that only used the POSIX threading API? To top it off, I cannot find anywhere in the FreeRTOS directory a list of what POSIX threading functions have been excluded in the FreeRTOS+POSIX.
Perhaps this is why “Real Engineers Don’t Read Specifications.” They don’t tell us what we need. But “Real Engineers Read Circuit Cellar.” So, read on and see if I can fill in the gap on this.
WHAT IS POSIX?
I’ve gotten slightly ahead of myself because I haven’t explained to you what POSIX is. POSIX stands for Portable Operating System Interface. Wait! Where does the X come from? I am not sure, but I think it comes from the close connection between POSIX and UNIX. UNIX was initially called UNICs for Uniplexed Information and Computing Service. But according to Brian Kernighan no one knows how it morphed into UNIX. The POSIX standard is maintained by the IEEE and The Open Group (Figure 2). The POSIX.1-2017 standard is simultaneously IEEE Std 1003.-2017 and The Open Group Technical Standard Base Specifications, Issue 7. The Open Group Technical Standard Base Specification  is a great source for all of the function and data definitions for POSIX. Any time we wrote POSIX compliant code, we used this specification as the “bible” for how things worked. See! We do read specifications.
Most commercial implementations of UNIX (for example AIX, HP-UX, Solaris and MacOS) are POSIX compliant but Linux and Android are only mostly compliant. Green Hills’ Integrity, Wind River’s VxWorks and QNX, which are popular embedded systems operating systems, claim to be POSIX compliant. But only Integrity and VxWorks are actually certified compliant .
ADVANTAGES OF USING POSIX?
In both the embedded world and the desktop/server world, using a POSIX compliant operating system is useful on a number of levels. The word “portable” is used in the name because that is the goal: Write your application and don’t worry what POSIX OS you use because you can always easily port it. With the ease of porting, your design team also can minimize the number of APIs that they have to learn. Every non-POSIX interface has a different way of using semaphores or tasking or message queues. With POSIX, you learn the details of just one.
Imagine that you implemented an embedded system using VxWorks but found that a new design was going to use a processor not yet supported by VxWorks but that the processor was supported by QNX. Porting the new application would be greatly simplified if you limited your OS interface to the POSIX compliant API. In one case, we had a system using the Integrity OS that had a show stopping bug that Green Hills would not fix. Porting to Linux became a trivial matter since all of the POSIX calls we used to interface with the OS were also in Linux.
One last example: Once we designed a medical system with very strict real-time constraints. We wanted to use Linux but were unsure that it could meet the hard deadline real time requirements. So, we required the designers to implement it using only POSIX compliant calls so that we could switch to QNX should the need arise. It turned out that Linux with Real-time Extensions did meet the deterministic real-time response that we required so we never needed to port to QNX. But I slept better at night knowing that I had not put all of my eggs in the real-time Linux basket. And that is the beauty of the POSIX standard. It does make re-use or re-purposing code much simpler in a wide range of scenarios.
WHAT IS FREERTOS+POSIX?
FreeRTOS+POSIX partially implements the most recent POSIX standard. Some functions are wrapper functions (semaphores for example) but others are unique functions (for example message queues). Figure 3 shows the layers of FreeRTOS+POSIX.
Table 1 defines the header files incorporated in FreeRTOS+POSIX. You can click on each header file name to get expanded information for each.
|errno.h||This header file undefines the standard FreeRTOS error numbers and uses POSIX specific numbers.|
|fcntl.h||Defines the File Control Options defines the values assigned to various file control parameters.|
|mqueue.h||This defines the functions and data types related to Message Queues|
|pthread.h||This defines the functions and data types related to Process Threads|
|sched.h||This defines the functions and data types related to Scheduling|
|semaphore.h||This defines the functions and data types related to Semaphores|
|signal.h||This defines the functions and data types related to Signals|
|sys/types.h||This defines the data types available in the system|
|time.h||This defines the functions and data types related to time management|
|unistd.h||This defines the symbolic constants and types|
|utils.h||This defines some glue utility functions that are not POSIX compliant|
Obviously, the rub is: What does “partially implement” mean? How partial is it? Let’s look at each header file and see what is not included in the full POSIX standard. An even more detailed list of all of the functions in these headers is provided in an Excel spread sheet FreeRTOS POSIX Functions.xlsx, available for download from Circuit Cellar’s article code and files webpage .
errno.h—A very small subset of the error numbers is defined for FreeRTOS+POSIX since these are the only errors that the FreeRTOS+POSIX functions can generate that are different from the C standard error numbers.
fcntl.h—This header file defines the control parameters used in file operations functions. FreeRTOS+POSIX does not include those defines associated with file descriptors, record locking, the POSIX future advanced functionality and file status flags.
mqueue.h—The POSIX standard supports 10 message queue functions. FreeRTOS+POSIX supports 8 of them. The only functions missing are: notify the thread when the message is available and the ability to set the attributes of the message queue. Although FreeRTOS+POSIX provides other means, if your POSIX application relied heavily on mq_notify, you will be in for quite a re-write. See “FreeRTOS-Part 4: Inter-Process Communications“, Circuit Cellar 371, June 2021, to learn about those other means.
pthread.h—This header file defines the pthread functions. Overall, FreeRTOS’ partial implementation of the Thread API encompasses 34 of the 99 functions. FreeRTOS+POSIX does not support the POSIX pthread functionality associated with stack addresses, attributes and guards; spin locks; read-write locks; thread clean-up handlers; attribute inheritance; all functions that deal with defining a grouping of threads that contend for resources together; forking support; barrier attributes; condition variable attributes; concurrency levels; thread specific keys; priority ceilings for mutexs and one-time initialization of threads. On the positive side, the 34 functions are among the most used functions. The only functions that I readily use that are missing are stack guards, read-write locking and spin locks. However, porting an embedded system that uses these will get complicated with FreeRTOS.
sched.h—FreeRTOS+POSIX supports the ability of a thread to set and obtain the scheduling priority policy and to yield CPU control while running. Functionality that is missing includes: setting and obtaining the scheduling policy and parameter of a thread; and obtaining the round-robin scheduling interval.
sem.h—FreeRTOS+POSIX provides full support for unnamed semaphores. Missing is the ability to use named semaphores. The missing open, close and unlink functionality all work with a named semaphore. Initialization and destroy functions work with unnamed semaphores. Named semaphores are used more often between processes without a shared memory space whereas unnamed are used more often between threads invoked from the same process or with processes and threads that have a shared memory space.
signal.h—None of the functions defined in the standard POSIX signal.h file are defined for FreeRTOS+POSIX. Overall, there are 26 signal functions not supported. These include sending a signal to another thread; blocking and unblocking of signals; waiting on queued signals with and without a timer; killing a thread from another thread via a kill signal and non-local gotos. As with much of FreeRTOS, all of the functionality that we previously used signals for can be provided by other means. For example, message queues can be used to replace a lot of the functionality of signals. Rather than waiting on a signal you can wait on a semaphore or message queue. But, as we stated before, if your previous POSIX design used signals, prepare for a significant re-write when you port to FreeRTOS.
time.h—POSIX supports 28 functions in time.h, whereas FreeRTOS+POSIX supports 12 of them. All of the clock, sleep and timer-based functionality is supported. All of the other functions are most likely supported in the C run-time library provided by your tool chain. In all probability they will be POSIX compliant. For example, tzset which sets the time zone will most probably be provided in the tool chain.
types.h—This file provides some of the data glue to make this library work. It contains no functions.
unistad.h—You will find 77 functions in the POSIX unistad.h file. FreeRTOS+POSIX supports one of them: sleep (usleep is also provided but has been declared obsolete in the POSIX standard). Some of these are provided in your standard C run-time library but most are not. Of particular note is the pipe function. If you used pipes in your POSIX compliant design, you will have a major rewrite ahead of you to port to FreeRTOS.
utils.h—FreeRTOS+POSIX provides some non-compliant utility functions defined here. If you ever plan to port your POSIX compatible application from FreeRTOS to something like QNX, use these very carefully if at all.
As I have mentioned many times in this column, it is difficult to write documentation that provides what your readers want and need in a form that they can use. FreeRTOS+POSIX provides very good definition of what they define. What is missing are some high-level descriptions of some of the words they throw out like partial and subset. I have attempted in this article to define what you are missing from the POSIX Thread API in the FreeRTOS+POSIX library. I have also provided the spread sheet  mentioned earlier that I created. The spread sheet provides what I’ve not found anywhere else: the list of POSIX functions not supported in the FreeRTOS+POSIX library. Don’t let you’re your manager or customer tell you it will be easy to port your VxWorks POSIX system to FreeRTOS before you carefully look at which functions you have used that are not available.
As always, I have covered this in thin slices—but the spread sheet is a deep dive. Take a look and let me know if you find any problems. Next time we will look at security in FreeRTOS. Of course, in thin slices.
Editors Note: Embedded in Thin Slices is a bi-monthly column. The FreeRTOS multi-part article series began in issue #365.
Back issue PDF’s can be purchased at: www.cc-webshop.com
 POSIX functions spreadsheet in an even more detailed list is provided in an Excel spread sheet, available for download from Circuit Cellar’s article code and files webpage
 “FreeRTOS Part 4 – Inter-Process Communications” (Circuit Cellar 371, June 2021)
FreeRTOS | www.freertos.org
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • AUGUST 2021 #373 – Get a PDF of the issue