/* * Copyright (c) 2008 Travis Geiselbrecht * Copyright (c) 2019 Google, Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include #include #include #include __BEGIN_CDECLS struct dpc; /** * typedef dpc_callback - DPC callback routine * @work: pointer to &struct dpc item for which this callback routine * is invoked. * * It is expected that &struct dpc item specified by @work parameter * is embedded into a caller specific structure and the caller will be * using the containerof macro to recover the outer structure. * * Return: none */ typedef void (*dpc_callback)(struct dpc* work); /** * struct dpc_queue - opaque DPC queue tracking structure */ struct dpc_queue; /** * struct dpc - DPC work item tracking structure * @node: tracking list node * @cb: pointer to callback routine to invoke * @q: pointer to DPC queue if DPC item is queued */ struct dpc { /* private: internal use only */ struct list_node node; dpc_callback cb; struct dpc_queue* q; }; /** * dpc_work_init() - initialize specified DPC work item * @work: pointer to &struct dpc to initialize * @cb: callback to invoke * @flags: reserved must be 0 * * Return: none */ void dpc_work_init(struct dpc* work, dpc_callback cb, uint32_t flags); /** * dpc_enqueue_work(): enqueue DPC work to run on specified DPC queue * @q: DPC queue to run DPC work specified by @work parameter. If @q is NULL * the work will be enqueued in the default DPC queue. * @work: DPC work to enqueue on DPC queue specified by @q parameter * @resched: directly passed to underlying event_signal() call. (See the * description of event_signal() call for more details). * * Note 1: It is guaranteed that after each invocation of dpc_enqueue_work() * routine the corresponding DPC work item will be processed at least once. * * Note 2: A DPC work item may be re-enqueued the same DPC work queue it is * already in. This is a no op. * * Note 3: The work item is removed from the DPC queue before the callback is * invoked. It is safe to re-enqueue DPC work item inside its own callback. * * Note 4: If DPC work item is enqueued again after it has been removed from * the queue but before callback is invoked or while callback is running it is * guaranteed that DPC work item will be processed again in the future. * * Note 5: An initialized DPC work item can only be enqueued in one queue. * An item needs to be initialized again in order to be enqueued in another * queue. * * Note 6: The only time when it is safe to free or reinitialize a DPC work * item is when it is not queued, for example, from DPC callback itself. * * Note 7: The @resched parameter must be false if invoked from interrupt * context. * * return value: 0 on success */ int dpc_enqueue_work(struct dpc_queue* q, struct dpc* work, bool resched); /** * dpc_queue_create(): initialize and start a DPC queue * @pq: Pointer to be filled with a pointer to the new queue structure * @name: DPC queue name * @thread_priority: a priority of DPC queue handling thread * @thread_stack_size: stack size of DPC queue handling thread * DEFAULT_STACK_SIZE is a reasonable default value here. * * Return: NO_ERROR on success, a negative error code otherwise */ status_t dpc_queue_create(struct dpc_queue** pq, const char* name, int thread_priority, size_t thread_stack_size); __END_CDECLS