ReactOS 0.4.17-dev-1190-g4c812f4
notify.c File Reference
Include dependency graph for notify.c:

Go to the source code of this file.

Classes

struct  notification_ctx
 

Functions

uacpi_status uacpi_initialize_notify (void)
 
void uacpi_deinitialize_notify (void)
 
static void free_notification_ctx (struct notification_ctx *ctx)
 
static uacpi_device_notify_handler * load_handler (uacpi_device_notify_handler **handler)
 
static void do_notify (uacpi_handle opaque)
 
uacpi_status uacpi_notify_all (uacpi_namespace_node *node, uacpi_u64 value)
 
static uacpi_device_notify_handler * handler_container (uacpi_handlers *handlers, uacpi_notify_handler target_handler)
 
uacpi_status uacpi_install_notify_handler (uacpi_namespace_node *node, uacpi_notify_handler handler, uacpi_handle handler_context)
 
uacpi_status uacpi_uninstall_notify_handler (uacpi_namespace_node *node, uacpi_notify_handler handler)
 

Variables

static uacpi_handle notify_mutex
 

Function Documentation

◆ do_notify()

static void do_notify ( uacpi_handle  opaque)
static

Definition at line 69 of file notify.c.

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}
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7708
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:18
bool uacpi_bool
Definition: types.h:31
#define UACPI_FALSE
Definition: types.h:30
#define UACPI_NULL
Definition: types.h:33
#define UACPI_TRUE
Definition: types.h:29
static void free_notification_ctx(struct notification_ctx *ctx)
Definition: notify.c:39
static uacpi_device_notify_handler * load_handler(uacpi_device_notify_handler **handler)
Definition: notify.c:62

Referenced by uacpi_notify_all().

◆ free_notification_ctx()

static void free_notification_ctx ( struct notification_ctx *  ctx)
static

Definition at line 39 of file notify.c.

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}
void uacpi_namespace_node_unref(uacpi_namespace_node *node)
Definition: namespace.c:294
uacpi_status uacpi_namespace_node_release_object(uacpi_object *obj)
Definition: namespace.c:754
#define uacpi_free(mem, _)
Definition: stdlib.h:96
void uacpi_kernel_free_work_item(uacpi_handle)

Referenced by do_notify().

◆ handler_container()

static uacpi_device_notify_handler * handler_container ( uacpi_handlers *  handlers,
uacpi_notify_handler  target_handler 
)
static

Definition at line 166 of file notify.c.

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}
static xmlCharEncodingHandlerPtr * handlers
Definition: encoding.c:1380

Referenced by uacpi_install_notify_handler(), and uacpi_uninstall_notify_handler().

◆ load_handler()

static uacpi_device_notify_handler * load_handler ( uacpi_device_notify_handler **  handler)
static

Definition at line 62 of file notify.c.

65{
67}
#define uacpi_atomic_load_ptr(ptr_to_ptr)
Definition: atomic.h:343

Referenced by do_notify().

◆ uacpi_deinitialize_notify()

void uacpi_deinitialize_notify ( void  )

Definition at line 24 of file notify.c.

25{
28
30}
static void uacpi_free_native_mutex(uacpi_handle mtx)
Definition: mutex.h:27
static uacpi_handle notify_mutex
Definition: notify.c:13

Referenced by uacpi_state_reset().

◆ uacpi_initialize_notify()

uacpi_status uacpi_initialize_notify ( void  )

Definition at line 15 of file notify.c.

16{
20
21 return UACPI_STATUS_OK;
22}
static uacpi_handle uacpi_create_native_mutex(void)
Definition: mutex.h:22
#define uacpi_unlikely(expr)
Definition: compiler.h:88
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_STATUS_OK
Definition: status.h:11

Referenced by uacpi_initialize().

◆ uacpi_install_notify_handler()

uacpi_status uacpi_install_notify_handler ( uacpi_namespace_node *  node,
uacpi_notify_handler  handler,
uacpi_handle  handler_context 
)

Install a Notify() handler to a device node. A handler installed to the root node will receive all notifications, even if a device already has a dedicated Notify handler. 'handler_context' is passed to the handler on every invocation.

Definition at line 182 of file notify.c.

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}
static uacpi_status uacpi_release_native_mutex(uacpi_handle mtx)
Definition: mutex.h:44
static uacpi_status uacpi_acquire_native_mutex(uacpi_handle mtx)
Definition: mutex.h:32
#define uacpi_atomic_store_ptr(ptr_to_ptr, value)
Definition: atomic.h:344
#define UACPI_ENSURE_INIT_LEVEL_AT_LEAST(lvl)
Definition: context.h:127
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
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:264
#define uacpi_unlikely_error(expr)
Definition: status.h:50
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_ALREADY_EXISTS
Definition: status.h:20
@ 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 uacpi_device_notify_handler * handler_container(uacpi_handlers *handlers, uacpi_notify_handler target_handler)
Definition: notify.c:166
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
Definition: dlist.c:348
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383

◆ uacpi_notify_all()

uacpi_status uacpi_notify_all ( uacpi_namespace_node *  node,
uacpi_u64  value 
)

Definition at line 96 of file notify.c.

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}
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_write_lock(void)
Definition: namespace.c:46
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_NO_HANDLER
Definition: status.h:25
void uacpi_object_ref(uacpi_object *obj)
Definition: types.c:733
static void do_notify(uacpi_handle opaque)
Definition: notify.c:69
void * uacpi_kernel_alloc(uacpi_size size)
Definition: uacpiosl.c:111
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)
static uacpi_u32 uacpi_shareable_ref(uacpi_handle handle)
Definition: shareable.h:40
uacpi_namespace_node * node
Definition: notify.c:33
uacpi_u64 value
Definition: notify.c:34
uacpi_object * node_object
Definition: notify.c:35
uacpi_device_notify_handler * notify_head
Definition: types.h:107
uacpi_handlers * handlers
Definition: types.h:277

Referenced by async_run_gpe_handler(), and handle_notify().

◆ uacpi_uninstall_notify_handler()

uacpi_status uacpi_uninstall_notify_handler ( uacpi_namespace_node *  node,
uacpi_notify_handler  handler 
)

Uninstall a Notify() handler previously installed to a device node. The handler is guaranteed to not be running, and to never be invoked again once this function returns.

NOTE: this waits for all of the in-flight notifications to complete, and therefore must not be called from a notify handler, any other work scheduled via uacpi_kernel_schedule_work, an address space handler, or with the global lock held.

Definition at line 237 of file notify.c.

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}
#define uacpi_likely_success(expr)
Definition: status.h:54
@ UACPI_STATUS_NOT_FOUND
Definition: status.h:17
uacpi_status uacpi_kernel_wait_for_work_completion(void)
Definition: uacpiosl.c:235

Variable Documentation

◆ notify_mutex