ReactOS 0.4.17-dev-1190-g4c812f4
notify.c
Go to the documentation of this file.
8#include <uacpi/kernel_api.h>
10
11#ifndef UACPI_BAREBONES_MODE
12
14
16{
20
21 return UACPI_STATUS_OK;
22}
23
25{
28
30}
31
37};
38
40{
43
44 /*
45 * This is the work item that we're being executed as. Nobody is supposed
46 * to be looking at it anymore now that the handler was invoked.
47 */
49
50 uacpi_free(ctx, sizeof(*ctx));
51}
52
53/*
54 * The handler lists are only modified with the notify mutex held, but are
55 * walked by do_notify without it: a handler is allowed to install another
56 * handler, which is not something that it would be able to do otherwise.
57 *
58 * This is safe because a handler is fully initialized before it's linked in,
59 * and because an unlinked handler is only freed after all of the in-flight
60 * notifications that might still be looking at it have finished.
61 */
64)
65{
67}
68
69static void do_notify(uacpi_handle opaque)
70{
71 struct notification_ctx *ctx = opaque;
73 uacpi_bool did_notify_root = UACPI_FALSE;
74
75 handler = load_handler(&ctx->node_object->handlers->notify_head);
76
77 for (;;) {
78 if (handler == UACPI_NULL) {
79 if (did_notify_root) {
81 return;
82 }
83
85 &g_uacpi_rt_ctx.root_object->handlers->notify_head
86 );
87 did_notify_root = UACPI_TRUE;
88 continue;
89 }
90
91 handler->callback(handler->user_context, ctx->node, ctx->value);
93 }
94}
95
97{
99 struct notification_ctx *ctx;
101
105 );
108
111 return ret;
112
114 g_uacpi_rt_ctx.root_object->handlers->notify_head == UACPI_NULL) {
116 goto error_out;
117 }
118
119 ctx = uacpi_kernel_alloc(sizeof(*ctx));
120 if (uacpi_unlikely(ctx == UACPI_NULL)) {
122 goto error_out;
123 }
124
125 ctx->work_item = uacpi_kernel_create_work_item();
126 if (uacpi_unlikely(ctx->work_item == UACPI_NULL)) {
127 uacpi_free(ctx, sizeof(*ctx));
129 goto error_out;
130 }
131
132 ctx->node = node;
133 // In case this node goes out of scope
135
136 ctx->value = value;
138 uacpi_object_ref(ctx->node_object);
139
140 /*
141 * Nothing prevents the kernel from executing the work synchronously, e.g.
142 * because it sees no reason to defer it if it's not in an interrupt
143 * context. The handlers are free to call back into uACPI, be it to
144 * evaluate an object or to install another handler, so make sure that
145 * we're not holding onto anything that they might need. This includes the
146 * namespace, which is locked by whoever is sending the notification.
147 *
148 * Everything that the work needs is referenced by now, and there's nothing
149 * left for us to do after it's scheduled.
150 */
153
156 );
157
159 return UACPI_STATUS_OK;
160
161error_out:
163 return ret;
164}
165
168)
169{
171
172 while (handler) {
173 if (handler->callback == target_handler)
174 return handler;
175
176 handler = handler->next;
177 }
178
179 return UACPI_NULL;
180}
181
184 uacpi_handle handler_context
185)
186{
190 uacpi_device_notify_handler *new_handler;
191
193
194 if (node == uacpi_namespace_root()) {
195 obj = g_uacpi_rt_ctx.root_object;
196 } else {
200 );
202 return ret;
203 }
204
207 goto out_no_mutex;
208
209 handlers = obj->handlers;
210
213 goto out;
214 }
215
216 new_handler = uacpi_kernel_alloc_zeroed(sizeof(*new_handler));
217 if (uacpi_unlikely(new_handler == UACPI_NULL)) {
219 goto out;
220 }
221
222 new_handler->callback = handler;
223 new_handler->user_context = handler_context;
224 new_handler->next = handlers->notify_head;
225
226 uacpi_atomic_store_ptr(&handlers->notify_head, new_handler);
227
228out:
230out_no_mutex:
231 if (node != uacpi_namespace_root())
233
234 return ret;
235}
236
239)
240{
244 uacpi_device_notify_handler *prev_handler, *containing = UACPI_NULL;
245
247
248 if (node == uacpi_namespace_root()) {
249 obj = g_uacpi_rt_ctx.root_object;
250 } else {
254 );
256 return ret;
257 }
258
261 goto out_no_mutex;
262
263 handlers = obj->handlers;
264
265 containing = handler_container(handlers, handler);
266 if (containing == UACPI_NULL) {
268 goto out;
269 }
270
271 prev_handler = handlers->notify_head;
272
273 // Are we the last linked handler?
274 if (prev_handler == containing) {
275 uacpi_atomic_store_ptr(&handlers->notify_head, containing->next);
276 goto out;
277 }
278
279 // Nope, we're somewhere in the middle. Do a search.
280 while (prev_handler) {
281 if (prev_handler->next == containing) {
282 uacpi_atomic_store_ptr(&prev_handler->next, containing->next);
283 goto out;
284 }
285
286 prev_handler = prev_handler->next;
287 }
288
289out:
291out_no_mutex:
292 if (node != uacpi_namespace_root())
294
296 /*
297 * The handler is no longer reachable, but a notification that started
298 * before we unlinked it might still be about to call it. Wait for
299 * those to finish, this also guarantees that the handler is never
300 * invoked again after we return.
301 *
302 * This must be done without the notify mutex held: the work that we
303 * are waiting for needs it in order to dispatch a Notify().
304 */
306 uacpi_free(containing, sizeof(*containing));
307 }
308
309 return ret;
310}
311
312#endif // !UACPI_BAREBONES_MODE
static uacpi_status uacpi_release_native_mutex(uacpi_handle mtx)
Definition: mutex.h:44
static void uacpi_free_native_mutex(uacpi_handle mtx)
Definition: mutex.h:27
static uacpi_status uacpi_acquire_native_mutex(uacpi_handle mtx)
Definition: mutex.h:32
static uacpi_handle uacpi_create_native_mutex(void)
Definition: mutex.h:22
#define uacpi_atomic_store_ptr(ptr_to_ptr, value)
Definition: atomic.h:344
#define uacpi_atomic_load_ptr(ptr_to_ptr)
Definition: atomic.h:343
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7708
#define UACPI_ENSURE_INIT_LEVEL_AT_LEAST(lvl)
Definition: context.h:127
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:18
void uacpi_namespace_node_unref(uacpi_namespace_node *node)
Definition: namespace.c:294
uacpi_status uacpi_namespace_write_unlock(void)
Definition: namespace.c:51
uacpi_object * uacpi_namespace_node_get_object_typed(const uacpi_namespace_node *node, uacpi_object_type_bits type_mask)
Definition: namespace.c:661
uacpi_object * uacpi_namespace_node_get_object(const uacpi_namespace_node *node)
Definition: namespace.c:653
uacpi_status uacpi_namespace_node_release_object(uacpi_object *obj)
Definition: namespace.c:754
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:46
uacpi_status uacpi_namespace_node_acquire_object_typed(const uacpi_namespace_node *node, uacpi_object_type_bits, uacpi_object **out_obj)
Definition: namespace.c:677
#define uacpi_kernel_alloc_zeroed
Definition: stdlib.h:127
#define uacpi_free(mem, _)
Definition: stdlib.h:96
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:264
#define uacpi_unlikely(expr)
Definition: compiler.h:88
bool uacpi_bool
Definition: types.h:31
#define UACPI_FALSE
Definition: types.h:30
uint64_t uacpi_u64
Definition: types.h:22
#define UACPI_NULL
Definition: types.h:33
#define UACPI_TRUE
Definition: types.h:29
#define uacpi_likely_success(expr)
Definition: status.h:54
#define uacpi_unlikely_error(expr)
Definition: status.h:50
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_NOT_FOUND
Definition: status.h:17
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_STATUS_ALREADY_EXISTS
Definition: status.h:20
@ UACPI_STATUS_OK
Definition: status.h:11
@ UACPI_STATUS_NO_HANDLER
Definition: status.h:25
void uacpi_object_ref(uacpi_object *obj)
Definition: types.c:733
uacpi_status(* uacpi_notify_handler)(uacpi_handle context, uacpi_namespace_node *node, uacpi_u64 value)
Definition: types.h:524
@ UACPI_OBJECT_PROCESSOR_BIT
Definition: types.h:146
@ UACPI_OBJECT_THERMAL_ZONE_BIT
Definition: types.h:147
@ UACPI_OBJECT_DEVICE_BIT
Definition: types.h:140
@ UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED
Definition: types.h:72
void uacpi_object_unref(uacpi_object *obj)
Definition: types.c:761
return ret
Definition: mutex.c:147
static void do_notify(uacpi_handle opaque)
Definition: notify.c:69
static uacpi_device_notify_handler * handler_container(uacpi_handlers *handlers, uacpi_notify_handler target_handler)
Definition: notify.c:166
uacpi_status uacpi_uninstall_notify_handler(uacpi_namespace_node *node, uacpi_notify_handler handler)
Definition: notify.c:237
static void free_notification_ctx(struct notification_ctx *ctx)
Definition: notify.c:39
void uacpi_deinitialize_notify(void)
Definition: notify.c:24
uacpi_status uacpi_install_notify_handler(uacpi_namespace_node *node, uacpi_notify_handler handler, uacpi_handle handler_context)
Definition: notify.c:182
uacpi_status uacpi_initialize_notify(void)
Definition: notify.c:15
static uacpi_device_notify_handler * load_handler(uacpi_device_notify_handler **handler)
Definition: notify.c:62
static uacpi_handle notify_mutex
Definition: notify.c:13
uacpi_status uacpi_notify_all(uacpi_namespace_node *node, uacpi_u64 value)
Definition: notify.c:96
static xmlCharEncodingHandlerPtr * handlers
Definition: encoding.c:1380
void * uacpi_kernel_alloc(uacpi_size size)
Definition: uacpiosl.c:111
uacpi_status uacpi_kernel_wait_for_work_completion(void)
Definition: uacpiosl.c:235
void uacpi_kernel_schedule_work(uacpi_work_type, uacpi_handle work_item, uacpi_work_handler handler, uacpi_handle ctx)
@ UACPI_WORK_NOTIFICATION
Definition: kernel_api.h:367
uacpi_handle uacpi_kernel_create_work_item(void)
void uacpi_kernel_free_work_item(uacpi_handle)
static uacpi_u32 uacpi_shareable_ref(uacpi_handle handle)
Definition: shareable.h:40
uacpi_namespace_node * node
Definition: notify.c:33
uacpi_handle work_item
Definition: notify.c:36
uacpi_u64 value
Definition: notify.c:34
uacpi_object * node_object
Definition: notify.c:35
struct uacpi_device_notify_handler * next
Definition: types.h:95
uacpi_notify_handler callback
Definition: types.h:93
uacpi_handle user_context
Definition: types.h:94
uacpi_device_notify_handler * notify_head
Definition: types.h:107
uacpi_handlers * handlers
Definition: types.h:277
Definition: dlist.c:348
Definition: pdh_main.c:64
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383