1 /* 2 * Copyright (c) 2008 Travis Geiselbrecht 3 * Copyright (c) 2019 Google, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files 7 * (the "Software"), to deal in the Software without restriction, 8 * including without limitation the rights to use, copy, modify, merge, 9 * publish, distribute, sublicense, and/or sell copies of the Software, 10 * and to permit persons to whom the Software is furnished to do so, 11 * subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 #pragma once 25 26 #include <lk/compiler.h> 27 #include <lk/list.h> 28 #include <kernel/thread.h> 29 #include <sys/types.h> 30 31 __BEGIN_CDECLS 32 33 struct dpc; 34 35 /** 36 * typedef dpc_callback - DPC callback routine 37 * @work: pointer to &struct dpc item for which this callback routine 38 * is invoked. 39 * 40 * It is expected that &struct dpc item specified by @work parameter 41 * is embedded into a caller specific structure and the caller will be 42 * using the containerof macro to recover the outer structure. 43 * 44 * Return: none 45 */ 46 typedef void (*dpc_callback)(struct dpc* work); 47 48 /** 49 * struct dpc_queue - opaque DPC queue tracking structure 50 */ 51 struct dpc_queue; 52 53 /** 54 * struct dpc - DPC work item tracking structure 55 * @node: tracking list node 56 * @cb: pointer to callback routine to invoke 57 * @q: pointer to DPC queue if DPC item is queued 58 */ 59 struct dpc { 60 /* private: internal use only */ 61 struct list_node node; 62 dpc_callback cb; 63 struct dpc_queue* q; 64 }; 65 66 /** 67 * dpc_work_init() - initialize specified DPC work item 68 * @work: pointer to &struct dpc to initialize 69 * @cb: callback to invoke 70 * @flags: reserved must be 0 71 * 72 * Return: none 73 */ 74 void dpc_work_init(struct dpc* work, dpc_callback cb, uint32_t flags); 75 76 /** 77 * dpc_enqueue_work(): enqueue DPC work to run on specified DPC queue 78 * @q: DPC queue to run DPC work specified by @work parameter. If @q is NULL 79 * the work will be enqueued in the default DPC queue. 80 * @work: DPC work to enqueue on DPC queue specified by @q parameter 81 * @resched: directly passed to underlying event_signal() call. (See the 82 * description of event_signal() call for more details). 83 * 84 * Note 1: It is guaranteed that after each invocation of dpc_enqueue_work() 85 * routine the corresponding DPC work item will be processed at least once. 86 * 87 * Note 2: A DPC work item may be re-enqueued the same DPC work queue it is 88 * already in. This is a no op. 89 * 90 * Note 3: The work item is removed from the DPC queue before the callback is 91 * invoked. It is safe to re-enqueue DPC work item inside its own callback. 92 * 93 * Note 4: If DPC work item is enqueued again after it has been removed from 94 * the queue but before callback is invoked or while callback is running it is 95 * guaranteed that DPC work item will be processed again in the future. 96 * 97 * Note 5: An initialized DPC work item can only be enqueued in one queue. 98 * An item needs to be initialized again in order to be enqueued in another 99 * queue. 100 * 101 * Note 6: The only time when it is safe to free or reinitialize a DPC work 102 * item is when it is not queued, for example, from DPC callback itself. 103 * 104 * Note 7: The @resched parameter must be false if invoked from interrupt 105 * context. 106 * 107 * return value: 0 on success 108 */ 109 int dpc_enqueue_work(struct dpc_queue* q, struct dpc* work, bool resched); 110 111 /** 112 * dpc_queue_create(): initialize and start a DPC queue 113 * @pq: Pointer to be filled with a pointer to the new queue structure 114 * @name: DPC queue name 115 * @thread_priority: a priority of DPC queue handling thread 116 * @thread_stack_size: stack size of DPC queue handling thread 117 * DEFAULT_STACK_SIZE is a reasonable default value here. 118 * 119 * Return: NO_ERROR on success, a negative error code otherwise 120 */ 121 status_t dpc_queue_create(struct dpc_queue** pq, 122 const char* name, 123 int thread_priority, 124 size_t thread_stack_size); 125 126 __END_CDECLS 127