1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <lk/debug.h>
9 #include <stddef.h>
10 #include <lk/list.h>
11 #include <malloc.h>
12 #include <lk/err.h>
13 #include <lib/dpc.h>
14 #include <kernel/thread.h>
15 #include <kernel/event.h>
16 #include <lk/init.h>
17 
18 struct dpc {
19     struct list_node node;
20 
21     dpc_callback cb;
22     void *arg;
23 };
24 
25 static struct list_node dpc_list = LIST_INITIAL_VALUE(dpc_list);
26 static event_t dpc_event;
27 
28 static int dpc_thread_routine(void *arg);
29 
dpc_queue(dpc_callback cb,void * arg,uint flags)30 status_t dpc_queue(dpc_callback cb, void *arg, uint flags) {
31     struct dpc *dpc;
32 
33     dpc = malloc(sizeof(struct dpc));
34 
35     if (dpc == NULL)
36         return ERR_NO_MEMORY;
37 
38     dpc->cb = cb;
39     dpc->arg = arg;
40     enter_critical_section();
41     list_add_tail(&dpc_list, &dpc->node);
42     event_signal(&dpc_event, (flags & DPC_FLAG_NORESCHED) ? false : true);
43     exit_critical_section();
44 
45     return NO_ERROR;
46 }
47 
dpc_thread_routine(void * arg)48 static int dpc_thread_routine(void *arg) {
49     for (;;) {
50         event_wait(&dpc_event);
51 
52         enter_critical_section();
53         struct dpc *dpc = list_remove_head_type(&dpc_list, struct dpc, node);
54         if (!dpc)
55             event_unsignal(&dpc_event);
56         exit_critical_section();
57 
58         if (dpc) {
59 //          dprintf("dpc calling %p, arg %p\n", dpc->cb, dpc->arg);
60             dpc->cb(dpc->arg);
61 
62             free(dpc);
63         }
64     }
65 
66     return 0;
67 }
68 
dpc_init(uint level)69 static void dpc_init(uint level) {
70     event_init(&dpc_event, false, 0);
71 
72     thread_detach_and_resume(thread_create("dpc", &dpc_thread_routine, NULL, DPC_PRIORITY, DEFAULT_STACK_SIZE));
73 }
74 
75 LK_INIT_HOOK(libdpc, &dpc_init, LK_INIT_LEVEL_THREADING);
76 
77 
78