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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1994 - 2000 by Ralf Baechle and others.
  7.  * Copyright (C) 1999 Silicon Graphics, Inc.
  8.  */
  9. #include <linux/config.h>
  10. #include <linux/errno.h>
  11. #include <linux/sched.h>
  12. #include <linux/kernel.h>
  13. #include <linux/mm.h>
  14. #include <linux/stddef.h>
  15. #include <linux/unistd.h>
  16. #include <linux/ptrace.h>
  17. #include <linux/slab.h>
  18. #include <linux/mman.h>
  19. #include <linux/sys.h>
  20. #include <linux/user.h>
  21. #include <linux/a.out.h>
  22. #include <asm/bootinfo.h>
  23. #include <asm/cpu.h>
  24. #include <asm/pgtable.h>
  25. #include <asm/system.h>
  26. #include <asm/mipsregs.h>
  27. #include <asm/processor.h>
  28. #include <asm/stackframe.h>
  29. #include <asm/uaccess.h>
  30. #include <asm/io.h>
  31. #include <asm/elf.h>
  32. #include <asm/isadep.h>
  33. void cpu_idle(void)
  34. {
  35. /* endless idle loop with no priority at all */
  36. current->nice = 20;
  37. current->counter = -100;
  38. init_idle();
  39. while (1) {
  40. while (!current->need_resched)
  41. if (cpu_wait)
  42. (*cpu_wait)();
  43. schedule();
  44. check_pgt_cache();
  45. }
  46. }
  47. struct task_struct *last_task_used_math = NULL;
  48. asmlinkage void ret_from_fork(void);
  49. void exit_thread(void)
  50. {
  51. /* Forget lazy fpu state */
  52. if (last_task_used_math == current) {
  53. set_cp0_status(ST0_CU1);
  54. __asm__ __volatile__("cfc1t$0,$31");
  55. last_task_used_math = NULL;
  56. }
  57. }
  58. void flush_thread(void)
  59. {
  60. /* Forget lazy fpu state */
  61. if (last_task_used_math == current) {
  62. set_cp0_status(ST0_CU1);
  63. __asm__ __volatile__("cfc1t$0,$31");
  64. last_task_used_math = NULL;
  65. }
  66. }
  67. int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
  68.  unsigned long unused,
  69.                  struct task_struct * p, struct pt_regs * regs)
  70. {
  71. struct pt_regs * childregs;
  72. long childksp;
  73. extern void save_fp(void*);
  74. childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
  75. if (last_task_used_math == current)
  76. if (mips_cpu.options & MIPS_CPU_FPU) {
  77. set_cp0_status(ST0_CU1);
  78. save_fp(p);
  79. }
  80. /* set up new TSS. */
  81. childregs = (struct pt_regs *) childksp - 1;
  82. *childregs = *regs;
  83. childregs->regs[7] = 0; /* Clear error flag */
  84. if(current->personality == PER_LINUX) {
  85. childregs->regs[2] = 0; /* Child gets zero as return value */
  86. regs->regs[2] = p->pid;
  87. } else {
  88. /* Under IRIX things are a little different. */
  89. childregs->regs[2] = 0;
  90. childregs->regs[3] = 1;
  91. regs->regs[2] = p->pid;
  92. regs->regs[3] = 0;
  93. }
  94. if (childregs->cp0_status & ST0_CU0) {
  95. childregs->regs[28] = (unsigned long) p;
  96. childregs->regs[29] = childksp;
  97. p->thread.current_ds = KERNEL_DS;
  98. } else {
  99. childregs->regs[29] = usp;
  100. p->thread.current_ds = USER_DS;
  101. }
  102. p->thread.reg29 = (unsigned long) childregs;
  103. p->thread.reg31 = (unsigned long) ret_from_fork;
  104. /*
  105.  * New tasks loose permission to use the fpu. This accelerates context
  106.  * switching for most programs since they don't use the fpu.
  107.  */
  108. p->thread.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
  109.                             ~(ST0_CU2|ST0_CU1|KU_MASK);
  110. childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
  111. return 0;
  112. }
  113. /* Fill in the fpu structure for a core dump.. */
  114. int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
  115. {
  116. /* We actually store the FPU info in the task->thread
  117.  * area.
  118.  */
  119. if(regs->cp0_status & ST0_CU1) {
  120. memcpy(r, &current->thread.fpu, sizeof(current->thread.fpu));
  121. return 1;
  122. }
  123. return 0; /* Task didn't use the fpu at all. */
  124. }
  125. /* Fill in the user structure for a core dump.. */
  126. void dump_thread(struct pt_regs *regs, struct user *dump)
  127. {
  128. dump->magic = CMAGIC;
  129. dump->start_code  = current->mm->start_code;
  130. dump->start_data  = current->mm->start_data;
  131. dump->start_stack = regs->regs[29] & ~(PAGE_SIZE - 1);
  132. dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
  133. dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) >> PAGE_SHIFT;
  134. dump->u_ssize =
  135. (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT;
  136. memcpy(&dump->regs[0], regs, sizeof(struct pt_regs));
  137. memcpy(&dump->regs[EF_SIZE/4], &current->thread.fpu, sizeof(current->thread.fpu));
  138. }
  139. /*
  140.  * Create a kernel thread
  141.  */
  142. int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  143. {
  144. long retval;
  145. __asm__ __volatile__(
  146. ".set noreorder               n"
  147. "    move    $6,$sp           n"
  148. "    move    $4,%5            n"
  149. "    li      $2,%1            n"
  150. "    syscall                  n"
  151. "    beq     $6,$sp,1f        n"
  152. "    subu    $sp,32           n" /* delay slot */
  153. "    jalr    %4               n"
  154. "    move    $4,%3            n" /* delay slot */
  155. "    move    $4,$2            n"
  156. "    li      $2,%2            n"
  157. "    syscall                  n"
  158. "1:  addiu   $sp,32           n"
  159. "    move    %0,$2            n"
  160. ".set reorder"
  161. :"=r" (retval)
  162. :"i" (__NR_clone), "i" (__NR_exit),
  163.  "r" (arg), "r" (fn),
  164.  "r" (flags | CLONE_VM)
  165.  /*
  166.   * The called subroutine might have destroyed any of the
  167.   * at, result, argument or temporary registers ...
  168.   */
  169. :"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
  170.  "$9","$10","$11","$12","$13","$14","$15","$24","$25");
  171. return retval;
  172. }
  173. /*
  174.  * These bracket the sleeping functions..
  175.  */
  176. extern void scheduling_functions_start_here(void);
  177. extern void scheduling_functions_end_here(void);
  178. #define first_sched ((unsigned long) scheduling_functions_start_here)
  179. #define last_sched ((unsigned long) scheduling_functions_end_here)
  180. /* get_wchan - a maintenance nightmare ...  */
  181. unsigned long get_wchan(struct task_struct *p)
  182. {
  183. unsigned long frame, pc;
  184. if (!p || p == current || p->state == TASK_RUNNING)
  185. return 0;
  186. pc = thread_saved_pc(&p->thread);
  187. if (pc < first_sched || pc >= last_sched) {
  188. return pc;
  189. }
  190. if (pc >= (unsigned long) sleep_on_timeout)
  191. goto schedule_timeout_caller;
  192. if (pc >= (unsigned long) sleep_on)
  193. goto schedule_caller;
  194. if (pc >= (unsigned long) interruptible_sleep_on_timeout)
  195. goto schedule_timeout_caller;
  196. if (pc >= (unsigned long)interruptible_sleep_on)
  197. goto schedule_caller;
  198. goto schedule_timeout_caller;
  199. schedule_caller:
  200. frame = ((unsigned long *)p->thread.reg30)[9];
  201. pc    = ((unsigned long *)frame)[11];
  202. return pc;
  203. schedule_timeout_caller:
  204. /* Must be schedule_timeout ...  */
  205. pc    = ((unsigned long *)p->thread.reg30)[10];
  206. frame = ((unsigned long *)p->thread.reg30)[9];
  207. /* The schedule_timeout frame ...  */
  208. pc    = ((unsigned long *)frame)[14];
  209. frame = ((unsigned long *)frame)[13];
  210. if (pc >= first_sched && pc < last_sched) {
  211. /* schedule_timeout called by interruptible_sleep_on_timeout */
  212. pc    = ((unsigned long *)frame)[11];
  213. frame = ((unsigned long *)frame)[10];
  214. }
  215. return pc;
  216. }