1 // Copyright 2016 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 #pragma once
7 
8 #include <kernel/thread.h>
9 #include <list.h>
10 #include <sys/types.h>
11 #include <zircon/compiler.h>
12 #include <zircon/types.h>
13 
14 __BEGIN_CDECLS
15 
16 #define DPC_THREAD_PRIORITY HIGH_PRIORITY
17 
18 struct dpc;
19 typedef void (*dpc_func_t)(struct dpc*);
20 
21 typedef struct dpc {
22     struct list_node node;
23 
24     dpc_func_t func;
25     void* arg;
26 } dpc_t;
27 
28 #define DPC_INITIAL_VALUE                   \
29     {                                       \
30         .node = LIST_INITIAL_CLEARED_VALUE, \
31         .func = 0,                          \
32         .arg = 0,                           \
33     }
34 
35 // initializes dpc for the current cpu
36 void dpc_init_for_cpu(void);
37 
38 // queue an already filled out dpc, optionally reschedule immediately to run the dpc thread.
39 // the deferred procedure runs in a dedicated thread that runs at DPC_THREAD_PRIORITY
40 zx_status_t dpc_queue(dpc_t* dpc, bool reschedule);
41 
42 // queue a dpc, but must be holding the thread lock
43 // does not force a reschedule
44 zx_status_t dpc_queue_thread_locked(dpc_t* dpc) TA_REQ(thread_lock);
45 
46 // Begins the DPC shutdown process for |cpu|.
47 //
48 // Shutting down a DPC queue is a two-phase process.  This is the first phase.  See
49 // |dpc_shutdown_transition_off_cpu| for the second phase.
50 //
51 // This function:
52 // - stops servicing the queue
53 // - waits for any in-progress DPC to complete
54 // - ensures no queued DPCs will begin executing
55 // - joins the DPC thread
56 //
57 // Upon completion, |cpu| may have unexecuted DPCs and |dpc_queue| will continue to queue new DPCs.
58 //
59 // Once |cpu| is no longer executing tasks, finish the shutdown process by calling
60 // |dpc_shutdown_transition_off_cpu|.
61 void dpc_shutdown(uint cpu);
62 
63 // Moves queued DPCs from |cpu| to the caller's CPU.
64 //
65 // This is the second phase of DPC shutdown.  See |dpc_shutdown|.
66 //
67 // Should only be called after |cpu| has stopped executing tasks.
68 void dpc_shutdown_transition_off_cpu(uint cpu);
69 
70 __END_CDECLS
71