Commit | Line | Data |
---|---|---|
24cedcfe MD |
1 | /* |
2 | * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) | |
3 | * | |
67a00fae MD |
4 | * wrapper around poll_get_entry, implementing __pollwait with exclusive |
5 | * wakeups. Using KALLSYMS to get poll_get_entry address when available, | |
6 | * else we need to have a kernel that exports this function to GPL | |
7 | * modules. | |
24cedcfe | 8 | * |
67a00fae | 9 | * GPL v2 license. |
24cedcfe MD |
10 | */ |
11 | ||
12 | #ifdef CONFIG_KALLSYMS | |
13 | ||
14 | #include <linux/kallsyms.h> | |
15 | #include <linux/poll.h> | |
67a00fae | 16 | #include <linux/wait.h> |
24cedcfe MD |
17 | |
18 | struct poll_table_entry; | |
19 | struct splice_pipe_desc; | |
20 | ||
21 | static | |
67a00fae | 22 | int (*pollwake_sym)(wait_queue_t *wait, unsigned mode, int sync, void *key); |
24cedcfe MD |
23 | static |
24 | struct poll_table_entry *(*poll_get_entry_sym)(struct poll_wqueues *p); | |
25 | ||
67a00fae MD |
26 | /* Add a new entry */ |
27 | static void __pollwait_exclusive(struct file *filp, | |
28 | wait_queue_head_t *wait_address, | |
29 | poll_table *p) | |
24cedcfe MD |
30 | { |
31 | struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt); | |
32 | struct poll_table_entry *entry; | |
33 | ||
34 | if (!poll_get_entry_sym) | |
35 | poll_get_entry_sym = (void *) kallsyms_lookup_name("poll_get_entry"); | |
36 | if (!poll_get_entry_sym) { | |
37 | printk(KERN_WARNING "LTTng: poll_get_entry_sym symbol lookup failed.\n"); | |
38 | return; | |
39 | } | |
24cedcfe | 40 | |
67a00fae MD |
41 | if (!pollwake_sym) |
42 | pollwake_sym = (void *) kallsyms_lookup_name("pollwake"); | |
43 | if (!pollwake_sym) { | |
44 | printk(KERN_WARNING "LTTng: pollwake_sym symbol lookup failed.\n"); | |
24cedcfe MD |
45 | return; |
46 | } | |
67a00fae MD |
47 | |
48 | entry = poll_get_entry_sym(pwq); | |
49 | ||
50 | if (!entry) | |
51 | return; | |
52 | get_file(filp); | |
53 | entry->filp = filp; | |
54 | entry->wait_address = wait_address; | |
55 | entry->key = p->key; | |
56 | init_waitqueue_func_entry(&entry->wait, pollwake_sym); | |
57 | entry->wait.private = pwq; | |
58 | add_wait_queue_exclusive(wait_address, &entry->wait); | |
59 | } | |
60 | ||
61 | void wrapper_pollwait_exclusive(struct file *filp, | |
62 | wait_queue_head_t *wait_address, | |
63 | poll_table *p) | |
64 | ||
65 | { | |
66 | __pollwait_exclusive(filp, wait_address, p); | |
24cedcfe MD |
67 | } |
68 | ||
69 | #else | |
70 | ||
71 | #include <linux/poll.h> | |
72 | ||
73 | ssize_t wrapper_pollwait_exclusive(struct file *filp, | |
74 | wait_queue_head_t *wait_address, | |
75 | poll_table *p) | |
76 | { | |
77 | return pollwait_exclusive(filp, wait_address, p); | |
78 | } | |
79 | ||
80 | #endif |