From: Pavel M. <pa...@uc...> - 2002-04-30 08:51:28
|
Hi! > > From: Pavel Machek [mailto:pa...@uc...] > > I mailed this few days ago. It looks small and simple to me. I'd like > > feedback if it was applied or why it was not... > > I've integrated this but I modified it, so I'm attaching the modified files > to get your opinion on if I've broken it. ;-) > > - tersified comments some > - removed the "/* NOT REACHED! */" comment, because afaics that comment is > wrong - pls explain why you added it. Ahha, I see. You are right, it is reached during suspend. What I wanted to warn about is that it is not reached during resume. I tried to put register restoring code there and got burned. > - put the new function in asm/acpi.h, instead of suspend.h. I realize you > want a non-ACPI-specific suspend but I think this patch would result in half > ACPI-specific and half non-ACPI specific CPU context save, which is not good > IMHO. (I also feel better patching files that are clearly ACPI-related.) Is > there a way to pull the saving of processor state out into a completely > non-ACPI related? Is that feasible? I believe so, swsusp is doing complete save of CPU state. I left it half-ACPI half-swsusp because it looked easier to me. > You're undoubtedly more up on the issues involved so please educate me. I'll test whether your changes work (they look like they should). Then comes the next step: adding process freezing. I found out that our hw drivers (ide) can't cope with userland throwing requests on it while we are suspending. [That's pretty logical, and it would be pretty hard for drivers to cope with concurrent userland access.] That's why I lately merged S3 and S4. Process freezing makes quite a lot of changes to a common code. Here are changes to common code I currently need for S3, plus it would need parts of suspend.h and suspend.c (not shown here). Does this look like you'd want to push it to linus, or will you somehow give me approval and I'll try my luck pushing, or do you see completely different solution? Pavel --- linux-acpi.ofic/arch/i386/kernel/signal.c Thu Apr 18 22:45:22 2002 +++ linux-acpi/arch/i386/kernel/signal.c Sun Apr 28 13:35:34 2002 @@ -21,6 +21,7 @@ #include <linux/tty.h> #include <linux/personality.h> #include <linux/binfmts.h> +#include <linux/suspend.h> #include <asm/ucontext.h> #include <asm/uaccess.h> #include <asm/i387.h> @@ -594,6 +595,11 @@ if ((regs->xcs & 3) != 3) return 1; + if (current->flags & PF_FREEZE) { + refrigerator(0); + goto no_signal; + } + if (!oldset) oldset = ¤t->blocked; @@ -701,6 +707,7 @@ return 1; } + no_signal: /* Did we come from a system call? */ if (regs->orig_eax >= 0) { /* Restart the system call - no handlers present */ --- linux-acpi.ofic/drivers/acpi/acpi_system.c Sat Apr 27 21:46:21 2002 +++ linux-acpi/drivers/acpi/acpi_system.c Sun Apr 28 21:07:43 2002 @@ -290,6 +295,8 @@ if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5) return AE_ERROR; + freeze_processes(); + /* do we have a wakeup address for S2 and S3? */ if (state == ACPI_STATE_S2 || state == ACPI_STATE_S3) { if (!acpi_wakeup_address) @@ -323,6 +332,8 @@ /* reset firmware waking vector */ acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) 0); + thaw_processes(); + return status; } --- linux-acpi.ofic/drivers/block/loop.c Thu Apr 18 22:45:31 2002 +++ linux-acpi/drivers/block/loop.c Sun Apr 28 13:35:34 2002 @@ -71,11 +71,11 @@ #include <linux/smp_lock.h> #include <linux/swap.h> #include <linux/slab.h> +#include <linux/loop.h> +#include <linux/suspend.h> #include <asm/uaccess.h> -#include <linux/loop.h> - #define MAJOR_NR LOOP_MAJOR static int max_loop = 8; @@ -550,7 +550,7 @@ atomic_inc(&lo->lo_pending); spin_unlock_irq(&lo->lo_lock); - current->flags |= PF_NOIO; + current->flags |= PF_NOIO | PF_IOTHREAD; /* * up sem, we are running --- linux-acpi.ofic/drivers/usb/storage/usb.c Tue Mar 5 21:52:43 2002 +++ linux-acpi/drivers/usb/storage/usb.c Sun Apr 28 13:35:34 2002 @@ -319,6 +319,7 @@ /* avoid getting signals */ spin_lock_irq(¤t->sigmask_lock); flush_signals(current); + current->flags |= PF_IOTHREAD; sigfillset(¤t->blocked); recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); --- linux-acpi.ofic/fs/jbd/journal.c Thu Apr 18 22:46:03 2002 +++ linux-acpi/fs/jbd/journal.c Sun Apr 28 13:35:34 2002 @@ -33,6 +33,7 @@ #include <linux/init.h> #include <linux/mm.h> #include <linux/slab.h> +#include <linux/suspend.h> #include <asm/uaccess.h> #include <linux/proc_fs.h> @@ -225,6 +226,7 @@ journal->j_commit_interval / HZ); list_add(&journal->j_all_journals, &all_journals); + current->flags |= PF_KERNTHREAD; /* And now, wait forever for commit wakeup events. */ while (1) { if (journal->j_flags & JFS_UNMOUNT) @@ -245,7 +247,15 @@ } wake_up(&journal->j_wait_done_commit); - interruptible_sleep_on(&journal->j_wait_commit); + if (current->flags & PF_FREEZE) { /* The simpler the better. Flushing journal isn't a + good idea, because that depends on threads that + may be already stopped. */ + jbd_debug(1, "Now suspending kjournald\n"); + refrigerator(PF_IOTHREAD); + jbd_debug(1, "Resuming kjournald\n"); + } else /* we assume on resume that commits are already there, + so we don't sleep */ + interruptible_sleep_on(&journal->j_wait_commit); jbd_debug(1, "kjournald wakes\n"); --- linux-acpi.ofic/fs/reiserfs/journal.c Thu Apr 25 12:51:49 2002 +++ linux-acpi/fs/reiserfs/journal.c Sun Apr 28 13:35:34 2002 @@ -58,6 +58,7 @@ #include <linux/stat.h> #include <linux/string.h> #include <linux/smp_lock.h> +#include <linux/suspend.h> /* the number of mounted filesystems. This is used to decide when to ** start and kill the commit thread @@ -1887,6 +1888,7 @@ spin_unlock_irq(¤t->sigmask_lock); sprintf(current->comm, "kreiserfsd") ; + current->flags |= PF_KERNTHREAD; lock_kernel() ; while(1) { @@ -1900,7 +1902,12 @@ break ; } wake_up(&reiserfs_commit_thread_done) ; - interruptible_sleep_on_timeout(&reiserfs_commit_thread_wait, 5 * HZ) ; +#ifdef CONFIG_SOFTWARE_SUSPEND + if (current->flags & PF_FREEZE) { + refrigerator(PF_IOTHREAD); + } else +#endif + interruptible_sleep_on_timeout(&reiserfs_commit_thread_wait, 5 * HZ) ; } unlock_kernel() ; wake_up(&reiserfs_commit_thread_done) ; --- linux-acpi.ofic/kernel/Makefile Thu Apr 18 22:46:18 2002 +++ linux-acpi/kernel/Makefile Sun Apr 28 13:35:34 2002 @@ -10,7 +10,7 @@ O_TARGET := kernel.o export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \ - printk.o platform.o + printk.o platform.o suspend.o obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ @@ -21,6 +21,7 @@ obj-$(CONFIG_MODULES) += ksyms.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra <al...@li...>, the -fno-omit-frame-pointer is --- linux-acpi.ofic/kernel/context.c Tue Mar 5 21:52:50 2002 +++ linux-acpi/kernel/context.c Sun Apr 28 13:35:34 2002 @@ -72,6 +72,7 @@ daemonize(); strcpy(curtask->comm, "keventd"); + current->flags |= PF_IOTHREAD; keventd_running = 1; keventd_task = curtask; --- linux-acpi.ofic/kernel/signal.c Thu Mar 21 11:36:11 2002 +++ linux-acpi/kernel/signal.c Sun Apr 28 13:35:34 2002 @@ -493,7 +493,7 @@ * No need to set need_resched since signal event passing * goes through ->blocked */ -static inline void signal_wake_up(struct task_struct *t) +inline void signal_wake_up(struct task_struct *t) { set_tsk_thread_flag(t,TIF_SIGPENDING); --- linux-acpi.ofic/kernel/softirq.c Thu Jan 31 23:42:30 2002 +++ linux-acpi/kernel/softirq.c Sun Apr 28 13:35:34 2002 @@ -365,6 +365,7 @@ daemonize(); set_user_nice(current, 19); + current->flags |= PF_IOTHREAD; sigfillset(¤t->blocked); /* Migrate to the right CPU */ --- linux-acpi.ofic/mm/pdflush.c Thu Apr 18 22:46:20 2002 +++ linux-acpi/mm/pdflush.c Sun Apr 28 13:35:34 2002 @@ -96,7 +96,7 @@ recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); - current->flags |= PF_FLUSHER; + current->flags |= PF_FLUSHER | PF_KERNTHREAD; my_work->fn = NULL; my_work->who = current; @@ -111,10 +111,13 @@ set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irq(&pdflush_lock); + if (current->flags & PF_FREEZE) + refrigerator(PF_IOTHREAD); schedule(); preempt_enable(); - (*my_work->fn)(my_work->arg0); + if (my_work->fn) + (*my_work->fn)(my_work->arg0); preempt_disable(); /* @@ -145,6 +148,7 @@ pdf->when_i_went_to_sleep = jiffies; /* Limit exit rate */ break; /* exeunt */ } + my_work->fn = NULL; } nr_pdflush_threads--; spin_unlock_irq(&pdflush_lock); --- linux-acpi.ofic/mm/vmscan.c Wed Apr 24 23:06:46 2002 +++ linux-acpi/mm/vmscan.c Sun Apr 28 13:35:34 2002 @@ -22,6 +22,7 @@ #include <linux/highmem.h> #include <linux/file.h> #include <linux/compiler.h> +#include <linux/suspend.h> #include <asm/pgalloc.h> #include <asm/tlbflush.h> @@ -760,18 +761,22 @@ * us from recursively trying to free more memory as we're * trying to free the first piece of memory in the first place). */ - tsk->flags |= PF_MEMALLOC; + tsk->flags |= PF_MEMALLOC | PF_KERNTHREAD; /* * Kswapd main loop. */ for (;;) { + if (current->flags & PF_FREEZE) + refrigerator(PF_IOTHREAD); __set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&kswapd_wait, &wait); mb(); - if (kswapd_can_sleep()) + if (kswapd_can_sleep()) { schedule(); + } + __set_current_state(TASK_RUNNING); remove_wait_queue(&kswapd_wait, &wait); -- (about SSSCA) "I don't say this lightly. However, I really think that the U.S. no longer is classifiable as a democracy, but rather as a plutocracy." --hpa |