.. _lifos_v2: Lifos ##### A :dfn:`lifo` is a kernel object that implements a traditional last in, first out (LIFO) queue, allowing threads and ISRs to add and remove data items of any size. .. contents:: :local: :depth: 2 Concepts ******** Any number of lifos can be defined. Each lifo is referenced by its memory address. A lifo has the following key properties: * A **queue** of data items that have been added but not yet removed. The queue is implemented as a simple linked list. A lifo must be initialized before it can be used. This sets its queue to empty. Lifo data items must be aligned on a 4-byte boundary, as the kernel reserves the first 32 bits of an item for use as a pointer to the next data item in the queue. Consequently, a data item that holds N bytes of application data requires N+4 bytes of memory. A data item may be **added** to a lifo by a thread or an ISR. The item is given directly to a waiting thread, if one exists; otherwise the item is added to the lifo's queue. There is no limit to the number of items that may be queued. A data item may be **removed** from a lifo by a thread. If the lifo's queue is empty a thread may choose to wait for a data item to be given. Any number of threads may wait on an empty lifo simultaneously. When a data item is added, it is given to the highest priority thread that has waited longest. .. note:: The kernel does allow an ISR to remove an item from a lifo, however the ISR must not attempt to wait if the lifo is empty. Implementation ************** Defining a Lifo =============== A lifo is defined using a variable of type :c:type:`struct k_lifo`. It must then be initialized by calling :cpp:func:`k_lifo_init()`. The following defines and initializes an empty lifo. .. code-block:: c struct k_lifo my_lifo; k_lifo_init(&my_lifo); Alternatively, an empty lifo can be defined and initialized at compile time by calling :c:macro:`K_LIFO_DEFINE`. The following code has the same effect as the code segment above. .. code-block:: c K_LIFO_DEFINE(my_lifo); Writing to a Lifo ================= A data item is added to a lifo by calling :cpp:func:`k_lifo_put()`. The following code builds on the example above, and uses the lifo to send data to one or more consumer threads. .. code-block:: c struct data_item_t { void *lifo_reserved; /* 1st word reserved for use by lifo */ ... }; struct data_item_t tx data; void producer_thread(int unused1, int unused2, int unused3) { while (1) { /* create data item to send */ tx_data = ... /* send data to consumers */ k_lifo_put(&my_lifo, &tx_data); ... } } Reading from a Lifo =================== A data item is removed from a lifo by calling :cpp:func:`k_lifo_get()`. The following code builds on the example above, and uses the lifo to obtain data items from a producer thread, which are then processed in some manner. .. code-block:: c void consumer_thread(int unused1, int unused2, int unused3) { struct data_item_t *rx_data; while (1) { rx_data = k_lifo_get(&my_lifo, K_FOREVER); /* process lifo data item */ ... } } Suggested Uses ************** Use a lifo to asynchronously transfer data items of arbitrary size in a "last in, first out" manner. Configuration Options ********************* Related configuration options: * None. APIs **** The following lifo APIs are provided by :file:`kernel.h`: * :c:macro:`K_LIFO_DEFINE` * :cpp:func:`k_lifo_init()` * :cpp:func:`k_lifo_put()` * :cpp:func:`k_lifo_get()`