aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2002-02-09 19:49:28 +0000
committerdavem <davem>2002-02-09 19:49:28 +0000
commit35f6bf4a4e288f2ccd8f44cdd1b25384a0ea4f74 (patch)
treec020fb2e432dd49d318280f5adcc19b20ae5adcb
parent434c06b9c0d0a10071d2bbaec1119d13559c1f2d (diff)
downloadnetdev-vger-cvs-35f6bf4a4e288f2ccd8f44cdd1b25384a0ea4f74.tar.gz
Merge mainline to 2.5.4-pre3
-rw-r--r--drivers/input/input.c486
-rw-r--r--fs/proc/base.c7
-rw-r--r--include/asm-i386/processor.h16
-rw-r--r--kernel/sched.c44
4 files changed, 481 insertions, 72 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index eb7fe0f17..e80f4a4c8 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1,11 +1,9 @@
/*
- * $Id: input.c,v 1.20 2001/05/17 15:50:27 vojtech Exp $
+ * $Id: input.c,v 1.48 2001/12/26 21:08:33 jsimmons Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
- * The input layer module itself
- *
- * Sponsored by SuSE
+ * The input core
*/
/*
@@ -24,8 +22,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/init.h>
@@ -34,12 +32,16 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/random.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input layer module");
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
-
EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
EXPORT_SYMBOL(input_register_handler);
@@ -48,6 +50,8 @@ EXPORT_SYMBOL(input_register_minor);
EXPORT_SYMBOL(input_unregister_minor);
EXPORT_SYMBOL(input_open_device);
EXPORT_SYMBOL(input_close_device);
+EXPORT_SYMBOL(input_accept_process);
+EXPORT_SYMBOL(input_flush_device);
EXPORT_SYMBOL(input_event);
#define INPUT_MAJOR 13
@@ -60,17 +64,31 @@ static devfs_handle_t input_devfs_handle;
static int input_number;
static long input_devices[NBITS(INPUT_DEVICES)];
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_bus_input_dir;
+DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static int input_devices_state;
+#endif
+
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle = dev->handle;
/*
+ * Wake up the device if it is sleeping.
+ */
+ if (dev->pm_dev)
+ pm_access(dev->pm_dev);
+
+/*
* Filter non-events, and bad input values out.
*/
if (type > EV_MAX || !test_bit(type, dev->evbit))
return;
+ add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
+
switch (type) {
case EV_KEY:
@@ -130,6 +148,8 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
if (code > MSC_MAX || !test_bit(code, dev->mscbit))
return;
+
+ if (dev->event) dev->event(dev, type, code, value);
break;
@@ -185,16 +205,36 @@ static void input_repeat_key(unsigned long data)
mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
}
+int input_accept_process(struct input_handle *handle, struct file *file)
+{
+ if (handle->dev->accept)
+ return handle->dev->accept(handle->dev, file);
+
+ return 0;
+}
+
int input_open_device(struct input_handle *handle)
{
+ if (handle->dev->pm_dev)
+ pm_access(handle->dev->pm_dev);
handle->open++;
if (handle->dev->open)
return handle->dev->open(handle->dev);
return 0;
}
+int input_flush_device(struct input_handle* handle, struct file* file)
+{
+ if (handle->dev->flush)
+ return handle->dev->flush(handle->dev, file);
+
+ return 0;
+}
+
void input_close_device(struct input_handle *handle)
{
+ if (handle->dev->pm_dev)
+ pm_dev_idle(handle->dev->pm_dev);
if (handle->dev->close)
handle->dev->close(handle->dev);
handle->open--;
@@ -208,25 +248,197 @@ static void input_link_handle(struct input_handle *handle)
handle->handler->handle = handle;
}
+/**
+ * input_find_and_remove - Find and remove node
+ *
+ * @type: data type
+ * @initval: initial value
+ * @targ: node to find
+ * @next: next node in the list
+ *
+ * Searches the linked list for the target node @targ. If the node
+ * is found, it is removed from the list.
+ *
+ * If the node is not found, the end of the list will be hit,
+ * indicating that it wasn't in the list to begin with.
+ *
+ * Returns nothing.
+ */
+#define input_find_and_remove(type, initval, targ, next) \
+ do { \
+ type **ptr; \
+ for (ptr = &initval; *ptr; ptr = &((*ptr)->next)) \
+ if (*ptr == targ) break; \
+ if (*ptr) *ptr = (*ptr)->next; \
+ } while (0)
+
static void input_unlink_handle(struct input_handle *handle)
{
- struct input_handle **handleptr;
+ input_find_and_remove(struct input_handle, handle->dev->handle, handle, dnext);
+ input_find_and_remove(struct input_handle, handle->handler->handle, handle, hnext);
+}
+
+#define MATCH_BIT(bit, max) \
+ for (i = 0; i < NBITS(max); i++) \
+ if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
+ break; \
+ if (i != NBITS(max)) \
+ continue;
+
+static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
+{
+ int i;
- handleptr = &handle->dev->handle;
- while (*handleptr && (*handleptr != handle))
- handleptr = &((*handleptr)->dnext);
- *handleptr = (*handleptr)->dnext;
+ for (; id->flags || id->driver_info; id++) {
- handleptr = &handle->handler->handle;
- while (*handleptr && (*handleptr != handle))
- handleptr = &((*handleptr)->hnext);
- *handleptr = (*handleptr)->hnext;
+ if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+ if (id->idbus != dev->idbus)
+ continue;
+
+ if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
+ if (id->idvendor != dev->idvendor)
+ continue;
+
+ if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
+ if (id->idproduct != dev->idproduct)
+ continue;
+
+ if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+ if (id->idversion != dev->idversion)
+ continue;
+
+ MATCH_BIT(evbit, EV_MAX);
+ MATCH_BIT(keybit, KEY_MAX);
+ MATCH_BIT(relbit, REL_MAX);
+ MATCH_BIT(absbit, ABS_MAX);
+ MATCH_BIT(mscbit, MSC_MAX);
+ MATCH_BIT(ledbit, LED_MAX);
+ MATCH_BIT(sndbit, SND_MAX);
+ MATCH_BIT(ffbit, FF_MAX);
+
+ return id;
+ }
+
+ return NULL;
}
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Input hotplugging invokes what /proc/sys/kernel/hotplug says
+ * (normally /sbin/hotplug) when input devices get added or removed.
+ *
+ * This invokes a user mode policy agent, typically helping to load driver
+ * or other modules, configure the device, and more. Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ */
+
+#define SPRINTF_BIT_A(bit, name, max) \
+ do { \
+ envp[i++] = scratch; \
+ scratch += sprintf(scratch, name); \
+ for (j = NBITS(max) - 1; j >= 0; j--) \
+ if (dev->bit[j]) break; \
+ for (; j >= 0; j--) \
+ scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
+ scratch++; \
+ } while (0)
+
+#define SPRINTF_BIT_A2(bit, name, max, ev) \
+ do { \
+ if (test_bit(ev, dev->evbit)) \
+ SPRINTF_BIT_A(bit, name, max); \
+ } while (0)
+
+static void input_call_hotplug(char *verb, struct input_dev *dev)
+{
+ char *argv[3], **envp, *buf, *scratch;
+ int i = 0, j, value;
+
+ if (!hotplug_path[0]) {
+ printk(KERN_ERR "input.c: calling hotplug a hotplug agent defined\n");
+ return;
+ }
+ if (in_interrupt()) {
+ printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
+ return;
+ }
+ if (!current->fs->root) {
+ printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
+ return;
+ }
+ if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
+ printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+ return;
+ }
+ if (!(buf = kmalloc(1024, GFP_KERNEL))) {
+ kfree (envp);
+ printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+ return;
+ }
+
+ argv[0] = hotplug_path;
+ argv[1] = "input";
+ argv[2] = 0;
+
+ envp[i++] = "HOME=/";
+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+ scratch = buf;
+
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
+ dev->idbus, dev->idvendor, dev->idproduct, dev->idversion) + 1;
+
+ if (dev->name) {
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
+ }
+
+ if (dev->phys) {
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
+ }
+
+ SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
+ SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
+ SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
+ SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
+ SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+ SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
+ SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
+ SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF);
+
+ envp[i++] = 0;
+
+ printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
+ argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
+
+ value = call_usermodehelper(argv [0], argv, envp);
+
+ kfree(buf);
+ kfree(envp);
+
+ if (value != 0)
+ printk(KERN_WARNING "input.c: hotplug returned %d\n", value);
+}
+
+#endif
+
void input_register_device(struct input_dev *dev)
{
struct input_handler *handler = input_handler;
struct input_handle *handle;
+ struct input_device_id *id;
/*
* Initialize repeat timer to default values.
@@ -259,18 +471,45 @@ void input_register_device(struct input_dev *dev)
*/
while (handler) {
- if ((handle = handler->connect(handler, dev)))
- input_link_handle(handle);
+ if ((id = input_match_device(handler->id_table, dev)))
+ if ((handle = handler->connect(handler, dev, id)))
+ input_link_handle(handle);
handler = handler->next;
}
+
+/*
+ * Notify the hotplug agent.
+ */
+
+#ifdef CONFIG_HOTPLUG
+ input_call_hotplug("add", dev);
+#endif
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
+
}
void input_unregister_device(struct input_dev *dev)
{
struct input_handle *handle = dev->handle;
- struct input_dev **devptr = &input_dev;
struct input_handle *dnext;
+ if (!dev) return;
+
+/*
+ * Turn off power management for the device.
+ */
+ if (dev->pm_dev)
+ pm_unregister(dev->pm_dev);
+
+
/*
* Kill any pending repeat timers.
*/
@@ -289,23 +528,36 @@ void input_unregister_device(struct input_dev *dev)
}
/*
- * Remove the device.
+ * Notify the hotplug agent.
*/
- while (*devptr && (*devptr != dev))
- devptr = &((*devptr)->next);
- *devptr = (*devptr)->next;
+#ifdef CONFIG_HOTPLUG
+ input_call_hotplug("remove", dev);
+#endif
+
+/*
+ * Remove the device.
+ */
+ input_find_and_remove(struct input_dev, input_dev, dev, next);
input_number--;
+/*
+ * Notify /proc.
+ */
- if (dev->number < INPUT_DEVICES)
- clear_bit(dev->number, input_devices);
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
}
void input_register_handler(struct input_handler *handler)
{
struct input_dev *dev = input_dev;
struct input_handle *handle;
+ struct input_device_id *id;
+
+ if (!handler) return;
/*
* Add minors if needed.
@@ -326,15 +578,24 @@ void input_register_handler(struct input_handler *handler)
*/
while (dev) {
- if ((handle = handler->connect(handler, dev)))
- input_link_handle(handle);
+ if ((id = input_match_device(handler->id_table, dev)))
+ if ((handle = handler->connect(handler, dev, id)))
+ input_link_handle(handle);
dev = dev->next;
}
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
}
void input_unregister_handler(struct input_handler *handler)
{
- struct input_handler **handlerptr = &input_handler;
struct input_handle *handle = handler->handle;
struct input_handle *hnext;
@@ -352,18 +613,23 @@ void input_unregister_handler(struct input_handler *handler)
/*
* Remove it.
*/
-
- while (*handlerptr && (*handlerptr != handler))
- handlerptr = &((*handlerptr)->next);
-
- *handlerptr = (*handlerptr)->next;
+ input_find_and_remove(struct input_handler, input_handler, handler,
+ next);
/*
* Remove minors.
*/
-
if (handler->fops != NULL)
input_table[handler->minor >> 5] = NULL;
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+ input_devices_state++;
+ wake_up(&input_devices_poll_wait);
+#endif
}
static int input_open_file(struct inode *inode, struct file *file)
@@ -415,18 +681,164 @@ void input_unregister_minor(devfs_handle_t handle)
devfs_unregister(handle);
}
+/*
+ * ProcFS interface for the input drivers.
+ */
+
+#ifdef CONFIG_PROC_FS
+
+#define SPRINTF_BIT_B(bit, name, max) \
+ do { \
+ len += sprintf(buf + len, "B: %s", name); \
+ for (i = NBITS(max) - 1; i >= 0; i--) \
+ if (dev->bit[i]) break; \
+ for (; i >= 0; i--) \
+ len += sprintf(buf + len, "%lx ", dev->bit[i]); \
+ len += sprintf(buf + len, "\n"); \
+ } while (0)
+
+#define SPRINTF_BIT_B2(bit, name, max, ev) \
+ do { \
+ if (test_bit(ev, dev->evbit)) \
+ SPRINTF_BIT_B(bit, name, max); \
+ } while (0)
+
+
+static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+{
+ int state = input_devices_state;
+ poll_wait(file, &input_devices_poll_wait, wait);
+ if (state != input_devices_state)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+ struct input_dev *dev = input_dev;
+ struct input_handle *handle;
+
+ off_t at = 0;
+ int i, len, cnt = 0;
+
+ while (dev) {
+
+ len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+ dev->idbus, dev->idvendor, dev->idproduct, dev->idversion);
+
+ len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+ len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+ len += sprintf(buf + len, "D: Drivers=");
+
+ handle = dev->handle;
+
+ while (handle) {
+ len += sprintf(buf + len, "%s ", handle->name);
+ handle = handle->dnext;
+ }
+
+ len += sprintf(buf + len, "\n");
+
+ SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
+ SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
+ SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
+ SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
+ SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+ SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
+ SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
+ SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF);
+
+ len += sprintf(buf + len, "\n");
+
+ at += len;
+
+ if (at >= pos) {
+ if (!*start) {
+ *start = buf + (pos - (at - len));
+ cnt = at - pos;
+ } else cnt += len;
+ buf += len;
+ if (cnt >= count)
+ break;
+ }
+
+ dev = dev->next;
+ }
+
+ if (!dev) *eof = 1;
+
+ return (count > cnt) ? cnt : count;
+}
+
+static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+ struct input_handler *handler = input_handler;
+
+ off_t at = 0;
+ int len = 0, cnt = 0;
+ int i = 0;
+
+ while (handler) {
+
+ if (handler->fops)
+ len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
+ i++, handler->name, handler->minor);
+ else
+ len = sprintf(buf, "N: Number=%d Name=%s\n",
+ i++, handler->name);
+
+ at += len;
+
+ if (at >= pos) {
+ if (!*start) {
+ *start = buf + (pos - (at - len));
+ cnt = at - pos;
+ } else cnt += len;
+ buf += len;
+ if (cnt >= count)
+ break;
+ }
+
+ handler = handler->next;
+ }
+
+ if (!handler) *eof = 1;
+
+ return (count > cnt) ? cnt : count;
+}
+
+#endif
+
static int __init input_init(void)
{
+ struct proc_dir_entry *entry;
+
+#ifdef CONFIG_PROC_FS
+ proc_bus_input_dir = proc_mkdir("input", proc_bus);
+ proc_bus_input_dir->owner = THIS_MODULE;
+ entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+ entry->owner = THIS_MODULE;
+ entry->proc_fops->poll = input_devices_poll;
+ entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+ entry->owner = THIS_MODULE;
+#endif
if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
return -EBUSY;
}
+
input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);
+
return 0;
}
static void __exit input_exit(void)
{
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("devices", proc_bus_input_dir);
+ remove_proc_entry("handlers", proc_bus_input_dir);
+ remove_proc_entry("input", proc_bus);
+#endif
devfs_unregister(input_devfs_handle);
if (devfs_unregister_chrdev(INPUT_MAJOR, "input"))
printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e472c395c..47c5cfdc6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1003,8 +1003,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
ei = PROC_I(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_ino = fake_ino(0, PROC_PID_INO);
- ei->file = NULL;
- ei->task = NULL;
+ ei->pde = NULL;
inode->i_mode = S_IFLNK|S_IRWXUGO;
inode->i_uid = inode->i_gid = 0;
inode->i_size = 64;
@@ -1035,7 +1034,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO);
- free_task_struct(task);
+ put_task_struct(task);
if (!inode)
goto out;
@@ -1057,7 +1056,7 @@ void proc_pid_delete_inode(struct inode *inode)
if (PROC_I(inode)->file)
fput(PROC_I(inode)->file);
if (proc_task(inode))
- free_task_struct(proc_task(inode));
+ put_task_struct(proc_task(inode));
}
#define PROC_NUMBUF 10
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index a270f2dd5..5ea17fb89 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -438,22 +438,14 @@ extern void release_segments(struct mm_struct * mm);
/*
* Return saved PC of a blocked thread.
*/
-static inline unsigned long thread_saved_pc(struct thread_struct *t)
+static inline unsigned long thread_saved_pc(struct thread_info *ti)
{
- return ((unsigned long *)t->esp)[3];
+ return ((unsigned long *)ti->task->thread->esp)[3];
}
unsigned long get_wchan(struct task_struct *p);
-#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long) (p), 1)
-#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)
-
-#define init_task (init_task_union.task)
-#define init_stack (init_task_union.stack)
+#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019])
+#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1022])
struct microcode {
unsigned int hdrver;
diff --git a/kernel/sched.c b/kernel/sched.c
index 5fcebb034..acda87e3c 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -51,7 +51,7 @@ static struct runqueue runqueues[NR_CPUS] __cacheline_aligned;
#define cpu_rq(cpu) (runqueues + (cpu))
#define this_rq() cpu_rq(smp_processor_id())
-#define task_rq(p) cpu_rq((p)->cpu)
+#define task_rq(p) cpu_rq((p)->thread_info->cpu)
#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
#define rt_task(p) ((p)->policy != SCHED_OTHER)
@@ -192,13 +192,19 @@ static inline void deactivate_task(struct task_struct *p, runqueue_t *rq)
static inline void resched_task(task_t *p)
{
- int need_resched;
+#ifdef CONFIG_SMP
+ int need_resched, nrpolling;
+
+ /* minimise the chance of sending an interrupt to poll_idle() */
+ nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
+ need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED);
+ nrpolling |= test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
- need_resched = p->work.need_resched;
- wmb();
- p->work.need_resched = 1;
- if (!need_resched && (p->cpu != smp_processor_id()))
- smp_send_reschedule(p->cpu);
+ if (!need_resched && !nrpolling && (p->thread_info->cpu != smp_processor_id()))
+ smp_send_reschedule(p->thread_info->cpu);
+#else
+ set_tsk_need_resched(p);
+#endif
}
#ifdef CONFIG_SMP
@@ -236,7 +242,7 @@ repeat:
void sched_task_migrated(task_t *new_task)
{
wait_task_inactive(new_task);
- new_task->cpu = smp_processor_id();
+ new_task->thread_info->cpu = smp_processor_id();
wake_up_process(new_task);
}
@@ -299,7 +305,7 @@ void wake_up_forked_process(task_t * p)
current->sleep_avg = current->sleep_avg * PARENT_FORK_PENALTY / 100;
}
spin_lock_irq(&rq->lock);
- p->cpu = smp_processor_id();
+ p->thread_info->cpu = smp_processor_id();
activate_task(p, rq);
spin_unlock_irq(&rq->lock);
}
@@ -519,11 +525,11 @@ skip_queue:
*/
dequeue_task(next, array);
busiest->nr_running--;
- next->cpu = this_cpu;
+ next->thread_info->cpu = this_cpu;
this_rq->nr_running++;
enqueue_task(next, this_rq->active);
if (next->prio < current->prio)
- current->work.need_resched = 1;
+ set_need_resched();
if (!idle && --imbalance) {
if (array == busiest->expired) {
array = busiest->active;
@@ -572,7 +578,7 @@ void scheduler_tick(task_t *p)
#endif
/* Task might have expired already, but not scheduled off yet */
if (p->array != rq->active) {
- p->work.need_resched = 1;
+ set_tsk_need_resched(p);
return;
}
spin_lock(&rq->lock);
@@ -583,7 +589,7 @@ void scheduler_tick(task_t *p)
*/
if ((p->policy == SCHED_RR) && !--p->time_slice) {
p->time_slice = NICE_TO_TIMESLICE(p->__nice);
- p->work.need_resched = 1;
+ set_tsk_need_resched(p);
/* put it at the end of the queue: */
dequeue_task(p, rq->active);
@@ -603,7 +609,7 @@ void scheduler_tick(task_t *p)
p->sleep_avg--;
if (!--p->time_slice) {
dequeue_task(p, rq->active);
- p->work.need_resched = 1;
+ set_tsk_need_resched(p);
p->prio = effective_prio(p);
p->time_slice = NICE_TO_TIMESLICE(p->__nice);
@@ -684,7 +690,7 @@ pick_next_task:
switch_tasks:
prefetch(next);
- prev->work.need_resched = 0;
+ clear_tsk_need_resched(prev);
if (likely(prev != next)) {
rq->nr_switches++;
@@ -1203,12 +1209,12 @@ static void show_task(task_t * p)
if (p == current)
printk(" current ");
else
- printk(" %08lX ", thread_saved_pc(&p->thread));
+ printk(" %08lX ", thread_saved_pc(p->thread_info));
#else
if (p == current)
printk(" current task ");
else
- printk(" %016lx ", thread_saved_pc(&p->thread));
+ printk(" %016lx ", thread_saved_pc(p->thread_info));
#endif
{
unsigned long * n = (unsigned long *) (p+1);
@@ -1316,9 +1322,9 @@ void __init init_idle(task_t *idle, int cpu)
idle->array = NULL;
idle->prio = MAX_PRIO;
idle->state = TASK_RUNNING;
- idle->cpu = cpu;
+ idle->thread_info->cpu = cpu;
double_rq_unlock(idle_rq, rq);
- idle->work.need_resched = 1;
+ set_tsk_need_resched(idle);
__restore_flags(flags);
}