Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pool_queue_exports.h Source File

pool_queue_exports.h

00001 /*
00002  * Copyright (c) 2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #ifndef UVISOR_POOL_QUEUE_EXPORTS_H
00018 #define UVISOR_POOL_QUEUE_EXPORTS_H
00019 
00020 #include "api/inc/magic_exports.h"
00021 #include "api/inc/uvisor_exports.h"
00022 #include "api/inc/uvisor_spinlock_exports.h"
00023 #include <stdint.h>
00024 #include <stddef.h>
00025 
00026 #define UVISOR_POOL_QUEUE_NON_BLOCKING (0)
00027 #define UVISOR_POOL_QUEUE_BLOCKING (1)
00028 
00029 #define UVISOR_POOL_SLOT_INVALID     ((uint8_t) 0xFFU)
00030 #define UVISOR_POOL_SLOT_IS_DEQUEUED ((uint8_t) 0xFEU)
00031 #define UVISOR_POOL_SLOT_IS_FREE     ((uint8_t) 0xFDU)
00032 #define UVISOR_POOL_MAX_VALID        ((uint8_t) 0xFCU)
00033 
00034 typedef uint8_t uvisor_pool_slot_t;
00035 
00036 typedef struct uvisor_pool_queue_entry {
00037     union {
00038         struct {
00039             /* The next slot in the queue */
00040             uvisor_pool_slot_t next;
00041 
00042             /* The previous slot in the queue */
00043             uvisor_pool_slot_t prev;
00044         } queued;
00045         struct {
00046             /* If the slot is free, the next available slot in the free list */
00047             uvisor_pool_slot_t next;
00048 
00049             /* If the slot is free or dequeued */
00050             uvisor_pool_slot_t state;
00051         } dequeued;
00052     };
00053 } uvisor_pool_queue_entry_t;
00054 
00055 /* These are assumed to only be statically allocated, so the management array
00056  * in in-place. */
00057 typedef struct uvisor_pool {
00058     /* Magic that identifies this as a uvisor_pool type. */
00059     uint32_t magic;
00060 
00061     /* The array holds slots of data. */
00062     void const * array;
00063 
00064     /* The distance between elements in the array. */
00065     size_t stride;
00066 
00067     /* The maximum number of elements that could be in the array. */
00068     uvisor_pool_slot_t num;
00069 
00070     /* The number of items currently allocated from the pool. For testing and
00071      * debug purposes only. */
00072     uvisor_pool_slot_t num_allocated;
00073 
00074     /* The first free slot. */
00075     uvisor_pool_slot_t first_free;
00076 
00077     /* The spinlock serializes updates to the management array. */
00078     UvisorSpinlock spinlock;
00079 
00080     /* This must be at the end so we can allocate memory for pools by
00081      * allocating enough room for the size of the pool appended by an array of
00082      * entries. */
00083     uvisor_pool_queue_entry_t management_array[];
00084 } uvisor_pool_t;
00085 
00086 typedef struct uvisor_pool_queue {
00087     /* Magic that identifies this as a uvisor_pool_queue type. */
00088     uint32_t magic;
00089 
00090     /* The first allocated slot */
00091     uvisor_pool_slot_t head;
00092 
00093     /* The last allocated slot */
00094     uvisor_pool_slot_t tail;
00095 
00096     uvisor_pool_t * pool;
00097 } uvisor_pool_queue_t;
00098 
00099 /* Intialize a pool.
00100  * Return 0 on success, non-zero otherwise. */
00101 UVISOR_EXTERN int uvisor_pool_init(uvisor_pool_t * pool, void * array, size_t stride, size_t num);
00102 
00103 /* Initialize a pool queue.
00104  * Return 0 on success, non-zero otherwise. */
00105 UVISOR_EXTERN int uvisor_pool_queue_init(uvisor_pool_queue_t * pool_queue, uvisor_pool_t * pool, void * array, size_t stride, size_t num);
00106 
00107 /* Allocate a slot from the pool. This doesn't put anything in the slot for
00108  * you. It's up to you to do that. Return the index of the allocated slot, or
00109  * UVISOR_POOL_SLOT_INVALID if there is no available slot. This function will
00110  * spin until the spin lock serializing access to the pool can be taken. */
00111 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_allocate(uvisor_pool_t * pool);
00112 /* Attempt to allocate a slot. This function will fail if the spin lock
00113  * serializing access to the pool can not be taken. */
00114 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_try_allocate(uvisor_pool_t * pool);
00115 
00116 /* Enqueue the specified slot into the queue. */
00117 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_enqueue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot);
00118 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_try_enqueue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot);
00119 
00120 /* Free the specified slot back into the pool. Invalid slots are ignored.
00121  * Return the slot that was freed, or UVISOR_POOL_SLOT_IS_FREE if the slot was
00122  * already freed, or UVISOR_POOL_SLOT_INVALID if the slot being requested to
00123  * free is outside the range of the queue. */
00124 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_free(uvisor_pool_t * pool, uvisor_pool_slot_t slot);
00125 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_try_free(uvisor_pool_t * pool, uvisor_pool_slot_t slot);
00126 
00127 /* Remove the specified slot from the queue. This function does not free the
00128  * specified slot back into the pool. Return the slot that was dequeued, or
00129  * UVISOR_POOL_SLOT_IS_DEQUEUED if the slot was already dequeued, or
00130  * UVISOR_POOL_SLOT_INVALID if the slot being requested to dequeue is outside
00131  * the range of the queue. */
00132 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_try_dequeue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot);
00133 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_dequeue(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot);
00134 
00135 /* Remove the first slot from the queue. This function does not free the
00136  * specified slot back into the pool. Return the slot that was dequeued or
00137  * UVISOR_POOL_SLOT_INVALID if the slot being requested to dequeue is outside
00138  * the range of the queue. */
00139 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_dequeue_first(uvisor_pool_queue_t * pool_queue);
00140 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_try_dequeue_first(uvisor_pool_queue_t * pool_queue);
00141 
00142 /* Find the first (in queue order) slot that the supplied query function
00143  * returns non-zero for. The query function is provided with `context` on every
00144  * invocation. This allows query functions to access additional data without
00145  * having to use global variables. `uvisor_pool_queue_find_first` is reentrant. */
00146 typedef int (*TQueryFN_Ptr)(uvisor_pool_slot_t slot, void * context);
00147 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_try_find_first(uvisor_pool_queue_t * pool_queue,
00148                                                                   TQueryFN_Ptr query_fn, void * context);
00149 UVISOR_EXTERN uvisor_pool_slot_t uvisor_pool_queue_find_first(uvisor_pool_queue_t * pool_queue,
00150                                                               TQueryFN_Ptr query_fn, void * context);
00151 
00152 /* Inline helper function to make allocating slots for pool queues easier and
00153  * better encapsulated (clients don't need to pull the pool out of the pool
00154  * queue, or even realize pool_queue is implemented with a pool) */
00155 static inline uvisor_pool_slot_t uvisor_pool_queue_allocate(uvisor_pool_queue_t * pool_queue)
00156 {
00157     return uvisor_pool_allocate(pool_queue->pool);
00158 }
00159 
00160 static inline uvisor_pool_slot_t uvisor_pool_queue_try_allocate(uvisor_pool_queue_t * pool_queue)
00161 {
00162     return uvisor_pool_try_allocate(pool_queue->pool);
00163 }
00164 
00165 /* Inline helper function to make freeing slots for pool queues easier and
00166  * better encapsulated (clients don't need to pull the pool out of the pool
00167  * queue, or even realize pool_queue is implemented with a pool) */
00168 static inline uvisor_pool_slot_t uvisor_pool_queue_free(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot)
00169 {
00170     return uvisor_pool_free(pool_queue->pool, slot);
00171 }
00172 
00173 static inline uvisor_pool_slot_t uvisor_pool_queue_try_free(uvisor_pool_queue_t * pool_queue, uvisor_pool_slot_t slot)
00174 {
00175     return uvisor_pool_try_free(pool_queue->pool, slot);
00176 }
00177 
00178 /* Return a pointer to the specified slot within the pool. */
00179 static inline void * uvisor_pool_pointer_to(uvisor_pool_t * pool, uvisor_pool_slot_t slot)
00180 {
00181     if (slot >= pool->num) {
00182         return NULL;
00183     }
00184     return (uint8_t *) pool->array + pool->stride * slot;
00185 }
00186 
00187 #endif