Native kernel C language API
To Contents | To previous page | To next page

## Native kernel C language API

The eCos kernel, like many other real-time kernels, is a library to which the programmer links an application. System calls resemble library API calls, and there is no trap mechanism to switch from user to system mode.

We present here the eCos kernel API and the APIs for other kernels provided as compatibility layers on top of eCos.

Since this API sits on top of a configurable system, the semantics are only weakly defined. The exact semantics and even the API itself depend on the configuration. For example if returned error codes were supported this would change the prototype of the functions. The semantics given in this chapter describe the default configuration.

As mentioned above, all source files which use the kernel C API should have the following `#include` statement:

    #include <cyg/kernel/kapi.h>

at the head of the file.

### Types used in programming eCos

We now describe the types defined for use with eCos. These are available to programs that include `kapi.h` .

Most of these types are meant to be opaque -- in other words, programmers do not need to know (and probably should not know) how they are defined. But the types that are numeric are marked, since it can be useful to use comparison operators.

The definitions for these types can be found in the installed tree, in the file `include/cyg/kernel/kapi.h` .

The eCos kernel uses the following naming convention for types:

- Types that can be treated as completely opaque usually have _t suffix.

- Types for which it is necessary to know the implementation do not have a _t suffix.

### cyg_addrword_t

A type which is large enough to store the larger of an address and a machine word. This is used for convenience when a function is passed data which could be either a pointer to a block of data or a single word.

### cyg_handle_t

A handle is a variable used to refer to eCos system objects (such as a thread or an alarm). Most eCos system calls that create system objects will return a handle that is used to access that object from then on.

### cyg_priority_t

A numeric type used to represent the priority of a thread, or the priority of an interrupt level. A lower number means a higher (i.e. more important) priority thread.

### cyg_code_t

A numeric type used for various error or status codes, such as exception numbers.

### cyg_vector_t

A numeric type used to identify an interrupt vector. Its value is called the interrupt vector id. This type is used for both ISR vector ids and VSR vector ids.

### cyg_tick_count_t

A numeric type used to count counter ticks. The resolution and other details regarding tick quantities depend on the configuration, but this is a 64 bit type, and no matter what configuration is chosen it should still last for centuries before it overflows.

### cyg_bool_t

A boolean type whose values can be false (0) or true (1).

### cyg_thread_entry_t

A function type for functions that are entry points for threads. It is used in the thread creation call `cyg_thread_create()` .

To help write thread entry point functions, here is how cyg_thread_entry_t is defined:

    typedef void cyg_thread_entry_t(void *);

Examples of thread functions can be found in the programming tutorial in Getting Started with eCos.

### cyg_exception_handler_t

A function type used for installing exception handlers. It is defined as:

    typedef void cyg_exception_handler_t(
     cyg_addrword_t data,
     cyg_code_t exception_number,
     cyg_addrword_t info
    );

### cyg_thread, cyg_interrupt, cyg_counter, cyg_clock, cyg_alarm, cyg_mbox, cyg_mempool_var, and cyg_mempool_fix

These types are of the appropriate size to contain the memory used by the respective kernel objects. These types are only used in the corresponding create call where the programmer allocates the memory for the object and passes the address to the kernel. After creation the provided handle is used to reference the object.

### cyg_mempool_info

Contains information about a memory pool.

    typedef struct {
     cyg_int32 totalmem;
     cyg_int32 freemem;
     void *base;
     cyg_int32 size;
     cyg_int32 blocksize;
     cyg_int32 maxfree; // The largest free block
    } cyg_mempool_info;

### cyg_sem_t, cyg_mutex_t, and cyg_cond_t

These types are of the appropriate size to contain the memory used by their respective kernel objects. These objects are always referred to by a pointer to an object of this type.

### cyg_VSR_t, cyg_ISR_t, and cyg_DSR_t

These are function types used when vector, interrupt and delayed service routines are installed.

    typedef void cyg_VSR_t();
    typedef cyg_uint32 cyg_ISR_t(cyg_vector_t vector,
     cyg_addrword_t data);
    typedef void cyg_DSR_t(cyg_uint32 vector,
     cyg_ucount32 count,
     cyg_addrword_t data);

### cyg_resolution_t

Stores the resolution of a clock. The resolution is defined to be (dividend/divisor) nanoseconds per tick.

    typedef struct { cyg_uint32 dividend;
     cyg_uint32 divisor; }
    cyg_resolution_t;

### cyg_alarm_t

The function type used for alarm handlers.

    typedef void cyg_alarm_t(cyg_handle_t alarm,
     cyg_addrword_t data);

### Thread operations

    void cyg_scheduler_start( void )

Starts the scheduler with the threads that have been created. It never returns. The scheduler has been chosen at configuration time. eCos currently ships with three schedulers: a bitmap scheduler, a multi-level scheduler (selected by default), and an experimental "lottery" scheduler which should not be used.

The configuration tool can be used to select between schedulers. The configuration options are
CYGSEM_SCHED_BITMAP, CYGSEM_SCHED_MLQUEUE and CYGSEM_SCHED_LOTTERY.

### NOTE

Interrupts are not enabled until the scheduler has been started with `cyg_scheduler_start()` .

    void cyg_scheduler_lock( void )

Locks the scheduler so that a context switch cannot occur. This can be used to protect data shared between a thread and a DSR, or between multiple threads, by surrounding the critical region with `cyg_scheduler_lock()` and `cyg_scheduler_unlock()` .

    void cyg_scheduler_unlock( void )

Unlocks the scheduler so that context switching can occur again.

    void cyg_thread_create(
        cyg_addrword_t sched_info,
        cyg_thread_entry_t *entry,
        cyg_addrword_t entry_data,
        char *name,
        void *stack_base,
        cyg_ucount32 stack_size,
        cyg_handle_t *handle,
        cyg_thread *thread )

Creates a thread in a suspended state. The thread will not run until it has been resumed with `cyg_thread_resume()` and the scheduler has been started with `cyg_scheduler_start()` .

Here is a description of the parameters of `cyg_thread_create()` :

sched_info

Information to be passed to the scheduler. For almost all schedulers this is a simple priority value, and you can simply pass a non-negative integer when you create the thread.

entry

A user-supplied function: it is a routine that begins execution of the new thread. This function takes a single argument of type cyg_addrword_t, which is usually a pointer to a block of data, which allows `cyg_scheduler_start()` to pass data to this particular thread.

Here is a typedef for the entry function:

    typedef void cyg_thread_entry_t(cyg_addrword_t);

entry_data

A data value passed to the entry function. This may be either a machine word datum or the address of a block of data.

name

A C string with the name of this thread.

stack_base

The address of the stack base. If this value is NULL then `cyg_thread_create()` will choose a stack base.

### NOTE

Passing a stack base of NULL is not supported in this release. You must pass a real address for the stack base.

stack_size

The size of the stack for this thread. If this is 0, the default stack size will be used for this thread.

### NOTE

Passing a stack size of 0 is not supported in this release. You must pass a real stack size.

handle

`cyg_thread_create()` returns the thread handle in this location.

thread

The thread housekeeping information is placed in the memory pointed to by this parameter. If this pointer is NULL then the memory will be allocated.

### NOTE

Passing a NULL value for the thread data structure address is not supported in this release. You must pass a valid address.

    void cyg_thread_exit( void )

Exits the current thread. At present this simply puts the thread into suspended state.

    void cyg_thread_suspend(
        cyg_handle_t thread )

Suspends the thread. A thread may be suspended multiple times, in which case it will need to be resumed the same number of times before it will run.

    void cyg_thread_resume(
        cyg_handle_t thread )

Resumes thread. If a thread has been suspended multiple times it will need to be resumed the same number of times before it will run. Threads are created in a suspended state and must be resumed before they will run.

    void cyg_thread_yield( void )

Yields control to the next runnable thread of equal priority. If no such thread exists, then this function has no effect.

    void cyg_thread_kill(
        cyg_handle_t thread )

Kills thread.

        cyg_handle_t cyg_thread_self( void )

Returns the handle of the current thread.

    void cyg_thread_release(
        cyg_handle_t thread )

Break the thread out of any wait it is currently in. Exactly how the thread returns from the wait operation, and how, if at all, the break is indicated, depends on the synchronization object it was waiting on.

    cyg_ucount32 cyg_thread_new_data_index( void )

Allocates a new per-thread data index from those still available. If no more indexes are available, and assertions are enabled, an assertion will be raised.

    void cyg_thread_free_data_index(
         cyg_ucount32 index )

Return the per-thread data index to the pool.

    CYG_ADDRWORD cyg_thread_get_data(
         cyg_ucount32 index )

Retrieve the per-thread data at the given index for the current thread.

    CYG_ADDRWORD *cyg_thread_get_data_ptr(
         cyg_ucount32 index )

Return a pointer to the per-thread data at the given index for the current thread. This should be used with some care since in some future implementation the per-thread data may be managed by a dynamic mechanism that might invalidate this pointer at any time. This pointer should only be considered valid until the next call to the per-thread data functions.

    void cyg_thread_set_data(
         cyg_ucount32 index, CYG_ADDRWORD data )

Store the data in the per-thread data for the current thread at the given index.

### Priority manipulation

    void cyg_thread_set_priority(
         cyg_handle_t thread,
         cyg_priority_t priority )

Sets the priority of the given thread to the given value. The smaller the value, the higher the priority of the thread.

Allowed priorities range between 1 and 64. The values of these parameters are configuration-dependent because they depend on which scheduler has been selected, and what value has been configured for the CYGNUM_KERNEL_SCHED_PRIORITIES configuration parameter (see Thread operations and "Option: Number of priority levels" in Section V").

There is always an idle thread, owned by the kernel, running at CYG_THREAD_MIN_PRIORITY. Because of this, ordinary threads should never be run at the lowest priority.

    cyg_priority_t cyg_thread_get_priority(
          cyg_handle_t thread )

Returns the priority of the given thread.

    void cyg_thread_delay(
         cyg_tick_count_t delay )

Puts the current thread to sleep for delay ticks. In a default configuration there are approximately 100 ticks a second. The actual length of the ticks is given by the resolution of the real-time clock. See Counters, clocks and alarms for more information on counter resolution.

### Exception handling

Exception handlers can be installed to deal with various system-level exceptions, such as alignment errors, resets, timers and so forth. Exception handling is a configurable feature of eCos and is enabled by default.

The range of values for the exception_number parameter in the functions below is hardware-dependent, as are the individual exceptions. See `hal/ARCH/arch/` v1_3_x `/include/hal_intr` for the exception vector definitions specific to a given architecture.

The exception handler is a function of the following type:

    typedef void cyg_exception_handler_t(
     cyg_addrword_t data,
     cyg_code_t exception_number,
     cyg_addrword_t info
    );

cyg_exception_handler_t is the type used for functions which are called as a result of an exception. It is used in the function `cyg_exception_set_handler()` .

    void cyg_exception_set_handler(
         cyg_code_t exception_number,
         cyg_exception_handler_t *new_handler,
         cyg_addrword_t new_data,
         cyg_exception_handler_t **old_handler,
         void **old_data )

Replace current exception handler. This may apply to either the thread, or to a global exception handler, according to how exception handling was configured (global or per-thread). The exception may be ignored, or used to specify a particular handler.

    void cyg_exception_call_handler(
        cyg_handle_t thread,
        cyg_code_t exception_number,
        cyg_addrword_t exception_info )

Invoke exception handler for the given exception number. The exception handler will be invoked with exception_info as its third argument.

### Interrupt handling

Interrupt handling is by nature machine-specific. The eCos kernel aims to provide efficiency and flexibility in this area, while maintaining a very low interrupt latency. To allow the programmer direct access to hardware, the semantics and the interface can vary from one architecture to another.

The interrupt vectors for a given architecture are defined in `hal/ARCH/arch/` v1_3_x `/include/hal_intr.h` where also special semantics and caveats of the interrupt capabilities would be described.

    typedef void cyg_VSR_t();
    typedef cyg_uint32 cyg_ISR_t(cyg_vector_t vector,
     cyg_addrword_t data);
    typedef void cyg_DSR_t(cyg_vector_t vector,
     cyg_ucount32 count,
     cyg_addrword_t data);

    enum cyg_ISR_results
    {
     CYG_ISR_HANDLED = 1, /* Interrupt was handled */
     CYG_ISR_CALL_DSR = 2 /* Schedule DSR */
    };

    void cyg_interrupt_create(
        cyg_vector_t vector,
        cyg_priority_t priority,
        cyg_addrword_t data,
        cyg_ISR_t *isr,
        cyg_DSR_t *dsr,
        cyg_handle_t *handle,
        cyg_interrupt *intr )

Creates an interrupt object and returns a handle to it. The object contains information about which interrupt vector to use and the ISR and DSR that will be called after the interrupt object is attached. The interrupt object will be allocated in the memory passed in the intr parameter. The interrupt object is not immediately attached; it must be attached with the `cyg_interrupt_attach()` call.

    void cyg_interrupt_delete(
        cyg_handle_t interrupt )

Detaches the interrupt from the vector and frees the corresponding memory.

    void cyg_interrupt_attach(
    cyg_handle_t interrupt )

Attaches interrupt.

    void cyg_interrupt_detach(
        cyg_handle_t interrupt )

Detaches interrupt.

    void cyg_interrupt_get_vsr(
        cyg_vector_t vector,
        cyg_VSR_t **vsr )

Returns a pointer to the VSR currently installed on vector.

void `cyg_interrupt_set_vsr` (
cyg_vector_t vector,
cyg_VSR_t *vsr )

Sets the current VSR on vector. A VSR directly attaches to the hardware interrupt vector and needs to be written in assembler.

void `cyg_interrupt_disable` ( void )

Disables all interrupts.

    void cyg_interrupt_enable( void )

Enables all interrupts.

    void cyg_interrupt_mask(
        cyg_vector_t vector )

Programs the interrupt controller to stop delivery of interrupts on vector. On some architectures this will also disable all lower priority interrupts while on others they remain enabled.

    void cyg_interrupt_unmask(
        cyg_vector_t vector )

Programs the interrupt controller to allow delivery of interrupts on the given interrupt vector.

    void cyg_interrupt_acknowledge(
        cyg_vector_t vector )

Should be used from inside an ISR to acknowledge receipt of the interrupt. The interrupt must be acknowledged. If an interrupt is not acknowledged, the interrupt may trigger immediately after the ISR returns, causing the ISR to be called again in a loop.

    void cyg_interrupt_configure(
        cyg_vector_t vector,
        cyg_bool_t level,
        cyg_bool_t up )

On some interrupt controllers the way an interrupt is detected may be configured. The level parameter chooses between level- or edge-triggered interrupts. The up parameter chooses between high and low level for level triggered interrupts or rising and falling edges for edge triggered interrupts.

### Counters, clocks and alarms

### Counters

The counter objects provided by the kernel provide an abstraction of the clock facility that is generally provided. Application code can associate alarms with counters, where an alarm is identified by the number of ticks until it triggers, the action to be taken on triggering, and whether or not the alarm should be repeated.

There are two different implementations of the counter objects. The first stores all alarms in a single linked list. The alternative implementation uses a table of linked lists, with the size of the table being a separate configurable option. A single list is more efficient in terms of memory usage and is generally adequate when the application only makes use of a small number of alarms. For more complicated operations it is better to have a table of lists since this reduces the amount of computation whenever the timer goes off. Assuming a table size of 8 (the default value) on average the timer code will only need to check 1/8 of the pending alarms instead of all of them.

The configuration options which select the counter implementation are CYGIMP_KERNEL_COUNTERS_MULTI_LIST ("Option: Implement counters using a table of lists" in Section V) and CYGIMP_KERNEL_COUNTERS_SINGLE_LIST ("Option: Implement counters using a single list", in Section V).

The following functions can be used to create and manipulate counters:

    void cyg_counter_create(
        cyg_handle_t *counter,
        cyg_counter *the_counter )

Creates a new counter and places it in the space pointed to by counter. A counter stores a value that is incremented by `cyg_counter_tick()` . Alarms may be attached to counters, and the alarms will trigger when the counter reaches a specified value.

    void cyg_counter_delete(
        cyg_handle_t counter )

Deletes the given counter and frees the corresponding memory.

    cyg_tick_count_t cyg_counter_current_value(
        cyg_handle_t counter )

Returns the current value of the given counter.

    void cyg_counter_set_value(
        cyg_handle_t counter,
        cyg_tick_count_t new_value )

Sets the counter's value to new_value.

    void cyg_counter_tick(
        cyg_handle_t counter )

Advances the counter by one tick.

### C locks

Clocks are counters which are associated with a stream of ticks that represent time periods. Clocks have a resolution associated with them, whereas counters do not.

The most frequently used clock is the real-time clock which serves two special purposes. First, it is necessary to support clock and alarm related functions such as `cyg_thread_delay()` . Second, it is needed to implement timeslicing in the mlqueue and lottery schedulers. If the application does not require either of these facilities, then it is possible to disable the real-time clock support completely. It is also possible to disable just timeslicing with the configuration option CYGSEM_KERNEL_SCHED_TIMESLICE, or just the clock and alarm functions, using the option CYGFUN_KERNEL_THREADS_TIMER. .

The real-time clock is available if the configuration option CYGVAR_KERNEL_COUNTERS_CLOCK is defined.

Clock resolution is stored in variables of type cyg_resolution_t (see cyg_resolution_t ).

    void cyg_clock_create(
        cyg_resolution_t resolution,
        cyg_handle_t *handle,
        cyg_clock *clock )

Creates a clock object with the given resolution and places it in the space pointed to by clock. A clock is a counter driven by a regular source of ticks. For example the system real-time clock is driven by a clock interrupt.

void `cyg_clock_delete` (
cyg_handle_t clock )

Deletes a clock object and frees the associated memory.

void `cyg_clock_to_counter` (
cyg_handle_t clock,
cyg_handle_t *counter )

Converts a clock handle to a counter handle. The counter functions can then be used with the counter handle.

    void cyg_clock_set_resolution(
        cyg_handle_t clock,
        cyg_resolution_t resolution )

Changes the resolution of a given clock object.

cyg_resolution_t `cyg_clock_get_resolution` (
cyg_handle_t clock )

Returns the resolution of clock.

cyg_handle `cyg_real_time_clock` ( void )

Returns a handle to the system-supplied real-time clock.

cyg_tick_count_t `cyg_current_time` ( void )

Returns the real-time clock's counter. This is equivalent to executing the code:

     cyg_clock_to_counter(cyg_real_time_clock(), &h),
     cyg_counter_current_value(h);

### Alarms

    typedef void cyg_alarm_t(cyg_handle_t alarm,
     cyg_addrword_t data);

cyg_alarm_t is the type used for functions which are used to handle alarm events. It is used in the function `cyg_alarm_create()` .

void `cyg_alarm_create` (
cyg_handle_t counter,
cyg_alarm_t *alarm_fn,
cyg_addrword_t data,
cyg_handle_t *handle,
cyg_alarm *alarm )

Creates an alarm object. The alarm is attached to the counter and is created in the memory pointed to by alarm. When the alarm triggers, the handler function alarmfn is called and is passed data as a parameter. The alarm handler executes in the context of the function that incremented the counter and thus triggered the alarm.

### NOTE

If the alarm is associated with the real-time clock, the alarm handler alarmfn will be invoked by the delayed service routine (DSR) that services the real-time clock. This means that real-time clock alarm handlers (which are possibly the most frequently used) must follow the rules of behavior for DSRs. These rules are outlined in Interrupt and exception handlers .

    void cyg_alarm_delete(
        cyg_handle_t alarm )

Disables the alarm, detaches from the counter, invalidates handles, and frees memory if it was dynamically allocated by `cyg_alarm_create()` .

    void cyg_alarm_initialize(
        cyg_handle_t alarm,
        cyg_tick_count_t trigger,
        cyg_tick_count_t interval )

Initialize an alarm. This sets it to trigger at the tick with value trigger. When an alarm triggers, this event is dealt with by calling the alarmfn parameter which was passed when the alarm was created using `cyg_alarm_create()` . If interval is non-zero, then after the alarm has triggered it will set itself to trigger again after interval ticks. Otherwise, if interval is zero, the alarm is will be disabled automatically once it has triggered.

void `cyg_alarm_enable` (
cyg_handle_t alarm )

Enables an alarm that has been disabled by calling `cyg_alarm_disable()` .

    void cyg_alarm_disable(
        cyg_handle_t alarm )

Disables an alarm. After an alarm is disabled it will not be triggered unless it is subsequently re-enabled by calling `cyg_alarm_enable()` or is reinitialized by calling `cyg_alarm_initialize()` .

Note, though, that if a periodic alarm that has been disabled is re-enabled without reinitializing it will be in phase with the original sequence of alarms. If it is reinitialized, the new sequence of alarms will be in phase with the moment in which `cyg_alarm_initialize()` was called.

### Synchronization

### Semaphores

The semaphores defined by the type cyg_sem_t are counting semaphores. These objects are not referred to by handles, but rather by the pointer to the variable in which the semaphore is created.

    void cyg_semaphore_init(
        cyg_sem_t *sem,
        cyg_ucount32 val )

Initializes a semaphore. The initial semaphore count is set to val.

    void cyg_semaphore_destroy(
        cyg_sem_t *sem )

Destroys a semaphore. This must not be done while there are any threads waiting on it.

    void cyg_semaphore_wait(
        cyg_sem_t *sem )

If the semaphore count is zero, the current thread will wait on the semaphore. If the count is non-zero, it will be decremented and the thread will continue running.

    cyg_bool_t cyg_semaphore_trywait(
        cyg_sem_t *sem )

A non-blocking version of `cyg_semaphore_wait()` . This attempts to decrement the semaphore count. If the count is positive, then the semaphore is decremented and true is returned. If the count is zero then the semaphore remains unchanged, and false is returned, but the current thread continues to run.

    cyg_bool_t cyg_semaphore_timed_wait(
        cyg_sem_t *sem,
        cyg_tick_count_t abstime )

A time-out version of `cyg_semaphore_wait()` . This attempts to decrement the semaphore count. If the count is positive, then the semaphore is decremented and true is returned. If the count is zero, it will wait for the semaphore to increment. If however the abstime time-out is reached first, it will return false without changing state, and the current thread will continue to run.

The cyg_tick_count_t parameter is an absolute time. If a relative time is required, you should use `cyg_current_time` with an offset. For example, to time out 200 ticks from the present you would use:

    cyg_semaphore_timed_wait(&sem, cyg_current_time() + 200);

`cyg_semaphore_timed_wait()` is only available if the configuration option CYGFUN_KERNEL_THREADS_TIMER is set.

    void cyg_semaphore_post(
        cyg_sem_t *sem )

If there are threads waiting on this semaphore this will wake exactly one of them. Otherwise it simply increments the semaphore count.

    void cyg_semaphore_peek(
        cyg_sem_t *sem,
        cyg_count32 *val )

Returns the current semaphore count in the variable pointed to by val.

### Mutexes

Mutexes (mutual exclusion locks) are used in a similar way to semaphores. A mutex only has two states, locked and unlocked. Mutexes are used to protect accesses to shared data or resources. When a thread locks a mutex it becomes the owner. Only the mutex's owner may unlock it. While a mutex remains locked, the owner should not lock it again, as the behavior is undefined and probably dangerous.

If non-owners try to lock the mutex, they will be suspended until the mutex is available again, at which point they will own the mutex.

    void cyg_mutex_init(
        cyg_mutex_t *mutex )

Initializes a mutex. It is initialized in the unlocked state.

void `cyg_mutex_destroy` (

cyg_mutex_t *mutex )

Destroys a mutex. A mutex should not be destroyed in the locked state, as the behavior is undefined.

    cyg_bool_t cyg_mutex_lock(
        cyg_mutex_t *mutex )

Changes the nutex from the unlocked state to the locked state. When this happens the mutex becomes owned by the current thread. If the mutex is locked, the current thread will wait until the mutex becomes unlocked before performing this operation. The result of this function will be TRUE if the mutex has been locked, or FALSE if it has not. A FALSE result can result if the thread has been released from its wait by a call to `cyg_thread_release()` or `cyg_mutex_release()` .

    void cyg_mutex_unlock(
        cyg_mutex_t *mutex )

Changes the mutex from the locked state to the unlocked state. This function may only be called by the thread which locked the mutex, and should not be called on an unlocked mutex.

    void cyg_mutex_release(
        cyg_mutex_t *mutex )

Release all threads waiting on the mutex pointed to by the mutex argument. These threads will return from cyg_mutex_lock() with a FALSE result and will not have claimed the mutex. This function has no effect on any thread that may haev the mutex claimed.

### Condition Variables

Condition variables are a synchronization mechanism which (used with a mutex) grants several threads mutually exclusive access to shared data and to broadcast availability of that data to all the other threads.

A typical example of the use of condition variables is when one thread (the producer) is producing data and several other (consumer) threads are waiting for that data to be ready. The consumers will wait by invoking `cyg_cond_wait()` . The producer will lock access to the data with a mutex, and when it has generated enough data for the other processes to consume, it will invoke `cyg_cond_broadcast()` to wake up the consumers. The Getting Started with eCos book has example programs which use condition variables to implement a simple message passing system between threads.

    void cyg_cond_init(
        cyg_cond_t *cond,
        cyg_mutex_t *mutex )

Initializes the condition variable. A condition variable is attached to a specific mutex.

    void cyg_cond_destroy(
        cyg_cond_t *cond )

Destroys the condition variable cond. This must not be done on a condition variable which is in use. After it has been destroyed, it may be subsequently reinitialized.

    void cyg_cond_wait(
        cyg_cond_t *cond )

Causes the current thread to wait on the condition variable, while simultaneously unlocking the corresponding mutex. `cyg_cond_wait()` may be called by a thread which has the corresponding mutex locked.

The thread can only be awakened by a call to `cyg_cond_signal()` or `cyg_cond_broadcast()` on the same condition variable. When the thread is awakened, the mutex will be reclaimed before this function proceeds. Since it may have to wait for this, `cyg_cond_wait()` should only be used in a loop since the condition may become false in the meantime. This is shown in the following example:

    extern cyg_mutex_t mutex;
    extern cyg_cond_t cond;

    cyg_mutex_lock( &mutex );
    ...

    while( condition_not_true )
    {
     cyg_cond_wait( &cond );
    }

    ...

    cyg_mutex_unlock( &mutex );

    cyg_bool_t cyg_cond_timed_wait(
        cyg_cond_t *cond,
        cyg_tick_count_t abstime )

A time-out version of `cyg_cond_wait()` which waits for a signal or broadcast. If a signal or broadcast is received it returns true, but if one is not received by abstime, it returns false.

The cyg_tick_count_t parameter is an absolute time. If a relative time is required, you should use `cyg_current_time` with an offset. For example, to time out 200 ticks from the present you would use:

    cyg_cond_timed_wait(&sem, cyg_current_time() + 200);

`cyg_cond_timed_wait()` is only available if the configuration option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT is set.

    void cyg_cond_signal(
        cyg_cond_t *cond )

Wakes up at least one thread which is waiting on the condition variable. When a thread is awakened it will become the owner of the mutex. `cyg_cond_signal()` may be called by the thread which currently owns the mutex to which the condition variable is attached.

    void cyg_cond_broadcast(
        cyg_cond_t *cond )

Wakes all the threads waiting on the condition variable. Each time a thread is awakened it will become the current owner of the mutex.

### Memory pools

There are two sorts of memory pools. A variable size memory pool is for allocating blocks of any size. A fixed size memory pool, has the block size specified when the pool is created and only provides blocks of that size.

Blocking, non-blocking and "blocking with time-out" versions of these calls are provided.

    void cyg_mempool_var_create(
        void *base,
        cyg_int32 size,
        cyg_handle_t *handle,
        cyg_mempool_var *var )

Creates a variable size memory pool. The parameters are:

base

base of memory to use for pool

size

size of memory pool in bytes

handle

returned handle of memory pool

var

space to put pool structure in

    void cyg_mempool_var_delete(
        cyg_handle_t varpool )

Deletes the variable size memory pool varpool.

    void *cyg_mempool_var_alloc(
        cyg_handle_t varpool,
        cyg_int32 size )

Allocates a block of length size. This will block until the memory becomes available.

    void *cyg_mempool_var_timed_alloc(
        cyg_handle_t varpool,
        cyg_int32 size,
        cyg_tick_count_t abstime )

Allocates a block of length size. If the requested amount of memory is not available, it will wait until abstime before giving up and returning NULL.

    void *cyg_mempool_var_try_alloc(
        cyg_handle_t varpool,
        cyg_int32 size )

Allocates a block of length size. NULL is returned if not enough is available.

    void cyg_mempool_var_free(
        cyg_handle_t varpool,
        void *p )

Frees memory back into variable size pool.

    cyg_bool_t cyg_mempool_var_waiting(
        cyg_handle_t varpool )

Returns true if any threads are waiting for memory in pool.

    typedef struct {
     cyg_int32 totalmem;
     cyg_int32 freemem;
     void *base;
     cyg_int32 size;
     cyg_int32 blocksize;
     cyg_int32 maxfree; // The largest free block
    } cyg_mempool_info;

    void cyg_mempool_var_get_info(
        cyg_handle_t varpool,
        cyg_mempool_info *info )

Puts information about a variable memory pool into the structure provided.

    void cyg_mempool_fix_create(
        void *base,
        cyg_int32 size,
        cyg_int32 blocksize,
        cyg_handle_t *handle,
        cyg_mempool_fix *fix )

Create a fixed size memory pool. This function takes the following parameters:

base

base of memory to use for pool

size

size of total space requested

blocksize

size of individual elements

handle

returned handle of memory pool

fix

space to put pool structure in

    void cyg_mempool_fix_delete(
        cyg_handle_t fixpool )

Deletes the given fixed size memory pool.

    void *cyg_mempool_fix_alloc(
    cyg_handle_t fixpool )

Allocates a block. If the memory is not available immediately, this blocks until the memory becomes available.

    void *cyg_mempool_fix_timed_alloc(
        cyg_handle_t fixpool,
        cyg_tick_count_t abstime )

Allocates a block. If the memory is not already available, it will try until abstime before giving up and returning a NULL.

    void *cyg_mempool_fix_try_alloc(
        cyg_handle_t fixpool )

Allocates a block. NULL is returned if no memory is available.

    void cyg_mempool_fix_free(
        cyg_handle_t fixpool,
        void *p )

Frees memory back into fixed size pool.

    cyg_bool_t cyg_mempool_fix_waiting(
        cyg_handle_t fixpool )

Returns true if there are any threads waiting for memory in the given memory pool.

    void cyg_mempool_fix_get_info(
        cyg_handle_t fixpool,
        cyg_mempool_info *info )

Puts information about a variable memory pool into the structure provided.

The fixed size memory pool simply returns blocks of memory of exactly the blocksize requested. If the pool is being used to allocate memory for a type that has alignment constraints (such as 4-byte alignment), then it is up to the user to align the memory appropriately for the type in question. Alternatively, choose a blocksize that is an exact multiple of the required alignment.

### Message boxes

Message boxes are a primitive mechanism for exchanging messages between threads, inspired by the µ ITRON specification. A message box can be created with `cyg_mbox_create()` before the scheduler is started, and two threads in a typical producer/consumer relationship can access it. One thread, the producer, will use `cyg_mbox_put()` to make data available to the consumer thread which uses `cyg_mbox_get()` to access the data.

The size of the internal message queue is configured by the CYGNUM_KERNEL_SYNCH_MBOX_QUEUE_SIZE parameter (see "Message box queue size", in Section V). The default value is 10.

Blocking, non-blocking and "blocking with time-out" versions of these calls are provided.

    void cyg_mbox_create(
        cyg_handle_t *handle,
        cyg_mbox *mbox )

Creates a message box using the space provided in the mbox parameter, and returns a handle for future access to that message box.

    void cyg_mbox_delete(
        cyg_handle_t mbox )

Deletes the given message box.

    void *cyg_mbox_get(
        cyg_handle_t mbox )

Waits for a message to be available, then retrieves it and returns the address of the data.

    void *cyg_mbox_timed_get(
        cyg_handle_t mbox,
        cyg_tick_count_t timeout )

Waits for a message to be available, but times out if timeout time passes. This version of the function is only available if the configuration option CYGFUN_KERNEL_THREADS_TIMER is turned on.

    void *cyg_mbox_tryget(
        cyg_handle_t mbox )

Checks to see if a message is ready. If no message is available it returns immediately with a return value of NULL. If a message is available it retrieves it and returns the address of the data.

    void *cyg_mbox_peek_item(
        cyg_handle_t mbox )

Checks to see if a message is ready, and if one is available returns the address of the data without removing the message from the queue. If no message is available it returns NULL.

    cyg_bool_t cyg_mbox_put(
        cyg_handle_t mbox,
        void *item )

Places a message in the given message box. If the queue is full it will block until the message can be sent. It returns true if the message was successfully sent, and false if the message was not sent and its sleep was awakened by the kernel before the message could be sent.

The `cyg_mbox_put()` function is only available if the CYGMTH_MBOXT_PUT_CAN_WAIT configuration has been selected.

    cyg_bool_t cyg_mbox_timed_put(
        cyg_handle_t mbox,
        void *item,
        cyg_tick_count_t abstime )

A time-out version of `cyg_mbox_put()` . This will try to place the message in the given message box. If the queue is full, it will wait until abstime before giving up and returning false.

The `cyg_mbox_timed_put()` function is only available if the both the CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT and CYGFUN_KERNEL_THREADS_TIMER configuration have been selected.

    cyg_bool_t cyg_mbox_tryput(
        cyg_handle_t mbox,
        void *item )

Tries to place a message in the given message box. It returns true if the message was successfully sent, and false if the message could not be sent immediately, usually because the queue was full.

    cyg_count32 cyg_mbox_peek(
        cyg_handle_t mbox )

Takes a peek at the queue and returns the number of messages waiting in it.

    cyg_bool_t cyg_mbox_waiting_to_get(
        cyg_handle_t mbox )

Queries the kernel to see if other processes are waiting to receive a message in the given message box. Returns true if other processes are waiting, false otherwise.

    cyg_bool_t cyg_mbox_waiting_to_put(
        cyg_handle_t mbox )

Queries the kernel to see if other processes are waiting to send a message in the given message box. Returns true if other processes are waiting, false otherwise.

### Flags

Flags are a synchronization mechanism which allow a thread to wait for a single condition or a combination of conditions. The conditions are represented by bits in a 32 bit word. Flags are inspired by the µ ITRON specification.

Flags are of type cyg_flag_t, which are 32 bit words, and routines are provided to set or mask some bits in the flag value.

A "consumer side" thread can wait for a "producer side" thread to set the entire collection of bits, or any subset of them.

When a thread sets some bits in a flag, all threads whose requirements are now satisfied are woken up; thus flags have broadcast semantics. A variation on the wait call can specify that the flag value be cleared when the wait call is satisfied, in which case the setting of bits would not be a broadcast.

Blocking, non-blocking, and "blocking with time-out" versions of the wait calls are provided.

    void cyg_flag_init(
        cyg_flag_t *flag )

Initializes a flag variable.

    void cyg_flag_destroy(
        cyg_flag_t *flag )

Destroys a flag variable.

    void cyg_flag_setbits(
        cyg_flag_t *flag,
        cyg_flag_value_t value )

Sets the bits in flag which are set in value.

A side effect of `cyg_flag_setbits()` is that the kernel wakes up any waiting threads whose requirements are now satisfied.

flag

A pointer to the flag whose bits are being set. The new setting of flag will be `*flag ->(*flag | value)` .

value

A word whose 1 bits will be also set in *flag.

    void cyg_flag_maskbits(
        cyg_flag_t *flag,
        cyg_flag_value_t value )

Clear the bits in the given flag which are zero in the value. This cannot result in new threads being eligible for awakening.

flag

A pointer to the flag whose bits are being cleared. The new setting of flag will be `*flag ->(*flag & value)` .

value

A word whose 0 bits will be also cleared in *flag.

We now describe the `cyg_flag_wait()` , which frequently uses the following macros:

     #define CYG_FLAG_WAITMODE_AND ((cyg_flag_mode_t)0)
     #define CYG_FLAG_WAITMODE_OR ((cyg_flag_mode_t)2)
     #define CYG_FLAG_WAITMODE_CLR ((cyg_flag_mode_t)1)

     cyg_flag_value_t cyg_flag_wait(
        cyg_flag_t *flag,
        cyg_flag_value_t pattern,
        cyg_flag_mode_t mode )

Wait for all the bits which are one in pattern to be set in the flag value (if mode is CYG_FLAG_WAITMODE_AND ) or for any of the bits which are one in pattern to be set in the flag value (if mode is CYG_FLAG_WAITMODE_OR ).

When `cyg_flag_wait()` returns, meaning that the condition is met, the flag value which succeeded is returned from the call; in other circumstances (such as a bad value for mode or pattern ), zero is returned to indicate the error.

If the mode is one of those above plus CYG_FLAG_WAITMODE_CLR, the whole of the flag value is cleared to zero when the condition is met.

`cyg_flag_wait()` takes the following parameters:

flag

The value of the flag (set by the thread that called `cyg_flag_setbits()` or `cyg_flag_maskbits()` ) is placed in here.

pattern

The set of bits which, if set, will cause the calling thread to be woken up.

mode

A parameter which modifies the conditions for wake-up. It can take the following values:

CYG_FLAG_WAITMODE_AND

Only wake up if all the bits in mask is set in the flag.

CYG_FLAG_WAITMODE_OR

Wake up if any of the bits in mask is set in the flag.

CYG_FLAG_WAITMODE_AND + CYG_FLAG_WAITMODE_CLR,

CYG_FLAG_WAITMODE_OR + CYG_FLAG_WAITMODE_CLR

Like CYG_FLAG_WAITMODE_AND and CYG_FLAG_WAITMODE_OR, but the entire flag is cleared to zero when the condition is met, whereas normally only the bits that are set in pattern would be cleared.

Waiting threads are queued depending on the semantics of the underlying scheduler. In release 1.3.x, this means that, if the multi-level queue scheduler is selected, queueing is in FIFO ordering, while the bitmap scheduler supports thread priority ordered queueing. When some flag value bits become signalled by a call to `cyg_flag_setbits()` , the queue is scanned in order, and each waiting thread in turn is awoken or re-queued depending on its request. When a thread is awoken, if it made the wait call with CYG_FLAG_WAITMODE_CLR, the flag value is cleared to zero, and the scan of queued threads is terminated.

    cyg_flag_value_t cyg_flag_timed_wait(
        cyg_flag_t *flag,
        cyg_flag_value_t pattern,
        cyg_flag_mode_t mode,
        cyg_tick_count_t abstime )

A time-out version of `cyg_flag_wait()` . This waits for the condition required by pattern and mode to be met, or until the abstime time-out is reached, whichever is first. If the time-out is reached first, zero is returned. This call is only available if the configuration option CYGFUN_KERNEL_THREADS_TIMER is enabled.

    cyg_flag_value_t cyg_flag_poll(
        cyg_flag_t *flag,
        cyg_flag_value_t pattern,
        cyg_flag_mode_t mode )

A non-blocking version of `cyg_flag_wait()` . If the condition required by pattern and mode is met, the flag value is returned, otherwise zero is returned. The flag value may be cleared in the event of success by specifying CYG_FLAG_WAITMODE_CLR in the mode, as usual.

    cyg_flag_value_t cyg_flag_peek(
        cyg_flag_t *flag )

Returns the current flag value.

    cyg_bool_t cyg_flag_waiting(
        cyg_flag_t *flag )

Returns true if there are threads waiting on this flag.

Native kernel C language API
To Contents | To previous page | To next page