[cgl_discussion] Announcing Non-intrusive Kernel Monitor Project

Steven Dake sdake at mvista.com
Thu Jun 10 15:28:26 PDT 2004


patch looks acceptable..  Although character drivers that implement
ioctls are poorly received...  Have you thought of a sysfs mechanism to
plug this into the kernel?

Thanks
-steve

On Thu, 2004-06-10 at 15:19, Rusty Lynch wrote:
> On Wed, Jun 09, 2004 at 10:19:03AM -0700, Sabharwal, Atul wrote:
> > I have been experimenting with the CGL 2.0 AVL 8.2 requirement on
> > Non-intrusive kernel
> > based monitoring of processes and threads.  For your reference, the
> > requirement is
> > quoted below :
> 
> Looks like outlook ate the patch.  Here is the patch again (without the
> help of outlook)
> 
> BTW, is this how everyone is interpreting the requirement?  There isn't much
> to this and the performance/scalability is basically what ever real-time
> signals can do.
> 
> I would at least like to hear if this is on or off target for the requirement
> before Atul takes this to LKML.  We have played with this on various ia32 and
> IPF systems with hardly noticeable impact while monitoring a significant load,
> and no measurable impact while not monitoring anything.
> 
>     --rusty
> 
> diff -Nru a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
> --- a/Documentation/ioctl-number.txt	Wed Jun  9 10:37:42 2004
> +++ b/Documentation/ioctl-number.txt	Wed Jun  9 10:37:42 2004
> @@ -189,3 +189,4 @@
>  					<mailto:michael.klein at puffin.lb.shuttle.de>
>  0xDD	00-3F	ZFCP device driver	see drivers/s390/scsi/
>  					<mailto:aherrman at de.ibm.com>
> +0xDE	all	drivers/char/kmonitor	<mailto:atul.sabharwal at intel.com>
> diff -Nru a/Documentation/kmonitor.txt b/Documentation/kmonitor.txt
> --- /dev/null	Wed Dec 31 16:00:00 1969
> +++ b/Documentation/kmonitor.txt	Wed Jun  9 10:37:42 2004
> @@ -0,0 +1,119 @@
> +Enabling Non-intrusive Application Monitoring with kmonitor
> +-----------------------------------------------------------
> +The kmonitor driver implements a kernel level non-intrusive 
> +mechanism for rapidly notifying a monitoring user space process
> +of key (process/thread creation/exit) kernel events.
> +
> +The monitoring user space process registers and deregisters for events via
> +a new misc char device using two new ioctl's.  The kernel notifies the
> +monitoring process(es) of the events via a signal that the monitor specifies
> +during registration.
> +
> +An example of how this would be used in an minimal command line utility
> +to wait for an arbitrary process to exit:
> +
> +<snip>rest of required headers...</snip>
> +#include <linux/kmonitor.h>
> +
> +void target_exit_handler (int signum , struct siginfo * info, void * buf)
> +{
> +	 /*
> +	  * Since we only registered for one type of event,
> +	  * KMONITOR_PROCESS_EXIT, on one process, then we already 
> +	  * know our target process has exited
> +	  *
> +	  * If we were doing something more complex, then the data in
> +	  * info might be usefull:
> +	  * 1. info->si_pid: process id of target process
> +	  * 2. info->si_gid: group id of target process
> +	  * 3. info->si_int: event that triggered this signal
> +	  *    (See include/linux/kmonitor.h for the list of events)
> +	  *
> +	  * The target process has exited, so we are done. Kmonitor
> +	  * will do cleanup when we close the file descriptor for 
> +	  * /dev/kmonitor (which will happen automatically when we
> +	  * exit.)
> +	  */
> +	exit(0);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +<snip>...</snip>
> +
> +	/*
> +	 * kmonitor will notify us that the target process has exited
> +	 * by sending us a real-time signal with the payload containing
> +	 * the event that triggered the notification.
> +	 */
> +	action.sa_sigaction = target_exit_handler;
> +	action.sa_flags = SA_SIGINFO;
> +	if (-1 == sigaction(SIGRTMIN, &action, NULL)) {
> +		perror("sigaction");
> +		exit(-1);
> +	}
> +
> +	/*
> +	 * The kmonitor is implemented as misc char device, so the
> +	 * file that needs to be opened (assumed to be /dev/kmonitor
> +	 * in this example) is a char device with a major number of 10
> +	 * and a minor number of 221.
> +	 * 
> +	 * mknod /dev/kmonitor c 10 221 
> +	 */
> +	fd = open("/dev/kmonitor", O_WRONLY);
> +	if (-1 == fd) {
> +		perror("open /dev/kmonitor");
> +		exit(-1);
> +	}
> +
> +	/*
> +	 * To sign up for notification of an arbitrary event on an
> +	 * arbitrary process then we send the KMONITOR_IOW_REGISTER
> +	 * command to the device via the ioctl system call.
> +	 *
> +	 * We indicate the target process and event by sending a
> +	 * kmonitor_cmd structure.
> +	 *
> +	 * NOTE: The 'type' field in the structure is actually 
> +	 *       a bitmask, so it is possible to register for
> +	 *       multiple events on a given target process in one
> +	 *       ioctl call.  The possible events are...
> +         *       #define KMONITOR_THREAD_CREATE 0x01 
> +         *       #define KMONITOR_THREAD_ABORT  0x02           
> +         *       #define KMONITOR_THREAD_EXIT   0x04
> +         *       #define KMONITOR_PROCESS_FORK  0x08
> +         *       #define KMONITOR_PROCESS_ABORT 0x10 
> +         *       #define KMONITOR_PROCESS_EXEC  0x20 
> +         *       #define KMONITOR_PROCESS_EXIT  0x40
> +	 */
> +	hdr.signal = SIGRTMIN;
> +	hdr.pid = args.pid;
> +	hdr.type = KMONITOR_PROCESS_EXIT;
> +	if (-1 == ioctl(fd, KMONITOR_IOW_REGISTER, &hdr)) {
> +		perror("ioctl");
> +		exit(-1);
> +	}
> +	
> +	/*
> +	 * In this very simple example all we need to do is wait 
> +	 * for a signal to be sent.  The signal handler will exit
> +	 * when it is notified of the target process exiting.
> +	 */
> +	sigemptyset(&empty_mask);
> +	sigsuspend(&empty_mask);	
> +
> +	/*
> +	 * kmonitor will perform a cleanup of all request a given 
> +	 * monitoring process has made, so it is required to deregister
> +	 * each of the specific request.
> +	 *
> +	 * If for some reason a monitoring process wanted to deregister
> +	 * a specific request, then the procedure is just like registering,
> +	 * other then the ioctl command is KMONITOR_IOW_DEREGISTER.
> +	 */
> +	close(fd);
> +	exit (0);
> +}
> +
> +
> diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
> --- a/drivers/char/Kconfig	Wed Jun  9 10:37:42 2004
> +++ b/drivers/char/Kconfig	Wed Jun  9 10:37:42 2004
> @@ -974,5 +974,15 @@
>  	  out to lunch past a certain margin.  It can reboot the system
>  	  or merely print a warning.
>  
> +config KMONITOR
> +	bool "Kmonitor driver"
> +	help
> +	  The kmonitor driver implements a kernel level non-intrusive 
> +	  mechanism for rapidly notifying a monitoring user space process
> +	  of key (process/thread creation/exit) kernel events. For more
> +	  info see Documentation/kmonitor.txt 
> +
> +	  If in doubt, say 'N'.
> +
>  endmenu
>  
> diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
> --- a/drivers/char/Makefile	Wed Jun  9 10:37:42 2004
> +++ b/drivers/char/Makefile	Wed Jun  9 10:37:42 2004
> @@ -79,6 +79,7 @@
>  obj-$(CONFIG_DRM) += drm/
>  obj-$(CONFIG_PCMCIA) += pcmcia/
>  obj-$(CONFIG_IPMI_HANDLER) += ipmi/
> +obj-$(CONFIG_KMONITOR) += kmonitor.o
>  
>  obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
>  
> diff -Nru a/drivers/char/kmonitor.c b/drivers/char/kmonitor.c
> --- /dev/null	Wed Dec 31 16:00:00 1969
> +++ b/drivers/char/kmonitor.c	Wed Jun  9 10:37:42 2004
> @@ -0,0 +1,336 @@
> +/*
> + * linux/kmonitor.c
> + *
> + * Copyright (C)  2004 Intel Corporation.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License v2.0 as published by the Free Software Foundation; 
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public
> + * License along with this program; if not, write to the
> + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> + * Boston, MA 021110-1307, USA.
> + *
> + * Authors: Atul Sabharwal <atul.sabharwal at intel.com>
> + *
> + * The kmonitor driver implements a kernel level non-intrusive 
> + * mechanism for rapidly notifying a monitoring user space process
> + * of key (process/thread creation/exit) kernel events.
> + * 
> + * See Documentation/kmonitor.txt for more details
> + */
> +
> +#include <linux/config.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/fs.h>
> +#include <linux/hash.h>
> +#include <linux/init.h>
> +#include <linux/kmonitor.h>
> +#include <linux/miscdevice.h>
> +#include <linux/proc_fs.h>
> +#include <linux/sched.h>
> +#include <linux/types.h>
> +#include <linux/timer.h>
> +#include <asm/uaccess.h>
> +#include <asm/atomic.h>
> +
> +/*
> + * kmonitor maintains a database of resources containing:
> + * - the pid of the process being monitored (target)
> + * - the pid of process that should be notified (monitor)
> + * - an event mask 
> + * - a signal number to notify the monitor with
> + * - a list_head
> + * 
> + * To improve scalability, a hash of linked listed is maintained
> + * with a per bucket read-write lock.  KMONITOR_BITS defines the
> + * order of the list size, so setting KMONITOR_BITS to 8 would translate
> + * to 265 buckets.  Using a hash of linked list improves the order of the
> + * search from an O(n) to O(n/m) where n is the number of resources and
> + * m is the number of buckets.
> + *
> + * Note that since we are using a per bucket read-write lock, the number
> + * of buckets also as an effect on SMP performance since the smaller the
> + * list of resources in each bucket, the less likely a processor will 
> + * spin waiting for another processor to finish writing to the same list.
> + */
> +
> +struct kmonitor_bucket 
> +{
> +	struct list_head list;
> +	rwlock_t lock;
> +};
> +
> +#define KMONITOR_BITS 0x8
> +
> +struct kmonitor_bucket kmonitor_resources[1<<KMONITOR_BITS];
> +
> +static inline unsigned long khash(pid_t target)
> +{
> +	return hash_long((unsigned long)target, KMONITOR_BITS);
> +}
> +
> +struct kmonitor_res
> +{
> +	struct list_head rlist;
> +	pid_t target;
> +	pid_t monitor;
> +	int signal;
> +	__u32 event_mask;
> +};
> +
> +#define to_kmonitor_res(r) \
> +        container_of(r, struct kmonitor_res, rlist);
> +
> +kmem_cache_t *kmonitor_cache;
> +
> +/*
> + * kmonitor_active is used to improve the performance of searching
> + * an empty resource database
> + */
> +atomic_t kmonitor_active = { .counter = 0};
> +
> +/* #define DEBUG */
> +#ifdef DEBUG
> +#define DBG(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
> +#define TRACE(format, arg...) printk("%s(" format ")\n", __FUNCTION__, ## arg)
> +#else
> +#define DBG(format, arg...) do {} while(0);
> +#define TRACE(arg...) do {} while(0);
> +#endif
> +
> +static int kmonitor_add(pid_t target, int type, int signal)
> +{
> +	struct kmonitor_res *r;
> +	struct list_head *tmp;
> +	unsigned long bucket = khash(target);
> +
> +	TRACE("%i, %i, %i", target, type, signal);
> +	read_lock(&kmonitor_resources[bucket].lock);
> +	list_for_each(tmp, &kmonitor_resources[bucket].list) {
> +		r = to_kmonitor_res(tmp);
> +		if (r->monitor == current->pid && r->target == target) {
> +			/*
> +			 * There is an existing resource for this
> +			 * target/monitor combination so just flip 
> +			 * a bit in the event mask indicating that 
> +			 * this monitor also wants to be notified 
> +			 * for this type of event.
> +			 */
> +			r->event_mask |= type;
> +			r->signal = signal;
> +			DBG("Added %i to existing res", type);
> +			read_unlock(&kmonitor_resources[bucket].lock);
> +			return 0;
> +		} 
> +	}
> +	read_unlock(&kmonitor_resources[bucket].lock);
> +
> +	/*
> +	 * This is the first event registered for this target 
> +	 * on this monitor.  Allocate a new resource from our 
> +	 * cache and add the resource to the global list.
> +	 *
> +         * Note: There is no race condition between the top half & the
> +         * bottom part of this function as if multiple monitors are active,
> +         * each will have a unique resource for itself. So, the function
> +         * is SMP safe.
> +         */
> +	r = kmem_cache_alloc(kmonitor_cache, SLAB_KERNEL);
> +	if (!r)
> +		return -ENOMEM;
> +		
> +	r->target = target;
> +	r->monitor = current->pid;
> +	r->event_mask = type;
> +	r->signal = signal;
> +	write_lock(&kmonitor_resources[bucket].lock);
> +	list_add(&r->rlist, &kmonitor_resources[bucket].list);
> +	write_unlock(&kmonitor_resources[bucket].lock);
> +	return 0;
> +}
> +
> +static int kmonitor_remove(pid_t target, int type)
> +{
> +	struct list_head *tmp, *next;
> +	int ret = -EINVAL;
> +	int bucket = khash(target);
> +
> +	TRACE("%i, %i", target, type);
> +
> +	write_lock(&kmonitor_resources[bucket].lock);
> +	list_for_each_safe(tmp, next, &kmonitor_resources[bucket].list) {
> +		struct kmonitor_res *r = to_kmonitor_res(tmp);
> +		if (r->monitor == current->pid && r->target == target) {
> +			r->event_mask &= ~type;
> +			if (!r->event_mask) {
> +				/* No more events so go ahead and cleanup */
> +				list_del(tmp);
> +				kmem_cache_free(kmonitor_cache, r);
> +			}
> +			ret = 0;
> +			break;
> +		} 
> +	}
> +
> +	write_unlock(&kmonitor_resources[bucket].lock);
> +	return ret;
> +}
> +
> +void __kmonitor_notify_event(struct task_struct *tsk, int type) 
> +{
> +	struct siginfo info;
> +	struct list_head *tmp, *next;
> +	int bucket = khash(current->pid);
> +
> +	read_lock(&kmonitor_resources[bucket].lock);
> +	list_for_each_safe(tmp,next,&kmonitor_resources[bucket].list) {
> +		struct kmonitor_res *r = to_kmonitor_res(tmp);
> +		if (r->target == current->pid && type & r->event_mask) {
> +			info.si_signo = r->signal;
> +			info.si_code = SI_QUEUE;
> +			info.si_int = type;
> +			info.si_pid = tsk->pid;
> +			info.si_uid = tsk->uid;
> +			kill_proc_info(r->signal, &info, r->monitor);
> +		}
> +	}
> +	read_unlock(&kmonitor_resources[bucket].lock);
> +}
> +
> +static int kmonitor_open(struct inode *inode, struct file *file)
> +{
> +	atomic_inc(&kmonitor_active);
> +	return 0;
> +}
> +
> +static int kmonitor_release(struct inode *inode, struct file *file)
> +{
> +	struct list_head *tmp, *next;
> +	int i;
> +
> +	TRACE("%p, %p", inode, file);
> +	atomic_dec(&kmonitor_active);
> +
> +	/*
> +	 * Remove any resources associated with this monitor
> +	 */
> +	for (i=0; i<(1<<KMONITOR_BITS); i++) {
> +		write_lock(&kmonitor_resources[i].lock);
> +		list_for_each_safe(tmp, next, &kmonitor_resources[i].list) {
> +			struct kmonitor_res *r = to_kmonitor_res(tmp);
> +			if (r->monitor == current->pid) {
> +				list_del(tmp);
> +				kmem_cache_free(kmonitor_cache, r);
> +			} 
> +		}
> +		write_unlock(&kmonitor_resources[i].lock);
> +	}
> +
> +	return 0;
> +}
> +
> +static int kmonitor_ioctl(struct inode *inode, struct file *file,
> +			  unsigned int cmd, unsigned long arg)
> +{
> +	struct kmonitor_cmd hdr;
> +
> +	TRACE("%p, %p, %i, %i", inode, file, (int)cmd, (int)arg);
> +	if (copy_from_user((struct kmonitor_cmd *)&hdr, 
> +			   (struct kmonitor_cmd *)arg, 
> +			   sizeof(struct kmonitor_cmd)))
> +		return -EFAULT;
> +
> +	switch (cmd) {
> +	case KMONITOR_IOW_REGISTER:
> +		return kmonitor_add(hdr.pid, hdr.type, hdr.signal);
> +	case KMONITOR_IOW_DEREGISTER:
> +		return kmonitor_remove(hdr.pid, hdr.type);		
> +	}
> +
> +	DBG("Unexpected ioctl, %i", cmd);
> +	return -EINVAL;
> +}
> +
> +static struct file_operations kmonitor_fops = {
> +	.owner		= THIS_MODULE,
> +	.llseek		= no_llseek,
> +	.open           = kmonitor_open,
> +	.release	= kmonitor_release,
> +	.ioctl          = kmonitor_ioctl,
> +};
> +
> +static struct miscdevice kmonitor_miscdev = {
> +	.minor		= KMONITOR_MINOR,
> +	.name		= "kmonitor",
> +	.fops		= &kmonitor_fops,
> +};
> +
> +static int __init kmonitor_init(void)
> +{
> +	int ret, i;
> +
> +	TRACE("void");
> +
> +	for (i=0; i<(1<<KMONITOR_BITS); i++) {
> +		INIT_LIST_HEAD(&kmonitor_resources[i].list);
> +		kmonitor_resources[i].lock = RW_LOCK_UNLOCKED;
> +	}
> +
> +	ret = misc_register(&kmonitor_miscdev);
> +	if (ret) {
> +		printk(KERN_ERR "unable to register kmonitor misc device\n");
> +		goto error_misc_drvr_register;
> +	}
> +
> +	kmonitor_cache = kmem_cache_create("kmonitor_res", 
> +					   sizeof(struct kmonitor_res), 0, 
> +					   SLAB_HWCACHE_ALIGN,
> +					   NULL, NULL);
> +	if (!kmonitor_cache) {
> +		printk(KERN_ERR "unable to allocate kmonitor_cache\n");
> +		ret = -EINVAL;
> +		goto error_in_kmonitor_cache;
> +	}
> +
> +	return 0;
> +
> + error_in_kmonitor_cache:
> +	misc_deregister(&kmonitor_miscdev);
> + error_misc_drvr_register:
> +	return ret;
> +}
> +
> +static void __exit kmonitor_exit(void)
> +{
> +	struct list_head *tmp, *next;
> +	int i;
> +
> +	TRACE("void");
> +	misc_deregister(&kmonitor_miscdev);
> +	for (i=0; i<(1<<KMONITOR_BITS); i++) {
> +		write_lock(&kmonitor_resources[i].lock);
> +		list_for_each_safe(tmp, next, &kmonitor_resources[i].list) {
> +			struct kmonitor_res *r = to_kmonitor_res(tmp);
> +			list_del(tmp);
> +			kmem_cache_free(kmonitor_cache, r);
> +		}
> +		write_unlock(&kmonitor_resources[i].lock);
> +	}
> +	kmem_cache_destroy(kmonitor_cache);
> +}
> +
> +module_init(kmonitor_init);
> +module_exit(kmonitor_exit);
> +
> +MODULE_AUTHOR("Atul Sabharwal");
> +MODULE_DESCRIPTION("Kmonitor Char Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS_MISCDEV(KMONITOR_MINOR);
> diff -Nru a/fs/exec.c b/fs/exec.c
> --- a/fs/exec.c	Wed Jun  9 10:37:42 2004
> +++ b/fs/exec.c	Wed Jun  9 10:37:42 2004
> @@ -46,6 +46,7 @@
>  #include <linux/security.h>
>  #include <linux/syscalls.h>
>  #include <linux/rmap.h>
> +#include <linux/kmonitor.h>
>  
>  #include <asm/uaccess.h>
>  #include <asm/pgalloc.h>
> @@ -1144,6 +1145,7 @@
>  		free_arg_pages(&bprm);
>  
>  		/* execve success */
> +		kmonitor_notify_event(current, KMONITOR_PROCESS_EXEC);
>  		security_bprm_free(&bprm);
>  		return retval;
>  	}
> diff -Nru a/include/linux/kmonitor.h b/include/linux/kmonitor.h
> --- /dev/null	Wed Dec 31 16:00:00 1969
> +++ b/include/linux/kmonitor.h	Wed Jun  9 10:37:42 2004
> @@ -0,0 +1,62 @@
> +/* 
> + *
> + * linux/kmonitor.h
> + *
> + * Copyright (C) 2004 Intel Corporation.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License v2.0 as published by the Free Software Foundation; 
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public
> + * License along with this program; if not, write to the
> + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> + * Boston, MA 021110-1307, USA.
> + *
> + * Authors: Atul Sabharwal <atul.sabharwal at intel.com>
> + *               
> + */
> +#ifndef _LINUX_KMONITOR_H_
> +#define _LINUX_KMONITOR_H_
> +
> +#include <asm/atomic.h>
> +
> +#define KMONITOR_THREAD_CREATE 0x01 
> +#define KMONITOR_THREAD_ABORT  0x02           
> +#define KMONITOR_THREAD_EXIT   0x04
> +#define KMONITOR_PROCESS_FORK  0x08
> +#define KMONITOR_PROCESS_ABORT 0x10 
> +#define KMONITOR_PROCESS_EXEC  0x20 
> +#define KMONITOR_PROCESS_EXIT  0x40
> +
> +struct kmonitor_cmd 
> +{
> +	pid_t pid;
> +	int type;
> +	int signal;
> +};
> +
> +#define KMONITOR_IOW_REGISTER   _IOW(0xDE, 1, struct kmonitor_cmd)
> +#define KMONITOR_IOW_DEREGISTER _IOW(0xDE, 2, struct kmonitor_cmd)
> +
> +#ifdef __KERNEL__
> +#include <linux/sysctl.h>
> +
> +extern  atomic_t  kmonitor_active;
> +extern void __kmonitor_notify_event(struct task_struct *tsk, int type);
> +
> +static inline void kmonitor_notify_event( struct task_struct *tsk, int type)
> +{
> +#ifdef CONFIG_KMONITOR	
> +	if (atomic_read(&kmonitor_active))
> +		__kmonitor_notify_event(tsk, type);
> +#endif /* CONFIG_KMONITOR */
> +}
> +#endif /* __KERNEL__ */
> +#endif /* _LINUX_KMONITOR_H_ */
> +
> diff -Nru a/include/linux/miscdevice.h b/include/linux/miscdevice.h
> --- a/include/linux/miscdevice.h	Wed Jun  9 10:37:42 2004
> +++ b/include/linux/miscdevice.h	Wed Jun  9 10:37:42 2004
> @@ -35,6 +35,7 @@
>  #define SGI_USEMACLONE	     151
>  
>  #define TUN_MINOR	     200
> +#define KMONITOR_MINOR	     221
>  
>  struct device;
>  
> diff -Nru a/kernel/exit.c b/kernel/exit.c
> --- a/kernel/exit.c	Wed Jun  9 10:37:42 2004
> +++ b/kernel/exit.c	Wed Jun  9 10:37:42 2004
> @@ -22,6 +22,7 @@
>  #include <linux/profile.h>
>  #include <linux/mount.h>
>  #include <linux/proc_fs.h>
> +#include <linux/kmonitor.h>
>  
>  #include <asm/uaccess.h>
>  #include <asm/pgtable.h>
> @@ -748,6 +749,11 @@
>  	 */
>  	_raw_write_unlock(&tasklist_lock);
>  	local_irq_enable();
> +
> +	if (tsk->pid == tsk->tgid)
> +		kmonitor_notify_event(tsk, KMONITOR_PROCESS_EXIT);
> +	else
> +		kmonitor_notify_event(tsk, KMONITOR_THREAD_EXIT);
>  
>  	/* If the process is dead, release it - nobody will wait for it */
>  	if (state == TASK_DEAD)
> diff -Nru a/kernel/fork.c b/kernel/fork.c
> --- a/kernel/fork.c	Wed Jun  9 10:37:42 2004
> +++ b/kernel/fork.c	Wed Jun  9 10:37:42 2004
> @@ -41,6 +41,7 @@
>  #include <asm/mmu_context.h>
>  #include <asm/cacheflush.h>
>  #include <asm/tlbflush.h>
> +#include <linux/kmonitor.h>
>  
>  /* The idle threads do not count..
>   * Protected by write_lock_irq(&tasklist_lock)
> @@ -1165,6 +1166,7 @@
>  	 */
>  	pid = IS_ERR(p) ? PTR_ERR(p) : p->pid;
>  
> +
>  	if (!IS_ERR(p)) {
>  		struct completion vfork;
>  
> @@ -1223,6 +1225,11 @@
>  			 * COW overhead when the child exec()s afterwards.
>  			 */
>  			set_need_resched();
> +
> +		if (p->pid == p->tgid)
> +			kmonitor_notify_event(p, KMONITOR_PROCESS_FORK);
> +		else
> +			kmonitor_notify_event(p, KMONITOR_THREAD_CREATE);
>  	}
>  	return pid;
>  }
> 
> ______________________________________________________________________
> _______________________________________________
> cgl_discussion mailing list
> cgl_discussion at lists.osdl.org
> http://lists.osdl.org/mailman/listinfo/cgl_discussion




More information about the cgl_discussion mailing list