background.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * JFFS2 -- Journalling Flash File System, Version 2.
  3.  *
  4.  * Copyright (C) 2001 Red Hat, Inc.
  5.  *
  6.  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  7.  *
  8.  * The original JFFS, from which the design for JFFS2 was derived,
  9.  * was designed and implemented by Axis Communications AB.
  10.  *
  11.  * The contents of this file are subject to the Red Hat eCos Public
  12.  * License Version 1.1 (the "Licence"); you may not use this file
  13.  * except in compliance with the Licence.  You may obtain a copy of
  14.  * the Licence at http://www.redhat.com/
  15.  *
  16.  * Software distributed under the Licence is distributed on an "AS IS"
  17.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
  18.  * See the Licence for the specific language governing rights and
  19.  * limitations under the Licence.
  20.  *
  21.  * The Original Code is JFFS2 - Journalling Flash File System, version 2
  22.  *
  23.  * Alternatively, the contents of this file may be used under the
  24.  * terms of the GNU General Public License version 2 (the "GPL"), in
  25.  * which case the provisions of the GPL are applicable instead of the
  26.  * above.  If you wish to allow the use of your version of this file
  27.  * only under the terms of the GPL and not to allow others to use your
  28.  * version of this file under the RHEPL, indicate your decision by
  29.  * deleting the provisions above and replace them with the notice and
  30.  * other provisions required by the GPL.  If you do not delete the
  31.  * provisions above, a recipient may use your version of this file
  32.  * under either the RHEPL or the GPL.
  33.  *
  34.  * $Id: background.c,v 1.16 2001/10/08 09:22:38 dwmw2 Exp $
  35.  *
  36.  */
  37. #define __KERNEL_SYSCALLS__
  38. #include <linux/kernel.h>
  39. #include <linux/sched.h>
  40. #include <linux/unistd.h>
  41. #include <linux/jffs2.h>
  42. #include <linux/mtd/mtd.h>
  43. #include <linux/interrupt.h>
  44. #include <linux/completion.h>
  45. #include "nodelist.h"
  46. static int jffs2_garbage_collect_thread(void *);
  47. static int thread_should_wake(struct jffs2_sb_info *c);
  48. void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
  49. {
  50. spin_lock_bh(&c->erase_completion_lock);
  51.         if (c->gc_task && thread_should_wake(c))
  52.                 send_sig(SIGHUP, c->gc_task, 1);
  53. spin_unlock_bh(&c->erase_completion_lock);
  54. }
  55. /* This must only ever be called when no GC thread is currently running */
  56. int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
  57. {
  58. pid_t pid;
  59. int ret = 0;
  60. if (c->gc_task)
  61. BUG();
  62. init_MUTEX_LOCKED(&c->gc_thread_start);
  63. init_completion(&c->gc_thread_exit);
  64. pid = kernel_thread(jffs2_garbage_collect_thread, c, CLONE_FS|CLONE_FILES);
  65. if (pid < 0) {
  66. printk(KERN_WARNING "fork failed for JFFS2 garbage collect thread: %dn", -pid);
  67. complete(&c->gc_thread_exit);
  68. ret = pid;
  69. } else {
  70. /* Wait for it... */
  71. D1(printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %dn", pid));
  72. down(&c->gc_thread_start);
  73. }
  74.  
  75. return ret;
  76. }
  77. void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
  78. {
  79. spin_lock_bh(&c->erase_completion_lock);
  80. if (c->gc_task) {
  81. D1(printk(KERN_DEBUG "jffs2: Killing GC task %dn", c->gc_task->pid));
  82. send_sig(SIGKILL, c->gc_task, 1);
  83. }
  84. spin_unlock_bh(&c->erase_completion_lock);
  85. wait_for_completion(&c->gc_thread_exit);
  86. }
  87. static int jffs2_garbage_collect_thread(void *_c)
  88. {
  89. struct jffs2_sb_info *c = _c;
  90. daemonize();
  91. current->tty = NULL;
  92. c->gc_task = current;
  93. up(&c->gc_thread_start);
  94.         sprintf(current->comm, "jffs2_gcd_mtd%d", c->mtd->index);
  95. /* FIXME in the 2.2 backport */
  96. current->nice = 10;
  97. for (;;) {
  98. spin_lock_irq(&current->sigmask_lock);
  99. siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
  100. recalc_sigpending();
  101. spin_unlock_irq(&current->sigmask_lock);
  102. if (!thread_should_wake(c)) {
  103.                         set_current_state (TASK_INTERRUPTIBLE);
  104. D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...n"));
  105. /* Yes, there's a race here; we checked thread_should_wake() before
  106.    setting current->state to TASK_INTERRUPTIBLE. But it doesn't
  107.    matter - We don't care if we miss a wakeup, because the GC thread
  108.    is only an optimisation anyway. */
  109. schedule();
  110. }
  111.                 
  112. if (current->need_resched)
  113. schedule();
  114.                 /* Put_super will send a SIGKILL and then wait on the sem. 
  115.                  */
  116.                 while (signal_pending(current)) {
  117.                         siginfo_t info;
  118.                         unsigned long signr;
  119.                         spin_lock_irq(&current->sigmask_lock);
  120.                         signr = dequeue_signal(&current->blocked, &info);
  121.                         spin_unlock_irq(&current->sigmask_lock);
  122.                         switch(signr) {
  123.                         case SIGSTOP:
  124.                                 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGSTOP received.n"));
  125.                                 set_current_state(TASK_STOPPED);
  126.                                 schedule();
  127.                                 break;
  128.                         case SIGKILL:
  129.                                 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.n"));
  130. spin_lock_bh(&c->erase_completion_lock);
  131.                                 c->gc_task = NULL;
  132. spin_unlock_bh(&c->erase_completion_lock);
  133. complete_and_exit(&c->gc_thread_exit, 0);
  134. case SIGHUP:
  135. D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGHUP received.n"));
  136. break;
  137. default:
  138. D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld receivedn", signr));
  139.                         }
  140.                 }
  141. /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */
  142. spin_lock_irq(&current->sigmask_lock);
  143. siginitsetinv (&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
  144. recalc_sigpending();
  145. spin_unlock_irq(&current->sigmask_lock);
  146. D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): passn"));
  147. jffs2_garbage_collect_pass(c);
  148. }
  149. }
  150. static int thread_should_wake(struct jffs2_sb_info *c)
  151. {
  152. D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%xn", 
  153.   c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size));
  154. if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER &&
  155.     c->dirty_size > c->sector_size)
  156. return 1;
  157. else 
  158. return 0;
  159. }