process.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

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