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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: process.c,v 1.35 2001/10/11 09:18:17 gniibe Exp $
  2.  *
  3.  *  linux/arch/sh/kernel/process.c
  4.  *
  5.  *  Copyright (C) 1995  Linus Torvalds
  6.  *
  7.  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  8.  */
  9. /*
  10.  * This file handles the architecture-dependent parts of process handling..
  11.  */
  12. #include <linux/unistd.h>
  13. #include <linux/slab.h>
  14. #include <asm/io.h>
  15. #include <asm/uaccess.h>
  16. #include <asm/mmu_context.h>
  17. #include <asm/elf.h>
  18. static int hlt_counter=0;
  19. #define HARD_IDLE_TIMEOUT (HZ / 3)
  20. void disable_hlt(void)
  21. {
  22. hlt_counter++;
  23. }
  24. void enable_hlt(void)
  25. {
  26. hlt_counter--;
  27. }
  28. /*
  29.  * The idle loop on a uniprocessor i386..
  30.  */ 
  31. void cpu_idle(void *unused)
  32. {
  33. /* endless idle loop with no priority at all */
  34. init_idle();
  35. current->nice = 20;
  36. current->counter = -100;
  37. while (1) {
  38. if (hlt_counter) {
  39. if (current->need_resched)
  40. break;
  41. } else {
  42. __cli();
  43. while (!current->need_resched) {
  44. __sti();
  45. asm volatile("sleep" : : : "memory");
  46. __cli();
  47. }
  48. __sti();
  49. }
  50. schedule();
  51. check_pgt_cache();
  52. }
  53. }
  54. void machine_restart(char * __unused)
  55. {
  56. /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
  57. asm volatile("ldc %0, srnt"
  58.      "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
  59. }
  60. void machine_halt(void)
  61. {
  62. while (1)
  63. asm volatile("sleep" : : : "memory");
  64. }
  65. void machine_power_off(void)
  66. {
  67. }
  68. void show_regs(struct pt_regs * regs)
  69. {
  70. printk("n");
  71. printk("PC  : %08lx SP  : %08lx SR  : %08lx TEA : %08x    %sn",
  72.        regs->pc, regs->regs[15], regs->sr, ctrl_inl(MMU_TEA), print_tainted());
  73. printk("R0  : %08lx R1  : %08lx R2  : %08lx R3  : %08lxn",
  74.        regs->regs[0],regs->regs[1],
  75.        regs->regs[2],regs->regs[3]);
  76. printk("R4  : %08lx R5  : %08lx R6  : %08lx R7  : %08lxn",
  77.        regs->regs[4],regs->regs[5],
  78.        regs->regs[6],regs->regs[7]);
  79. printk("R8  : %08lx R9  : %08lx R10 : %08lx R11 : %08lxn",
  80.        regs->regs[8],regs->regs[9],
  81.        regs->regs[10],regs->regs[11]);
  82. printk("R12 : %08lx R13 : %08lx R14 : %08lxn",
  83.        regs->regs[12],regs->regs[13],
  84.        regs->regs[14]);
  85. printk("MACH: %08lx MACL: %08lx GBR : %08lx PR  : %08lxn",
  86.        regs->mach, regs->macl, regs->gbr, regs->pr);
  87. }
  88. struct task_struct * alloc_task_struct(void)
  89. {
  90. /* Get two pages */
  91. return (struct task_struct *) __get_free_pages(GFP_KERNEL,1);
  92. }
  93. void free_task_struct(struct task_struct *p)
  94. {
  95. free_pages((unsigned long) p, 1);
  96. }
  97. /*
  98.  * Create a kernel thread
  99.  */
  100. /*
  101.  * This is the mechanism for creating a new kernel thread.
  102.  *
  103.  */
  104. int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  105. { /* Don't use this in BL=1(cli).  Or else, CPU resets! */
  106. register unsigned long __sc0 __asm__ ("r0");
  107. register unsigned long __sc3 __asm__ ("r3") = __NR_clone;
  108. register unsigned long __sc4 __asm__ ("r4") = (long) flags | CLONE_VM;
  109. register unsigned long __sc5 __asm__ ("r5") = 0;
  110. register unsigned long __sc8 __asm__ ("r8") = (long) arg;
  111. register unsigned long __sc9 __asm__ ("r9") = (long) fn;
  112. __asm__("trapa #0x12nt"  /* Linux/SH system call */
  113. "tst r0, r0nt" /* child or parent? */
  114. "bf 1fnt" /* parent - jump */
  115. "jsr @r9nt" /* call fn */
  116. " mov r8, r4nt" /* push argument */
  117. "mov r0, r4nt" /* return value to arg of exit */
  118. "mov %1, r3nt" /* exit */
  119. "trapa #0x11n"
  120. "1:"
  121. : "=z" (__sc0)
  122. : "i" (__NR_exit), "r" (__sc3), "r" (__sc4), "r" (__sc5), 
  123.   "r" (__sc8), "r" (__sc9)
  124. : "memory", "t");
  125. return __sc0;
  126. }
  127. /*
  128.  * Free current thread data structures etc..
  129.  */
  130. void exit_thread(void)
  131. {
  132. /* Nothing to do. */
  133. }
  134. void flush_thread(void)
  135. {
  136. #if defined(__sh3__)
  137. /* do nothing */
  138. /* Possibly, set clear debug registers */
  139. #elif defined(__SH4__)
  140. struct task_struct *tsk = current;
  141. /* Forget lazy FPU state */
  142. clear_fpu(tsk);
  143. tsk->used_math = 0;
  144. #endif
  145. }
  146. void release_thread(struct task_struct *dead_task)
  147. {
  148. /* do nothing */
  149. }
  150. /* Fill in the fpu structure for a core dump.. */
  151. int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
  152. {
  153. #if defined(__SH4__)
  154. int fpvalid;
  155. struct task_struct *tsk = current;
  156. fpvalid = tsk->used_math;
  157. if (fpvalid) {
  158. unsigned long flags;
  159. save_and_cli(flags);
  160. unlazy_fpu(tsk);
  161. restore_flags(flags);
  162. memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
  163. }
  164. return fpvalid;
  165. #else
  166. return 0; /* Task didn't use the fpu at all. */
  167. #endif
  168. }
  169. asmlinkage void ret_from_fork(void);
  170. int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
  171. unsigned long unused,
  172. struct task_struct *p, struct pt_regs *regs)
  173. {
  174. struct pt_regs *childregs;
  175. #if defined(__SH4__)
  176. struct task_struct *tsk = current;
  177. if (tsk != &init_task) {
  178. unsigned long flags;
  179. save_and_cli(flags);
  180. unlazy_fpu(tsk);
  181. restore_flags(flags);
  182. p->thread.fpu = current->thread.fpu;
  183. p->used_math = tsk->used_math;
  184. }
  185. #endif
  186. childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1;
  187. *childregs = *regs;
  188. if (user_mode(regs)) {
  189. childregs->regs[15] = usp;
  190. } else {
  191. childregs->regs[15] = (unsigned long)p+2*PAGE_SIZE;
  192. }
  193. childregs->regs[0] = 0; /* Set return value for child */
  194. childregs->sr |= SR_FD; /* Invalidate FPU flag */
  195. p->thread.sp = (unsigned long) childregs;
  196. p->thread.pc = (unsigned long) ret_from_fork;
  197. return 0;
  198. }
  199. /*
  200.  * fill in the user structure for a core dump..
  201.  */
  202. void dump_thread(struct pt_regs * regs, struct user * dump)
  203. {
  204. dump->magic = CMAGIC;
  205. dump->start_code = current->mm->start_code;
  206. dump->start_data  = current->mm->start_data;
  207. dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1);
  208. dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
  209. dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT;
  210. dump->u_ssize = (current->mm->start_stack - dump->start_stack +
  211.  PAGE_SIZE - 1) >> PAGE_SHIFT;
  212. /* Debug registers will come here. */
  213. dump->regs = *regs;
  214. dump->u_fpvalid = dump_fpu(regs, &dump->fpu);
  215. }
  216. /*
  217.  * switch_to(x,y) should switch tasks from x to y.
  218.  *
  219.  */
  220. void __switch_to(struct task_struct *prev, struct task_struct *next)
  221. {
  222. #if defined(__SH4__)
  223. if (prev != &init_task) {
  224. unsigned long flags;
  225. save_and_cli(flags);
  226. unlazy_fpu(prev);
  227. restore_flags(flags);
  228. }
  229. #endif
  230. /*
  231.  * Restore the kernel mode register
  232.  *    k7 (r7_bank1)
  233.  */
  234. asm volatile("ldc %0, r7_bank"
  235.      : /* no output */
  236.      :"r" (next));
  237. }
  238. asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
  239. unsigned long r6, unsigned long r7,
  240. struct pt_regs regs)
  241. {
  242. return do_fork(SIGCHLD, regs.regs[15], &regs, 0);
  243. }
  244. asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
  245.  unsigned long r6, unsigned long r7,
  246.  struct pt_regs regs)
  247. {
  248. if (!newsp)
  249. newsp = regs.regs[15];
  250. return do_fork(clone_flags, newsp, &regs, 0);
  251. }
  252. /*
  253.  * This is trivial, and on the face of it looks like it
  254.  * could equally well be done in user mode.
  255.  *
  256.  * Not so, for quite unobvious reasons - register pressure.
  257.  * In user mode vfork() cannot have a stack frame, and if
  258.  * done by calling the "clone()" system call directly, you
  259.  * do not have enough call-clobbered registers to hold all
  260.  * the information you need.
  261.  */
  262. asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
  263.  unsigned long r6, unsigned long r7,
  264.  struct pt_regs regs)
  265. {
  266. return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs, 0);
  267. }
  268. /*
  269.  * sys_execve() executes a new program.
  270.  */
  271. asmlinkage int sys_execve(char *ufilename, char **uargv,
  272.   char **uenvp, unsigned long r7,
  273.   struct pt_regs regs)
  274. {
  275. int error;
  276. char *filename;
  277. filename = getname(ufilename);
  278. error = PTR_ERR(filename);
  279. if (IS_ERR(filename))
  280. goto out;
  281. error = do_execve(filename, uargv, uenvp, &regs);
  282. if (error == 0)
  283. current->ptrace &= ~PT_DTRACE;
  284. putname(filename);
  285. out:
  286. return error;
  287. }
  288. /*
  289.  * These bracket the sleeping functions..
  290.  */
  291. extern void scheduling_functions_start_here(void);
  292. extern void scheduling_functions_end_here(void);
  293. #define first_sched ((unsigned long) scheduling_functions_start_here)
  294. #define last_sched ((unsigned long) scheduling_functions_end_here)
  295. unsigned long get_wchan(struct task_struct *p)
  296. {
  297. unsigned long schedule_frame;
  298. unsigned long pc;
  299. if (!p || p == current || p->state == TASK_RUNNING)
  300. return 0;
  301. /*
  302.  * The same comment as on the Alpha applies here, too ...
  303.  */
  304. pc = thread_saved_pc(&p->thread);
  305. if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
  306. schedule_frame = ((unsigned long *)(long)p->thread.sp)[1];
  307. return (unsigned long)((unsigned long *)schedule_frame)[1];
  308. }
  309. return pc;
  310. }
  311. asmlinkage void print_syscall(int x)
  312. {
  313. unsigned long flags, sr;
  314. asm("stc sr, %0": "=r" (sr));
  315. save_and_cli(flags);
  316. printk("%c: %c %c, %c: SYSCALLn", (x&63)+32,
  317.        (current->flags&PF_USEDFPU)?'C':' ',
  318.        (init_task.flags&PF_USEDFPU)?'K':' ', (sr&SR_FD)?' ':'F');
  319. restore_flags(flags);
  320. }
  321. asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
  322.  unsigned long r6, unsigned long r7,
  323.  struct pt_regs regs)
  324. {
  325. /* Clear tracing.  */
  326. ctrl_outw(0, UBC_BBRA);
  327. ctrl_outw(0, UBC_BBRB);
  328. force_sig(SIGTRAP, current);
  329. }
  330. asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
  331.   unsigned long r6, unsigned long r7,
  332.   struct pt_regs regs)
  333. {
  334. regs.pc -= 2;
  335. force_sig(SIGTRAP, current);
  336. }