2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/init.h>
6 #include <linux/interrupt.h>
8 #include <linux/device.h>
9 #include <linux/platform_device.h>
10 #include <asm/thread_notify.h>
12 #include <linux/poll.h>
13 #include <linux/wait.h>
14 #include <linux/sched.h>
15 #include <linux/slab.h>
17 #define PMON_DEVICE "pmon"
19 struct _process_mon_data {
25 struct list_head mp_list; /* monitor process list */
26 struct list_head dp_list; /* dead process list */
27 struct work_struct pmon_work;
39 struct list_head list;
40 enum mp_entry_type type;
45 struct list_head list;
49 static struct _process_mon_data pmon_data = {
54 static DEFINE_SPINLOCK(mp_list_lock);
55 static DEFINE_SPINLOCK(dp_list_lock);
56 static DECLARE_WAIT_QUEUE_HEAD(pmon_wait);
57 static atomic_t nr_watcher_task = ATOMIC_INIT(0);
59 static int pmon_open(struct inode *inode, struct file *file)
63 /* only 1 process can do "read open" */
64 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
65 nr_read_task = atomic_read(&nr_watcher_task);
69 atomic_inc(&nr_watcher_task);
70 pmon_data.watcher_pid = get_current()->pid;
71 pr_info("add process monitor task = %d\n",
72 pmon_data.watcher_pid);
79 static int pmon_release(struct inode *inode, struct file *file)
81 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
82 atomic_dec(&nr_watcher_task);
87 static ssize_t pmon_read(struct file *file, char __user *buf, size_t count,
93 spin_lock(&dp_list_lock);
95 if (!list_empty(&pmon_data.dp_list)) {
96 dp = list_first_entry(&pmon_data.dp_list, struct dp_entry,
98 if (copy_to_user(buf, &(dp->pid), sizeof(pid_t))) {
99 spin_unlock(&dp_list_lock);
107 spin_unlock(&dp_list_lock);
112 static unsigned int pmon_poll(struct file *file, poll_table *wait)
114 unsigned int retval = 0;
115 poll_wait(file, &pmon_wait, wait);
116 spin_lock(&dp_list_lock);
117 if (!list_empty(&pmon_data.dp_list))
119 spin_unlock(&dp_list_lock);
124 static int mp_store(const char *buf, enum mp_entry_type type, size_t count)
126 struct mp_entry *new_mp;
131 pr_debug("monitor process - %d : %d\n", *pid, type);
133 spin_lock(&mp_list_lock);
134 list_for_each_entry(new_mp, &pmon_data.mp_list, list) {
135 if (new_mp->pid == *pid) {
136 pr_info("Already exist ! pid: %d\n", *pid);
141 spin_unlock(&mp_list_lock);
146 new_mp = kmalloc(sizeof(struct mp_entry), GFP_KERNEL);
152 spin_lock(&mp_list_lock);
153 list_add_tail(&new_mp->list, &pmon_data.mp_list);
154 spin_unlock(&mp_list_lock);
159 static ssize_t mp_remove(struct class *class, struct class_attribute *attr,
160 const char *buf, size_t count)
162 struct mp_entry *rm_mp, *next;
167 pid = (int)simple_strtoul(buf, NULL, 10);
169 spin_lock(&mp_list_lock);
170 list_for_each_entry_safe(rm_mp, next, &pmon_data.mp_list, list) {
171 if (rm_mp->pid == pid) {
172 list_del(&rm_mp->list);
174 pr_debug("remove the monitoring process - %d\n", pid);
179 spin_unlock(&mp_list_lock);
182 pr_info("No precess to be removed - %d\n", pid);
188 static ssize_t mp_vip_store(struct class *class, struct class_attribute *attr,
189 const char *buf, size_t count)
191 return mp_store(buf, MP_VIP, count);
194 static ssize_t mp_pnp_store(struct class *class, struct class_attribute *attr,
195 const char *buf, size_t count)
197 return mp_store(buf, MP_PERMANENT, count);
200 static void pmon_work_thread(struct work_struct *work)
202 if (pmon_data.watcher_pid)
203 wake_up_interruptible_all(&pmon_wait);
205 kobject_uevent(&pmon_data.dev->kobj, KOBJ_CHANGE);
208 static int check_pernament_process(int pid, char *tsk_name)
210 struct dp_entry *new_dp;
211 struct mp_entry *mp, *next;
213 enum mp_entry_type mtype = MP_NONE;
215 if (!pmon_data.initialized)
218 spin_lock(&mp_list_lock);
219 list_for_each_entry_safe(mp, next, &pmon_data.mp_list, list) {
220 if (mp->pid == pid) {
228 spin_unlock(&mp_list_lock);
230 if (pmon_data.watcher_pid == pid || mtype == MP_VIP) {
231 if (pmon_data.watcher_pid == pid)
232 pr_info("<<< process monitor process dead: %d (%s)\n",
235 pr_info("<<< VIP process dead: %d (%s)>>>\n", pid,
237 pmon_data.watcher_pid = 0;
238 schedule_work(&pmon_data.pmon_work);
243 new_dp = kmalloc(sizeof(struct dp_entry), GFP_ATOMIC);
245 pr_err("Not enough memory\n");
246 return -1; /* TODO - must do retry */
248 new_dp->pid = found_pid;
249 spin_lock(&dp_list_lock);
250 list_add_tail(&new_dp->list, &pmon_data.dp_list);
251 spin_unlock(&dp_list_lock);
253 schedule_work(&pmon_data.pmon_work);
259 static int process_mon_do(struct notifier_block *self, unsigned long cmd,
262 struct thread_info *thread;
265 case THREAD_NOTIFY_FLUSH:
266 case THREAD_NOTIFY_SWITCH:
268 case THREAD_NOTIFY_EXIT:
269 thread = (struct thread_info *)t;
270 check_pernament_process(thread->task->pid, thread->task->comm);
277 static struct notifier_block process_mon_nb = {
278 .notifier_call = process_mon_do,
281 static ssize_t mp_show(char *buf, enum mp_entry_type type)
286 if (!pmon_data.initialized)
289 spin_lock(&mp_list_lock);
290 list_for_each_entry(mp, &pmon_data.mp_list, list) {
291 if (mp->type == type) {
292 len += snprintf(buf + len, PAGE_SIZE, "%d ", mp->pid);
295 spin_unlock(&mp_list_lock);
297 len += snprintf(buf + len, PAGE_SIZE, "\n");
302 static ssize_t mp_vip_show(struct class *class, struct class_attribute *attr,
305 return mp_show(buf, MP_VIP);
308 static ssize_t mp_pnp_show(struct class *class, struct class_attribute *attr,
311 return mp_show(buf, MP_PERMANENT);
314 static CLASS_ATTR(rm_pmon, S_IWUGO, NULL, mp_remove);
315 static CLASS_ATTR(mp_vip, 0644, mp_vip_show, mp_vip_store);
316 static CLASS_ATTR(mp_pnp, 0644, mp_pnp_show, mp_pnp_store);
318 struct file_operations pmon_fops = {
320 .release = pmon_release,
325 static int __init process_mon_init(void)
329 pmon_data.major = register_chrdev(0, PMON_DEVICE, &pmon_fops);
330 if (pmon_data.major < 0) {
331 pr_err("Unable to get major number for pmon dev\n");
333 goto error_create_chr_dev;
336 pmon_data.cls = class_create(THIS_MODULE, PMON_DEVICE);
337 if (IS_ERR(pmon_data.cls)) {
338 pr_err("class create err\n");
339 err = PTR_ERR(pmon_data.cls);
340 goto error_class_create;
343 pmon_data.dev = device_create(pmon_data.cls, NULL,
344 MKDEV(pmon_data.major, 0), NULL,
347 if (IS_ERR(pmon_data.dev)) {
348 pr_err("device create err\n");
349 err = PTR_ERR(pmon_data.dev);
350 goto error_create_class_dev;
353 err = class_create_file(pmon_data.cls, &class_attr_rm_pmon);
355 pr_err("%s: couldn't create meminfo.\n", __func__);
356 goto error_create_class_file_pmoninfo;
359 err = class_create_file(pmon_data.cls, &class_attr_mp_vip);
361 pr_err("%s: couldn't create meminfo.\n", __func__);
362 goto error_create_class_file_mp_vip;
364 err = class_create_file(pmon_data.cls, &class_attr_mp_pnp);
366 pr_err("%s: couldn't create meminfo.\n", __func__);
367 goto error_create_class_file_mp_pnp;
370 INIT_LIST_HEAD(&pmon_data.mp_list);
371 INIT_LIST_HEAD(&pmon_data.dp_list);
373 INIT_WORK(&pmon_data.pmon_work, pmon_work_thread);
374 thread_register_notifier(&process_mon_nb);
375 pmon_data.initialized = 1;
379 error_create_class_file_mp_pnp:
380 class_remove_file(pmon_data.cls, &class_attr_mp_vip);
381 error_create_class_file_mp_vip:
382 class_remove_file(pmon_data.cls, &class_attr_rm_pmon);
383 error_create_class_file_pmoninfo:
384 device_del(pmon_data.dev);
385 error_create_class_dev:
386 class_destroy(pmon_data.cls);
388 unregister_chrdev(pmon_data.major, PMON_DEVICE);
389 error_create_chr_dev:
393 static void __exit process_mon_exit(void)
395 thread_unregister_notifier(&process_mon_nb);
398 module_init(process_mon_init);
399 module_exit(process_mon_exit);
401 MODULE_AUTHOR("baik");
402 MODULE_DESCRIPTION("SLP Process Monitoring driver");
403 MODULE_LICENSE("GPL");