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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: process.c,v 1.22 2001/11/13 09:40:43 orjanf Exp $
  2.  * 
  3.  *  linux/arch/cris/kernel/process.c
  4.  *
  5.  *  Copyright (C) 1995  Linus Torvalds
  6.  *  Copyright (C) 2000, 2001  Axis Communications AB
  7.  *
  8.  *  Authors:   Bjorn Wesen (bjornw@axis.com)
  9.  *
  10.  *  $Log: process.c,v $
  11.  *  Revision 1.22  2001/11/13 09:40:43  orjanf
  12.  *  Added dump_fpu (needed for core dumps).
  13.  *
  14.  *  Revision 1.21  2001/11/12 18:26:21  pkj
  15.  *  Fixed compiler warnings.
  16.  *
  17.  *  Revision 1.20  2001/10/03 08:21:39  jonashg
  18.  *  cause_of_death does not exist if CONFIG_SVINTO_SIM is defined.
  19.  *
  20.  *  Revision 1.19  2001/09/26 11:52:54  bjornw
  21.  *  INIT_MMAP is gone in 2.4.10
  22.  *
  23.  *  Revision 1.18  2001/08/21 21:43:51  hp
  24.  *  Move last watchdog fix inside #ifdef CONFIG_ETRAX_WATCHDOG
  25.  *
  26.  *  Revision 1.17  2001/08/21 13:48:01  jonashg
  27.  *  Added fix by HP to avoid oops when doing a hard_reset_now.
  28.  *
  29.  *  Revision 1.16  2001/06/21 02:00:40  hp
  30.  *   * entry.S: Include asm/unistd.h.
  31.  *   (_sys_call_table): Use section .rodata, not .data.
  32.  *   (_kernel_thread): Move from...
  33.  *   * process.c: ... here.
  34.  *   * entryoffsets.c (VAL): Break out from...
  35.  *   (OF): Use VAL.
  36.  *   (LCLONE_VM): New asmified value from CLONE_VM.
  37.  *
  38.  *  Revision 1.15  2001/06/20 16:31:57  hp
  39.  *  Add comments to describe empty functions according to review.
  40.  *
  41.  *  Revision 1.14  2001/05/29 11:27:59  markusl
  42.  *  Fixed so that hard_reset_now will do reset even if watchdog wasn't enabled
  43.  *
  44.  *  Revision 1.13  2001/03/20 19:44:06  bjornw
  45.  *  Use the 7th syscall argument for regs instead of current_regs
  46.  *
  47.  */
  48. /*
  49.  * This file handles the architecture-dependent parts of process handling..
  50.  */
  51. #define __KERNEL_SYSCALLS__
  52. #include <stdarg.h>
  53. #include <linux/errno.h>
  54. #include <linux/sched.h>
  55. #include <linux/kernel.h>
  56. #include <linux/mm.h>
  57. #include <linux/stddef.h>
  58. #include <linux/unistd.h>
  59. #include <linux/ptrace.h>
  60. #include <linux/slab.h>
  61. #include <linux/user.h>
  62. #include <linux/a.out.h>
  63. #include <linux/elfcore.h>
  64. #include <linux/interrupt.h>
  65. #include <linux/delay.h>
  66. #include <asm/uaccess.h>
  67. #include <asm/pgtable.h>
  68. #include <asm/system.h>
  69. #include <asm/io.h>
  70. #include <asm/processor.h>
  71. #include <linux/smp.h>
  72. //#define DEBUG
  73. /*
  74.  * Initial task structure. Make this a per-architecture thing,
  75.  * because different architectures tend to have different
  76.  * alignment requirements and potentially different initial
  77.  * setup.
  78.  */
  79. static struct fs_struct init_fs = INIT_FS;
  80. static struct files_struct init_files = INIT_FILES;
  81. static struct signal_struct init_signals = INIT_SIGNALS;
  82. struct mm_struct init_mm = INIT_MM(init_mm);
  83. /*
  84.  * Initial task structure.
  85.  *
  86.  * We need to make sure that this is 8192-byte aligned due to the
  87.  * way process stacks are handled. This is done by having a special
  88.  * "init_task" linker map entry..
  89.  */
  90. union task_union init_task_union 
  91.       __attribute__((__section__(".data.init_task"))) =
  92.              { INIT_TASK(init_task_union.task) };
  93. /*
  94.  * The hlt_counter, disable_hlt and enable_hlt is just here as a hook if
  95.  * there would ever be a halt sequence (for power save when idle) with
  96.  * some largish delay when halting or resuming *and* a driver that can't
  97.  * afford that delay.  The hlt_counter would then be checked before
  98.  * executing the halt sequence, and the driver marks the unhaltable
  99.  * region by enable_hlt/disable_hlt.
  100.  */
  101. static int hlt_counter=0;
  102. void disable_hlt(void)
  103. {
  104. hlt_counter++;
  105. }
  106. void enable_hlt(void)
  107. {
  108. hlt_counter--;
  109. }
  110.  
  111. int cpu_idle(void *unused)
  112. {
  113. while(1) {
  114. current->counter = -100;
  115. schedule();
  116. }
  117. }
  118. /* if the watchdog is enabled, we can simply disable interrupts and go
  119.  * into an eternal loop, and the watchdog will reset the CPU after 0.1s
  120.  * if on the other hand the watchdog wasn't enabled, we just enable it and wait
  121.  */
  122. void hard_reset_now (void)
  123. {
  124. /*
  125.  * Don't declare this variable elsewhere.  We don't want any other
  126.  * code to know about it than the watchdog handler in entry.S and
  127.  * this code, implementing hard reset through the watchdog.
  128.  */
  129. #if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
  130. extern int cause_of_death;
  131. #endif
  132. printk("*** HARD RESET ***n");
  133. cli();
  134. #if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
  135. cause_of_death = 0xbedead;
  136. #else
  137. /* Since we dont plan to keep on reseting the watchdog,
  138.    the key can be arbitrary hence three */
  139. *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, 3) |
  140. IO_STATE(R_WATCHDOG, enable, start);
  141. #endif
  142. while(1) /* waiting for RETRIBUTION! */ ;
  143. }
  144. void machine_restart(void)
  145. {
  146. hard_reset_now();
  147. }
  148. /*
  149.  * Similar to machine_power_off, but don't shut off power.  Add code
  150.  * here to freeze the system for e.g. post-mortem debug purpose when
  151.  * possible.  This halt has nothing to do with the idle halt.
  152.  */
  153. void machine_halt(void)
  154. {
  155. }
  156. /* If or when software power-off is implemented, add code here.  */
  157. void machine_power_off(void)
  158. {
  159. }
  160. /*
  161.  * When a process does an "exec", machine state like FPU and debug
  162.  * registers need to be reset.  This is a hook function for that.
  163.  * Currently we don't have any such state to reset, so this is empty.
  164.  */
  165. void flush_thread(void)
  166. {
  167. }
  168. asmlinkage void ret_from_sys_call(void);
  169. /* setup the child's kernel stack with a pt_regs and switch_stack on it.
  170.  * it will be un-nested during _resume and _ret_from_sys_call when the
  171.  * new thread is scheduled.
  172.  *
  173.  * also setup the thread switching structure which is used to keep
  174.  * thread-specific data during _resumes.
  175.  *
  176.  */
  177. int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
  178. unsigned long unused,
  179. struct task_struct *p, struct pt_regs *regs)
  180. {
  181. struct pt_regs * childregs;
  182. struct switch_stack *swstack;
  183. /* put the pt_regs structure at the end of the new kernel stack page and fix it up
  184.  * remember that the task_struct doubles as the kernel stack for the task
  185.  */
  186. childregs = user_regs(p);
  187. *childregs = *regs;  /* struct copy of pt_regs */
  188. childregs->r10 = 0;  /* child returns 0 after a fork/clone */
  189. /* put the switch stack right below the pt_regs */
  190. swstack = ((struct switch_stack *)childregs) - 1;
  191. swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */
  192. /* we want to return into ret_from_sys_call after the _resume */
  193. swstack->return_ip = (unsigned long) ret_from_sys_call;
  194. /* fix the user-mode stackpointer */
  195. p->thread.usp = usp;
  196. /* and the kernel-mode one */
  197. p->thread.ksp = (unsigned long) swstack;
  198. #ifdef DEBUG
  199. printk("copy_thread: new regs at 0x%p, as shown below:n", childregs);
  200. show_registers(childregs);
  201. #endif
  202. return 0;
  203. }
  204. /*
  205.  * fill in the user structure for a core dump..
  206.  */
  207. void dump_thread(struct pt_regs * regs, struct user * dump)
  208. {
  209. #if 0
  210. int i;
  211. /* changed the size calculations - should hopefully work better. lbt */
  212. dump->magic = CMAGIC;
  213. dump->start_code = 0;
  214. dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
  215. dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
  216. dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
  217. dump->u_dsize -= dump->u_tsize;
  218. dump->u_ssize = 0;
  219. for (i = 0; i < 8; i++)
  220. dump->u_debugreg[i] = current->debugreg[i];  
  221. if (dump->start_stack < TASK_SIZE)
  222. dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
  223. dump->regs = *regs;
  224. dump->u_fpvalid = dump_fpu (regs, &dump->i387);
  225. #endif 
  226. }
  227. /* Fill in the fpu structure for a core dump. */
  228. int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
  229. {
  230.         return 0;
  231. }
  232. /* 
  233.  * Be aware of the "magic" 7th argument in the four system-calls below.
  234.  * They need the latest stackframe, which is put as the 7th argument by
  235.  * entry.S. The previous arguments are dummies or actually used, but need
  236.  * to be defined to reach the 7th argument.
  237.  *
  238.  * N.B.: Another method to get the stackframe is to use current_regs(). But
  239.  * it returns the latest stack-frame stacked when going from _user mode_ and
  240.  * some of these (at least sys_clone) are called from kernel-mode sometimes
  241.  * (for example during kernel_thread, above) and thus cannot use it. Thus,
  242.  * to be sure not to get any surprises, we use the method for the other calls
  243.  * as well.
  244.  */
  245. asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
  246. struct pt_regs *regs)
  247. {
  248. return do_fork(SIGCHLD, rdusp(), regs, 0);
  249. }
  250. /* if newusp is 0, we just grab the old usp */
  251. asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
  252.  long r12, long r13, long mof, long srp,
  253.  struct pt_regs *regs)
  254. {
  255. if (!newusp)
  256. newusp = rdusp();
  257. return do_fork(flags, newusp, regs, 0);
  258. }
  259. /* vfork is a system call in i386 because of register-pressure - maybe
  260.  * we can remove it and handle it in libc but we put it here until then.
  261.  */
  262. asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
  263.  struct pt_regs *regs)
  264. {
  265.         return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0);
  266. }
  267. /*
  268.  * sys_execve() executes a new program.
  269.  */
  270. asmlinkage int sys_execve(const char *fname, char **argv, char **envp,
  271.   long r13, long mof, long srp, 
  272.   struct pt_regs *regs)
  273. {
  274. int error;
  275. char *filename;
  276. filename = getname(fname);
  277. error = PTR_ERR(filename);
  278. if (IS_ERR(filename))
  279.         goto out;
  280. error = do_execve(filename, argv, envp, regs);
  281. putname(filename);
  282.  out:
  283. return error;
  284. }
  285. /*
  286.  * These bracket the sleeping functions..
  287.  */
  288. extern void scheduling_functions_start_here(void);
  289. extern void scheduling_functions_end_here(void);
  290. #define first_sched     ((unsigned long) scheduling_functions_start_here)
  291. #define last_sched      ((unsigned long) scheduling_functions_end_here)
  292. unsigned long get_wchan(struct task_struct *p)
  293. {
  294. #if 0
  295. /* YURGH. TODO. */
  296.         unsigned long ebp, esp, eip;
  297.         unsigned long stack_page;
  298.         int count = 0;
  299.         if (!p || p == current || p->state == TASK_RUNNING)
  300.                 return 0;
  301.         stack_page = (unsigned long)p;
  302.         esp = p->thread.esp;
  303.         if (!stack_page || esp < stack_page || esp > 8188+stack_page)
  304.                 return 0;
  305.         /* include/asm-i386/system.h:switch_to() pushes ebp last. */
  306.         ebp = *(unsigned long *) esp;
  307.         do {
  308.                 if (ebp < stack_page || ebp > 8184+stack_page)
  309.                         return 0;
  310.                 eip = *(unsigned long *) (ebp+4);
  311.                 if (eip < first_sched || eip >= last_sched)
  312.                         return eip;
  313.                 ebp = *(unsigned long *) ebp;
  314.         } while (count++ < 16);
  315. #endif
  316.         return 0;
  317. }
  318. #undef last_sched
  319. #undef first_sched