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