Cheap Threads for Embedded Systems

The standard version of Cheap Threads is designed for a hosted implementation of ISO C. That is, it uses a number of standard library functions.

Embedded applications typically use stand-alone implementations of C, where the standard library is not available. It's not hard to write your own versions of some standard functions such as memcpy and strlen. Others, however, are much more difficult to write from scratch.

In particular, consider the memory management functions (malloc and its kindred) and the file IO functions (from stdio.h). Not only would they be difficult to write -- for an embedded system they may be completely out of reach. A toaster oven can't very well write messages to standard error.

Since the standard version of Cheap Threads is not suitable for embedded systems, I cloned it to form Embedded Cheap Threads. This version enables you to avoid the use of dynamic memory allocation, standard IO functions, or both, just by using different versions of the Cheap Threads modules. The interface is unchanged, with one exception -- with Embedded Cheap Threads a thread cannot send a message of arbitrary length.

Caveats

I have not tried to eliminate all standard functions and headers. If you want to use Embedded Cheap Threads in an embedded application, you know better than I do whether those vestiges of the standard library will be a problem for you, and how best to deal with them.

I have never worked on an embedded system myself, so I don't know much about what's involved, beyond the likely absence of the standard library. For all I know there may be more I could do to make Embedded Cheap Threads useful. Suggestions are welcome.

Avoiding Files

Cheap Threads performs file IO in only one place -- the ct_report_error function, which by default writes a message to standard error. In Embedded Cheap Threads, the same function by default does nothing. The application can still install its own error handler by calling ct_install_error_reporter().

To avoid any reference to file IO, use the source file ecterror.c in place of cterror.c.

Avoiding stdio.h

The source file ctmemory.c, though not accessing any files, does #include <stdio.h> in order to provide a prototype for the sprintf function. It uses sprintf to format a small report about memory usage, issued via the ct_report_error function at the end of the program. Neither stdio.h nor sprintf is referenced if you compile with debugging turned off.

For an embedded application you are likely not to use dynamically allocated memory, in which case you won't use this source file anyway (see below). Otherwise you have several ways to avoid stdio.h:

Avoiding malloc and free

Standard Cheap Threads uses dynamic memory allocation extensively. It wraps all calls to the malloc and free functions in the allocMemory and freeMemory functions, defined in the source file ctmemory.c.

For those who cannot use dynamic memory allocation, Embedded Cheap Threads provides a parallel collection of modules that don't call malloc or free in any form:

Instead of calling malloc and free, Embedded Cheap Threads allocates objects internally from static arrays.

For example, in ectalloc.c there is a static array of objects of type Ct_thread, each of which represents a thread. When you create a thread, the software picks an available Ct_thread from the array. When a thread expires, the corresponding Ct_thread is returned to a pool from which it may be reused.

By default, there are ten Ct_thread objects. They may be reused indefinitely, so long as no more than ten threads exist at any one time. If that isn't enough, or if it's more than you need, you can increase or decrease the size of the static array by defining a macro.

Similar considerations apply to several other object types. The relevant macros are described elsewhere.


Home