Version:  2.0.40 2.2.26 2.4.37 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10

Linux/lib/syscall.c

  1 #include <linux/ptrace.h>
  2 #include <linux/sched.h>
  3 #include <linux/export.h>
  4 #include <asm/syscall.h>
  5 
  6 static int collect_syscall(struct task_struct *target, long *callno,
  7                            unsigned long args[6], unsigned int maxargs,
  8                            unsigned long *sp, unsigned long *pc)
  9 {
 10         struct pt_regs *regs;
 11 
 12         if (!try_get_task_stack(target)) {
 13                 /* Task has no stack, so the task isn't in a syscall. */
 14                 *callno = -1;
 15                 return 0;
 16         }
 17 
 18         regs = task_pt_regs(target);
 19         if (unlikely(!regs)) {
 20                 put_task_stack(target);
 21                 return -EAGAIN;
 22         }
 23 
 24         *sp = user_stack_pointer(regs);
 25         *pc = instruction_pointer(regs);
 26 
 27         *callno = syscall_get_nr(target, regs);
 28         if (*callno != -1L && maxargs > 0)
 29                 syscall_get_arguments(target, regs, 0, maxargs, args);
 30 
 31         put_task_stack(target);
 32         return 0;
 33 }
 34 
 35 /**
 36  * task_current_syscall - Discover what a blocked task is doing.
 37  * @target:             thread to examine
 38  * @callno:             filled with system call number or -1
 39  * @args:               filled with @maxargs system call arguments
 40  * @maxargs:            number of elements in @args to fill
 41  * @sp:                 filled with user stack pointer
 42  * @pc:                 filled with user PC
 43  *
 44  * If @target is blocked in a system call, returns zero with *@callno
 45  * set to the the call's number and @args filled in with its arguments.
 46  * Registers not used for system call arguments may not be available and
 47  * it is not kosher to use &struct user_regset calls while the system
 48  * call is still in progress.  Note we may get this result if @target
 49  * has finished its system call but not yet returned to user mode, such
 50  * as when it's stopped for signal handling or syscall exit tracing.
 51  *
 52  * If @target is blocked in the kernel during a fault or exception,
 53  * returns zero with *@callno set to -1 and does not fill in @args.
 54  * If so, it's now safe to examine @target using &struct user_regset
 55  * get() calls as long as we're sure @target won't return to user mode.
 56  *
 57  * Returns -%EAGAIN if @target does not remain blocked.
 58  *
 59  * Returns -%EINVAL if @maxargs is too large (maximum is six).
 60  */
 61 int task_current_syscall(struct task_struct *target, long *callno,
 62                          unsigned long args[6], unsigned int maxargs,
 63                          unsigned long *sp, unsigned long *pc)
 64 {
 65         long state;
 66         unsigned long ncsw;
 67 
 68         if (unlikely(maxargs > 6))
 69                 return -EINVAL;
 70 
 71         if (target == current)
 72                 return collect_syscall(target, callno, args, maxargs, sp, pc);
 73 
 74         state = target->state;
 75         if (unlikely(!state))
 76                 return -EAGAIN;
 77 
 78         ncsw = wait_task_inactive(target, state);
 79         if (unlikely(!ncsw) ||
 80             unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) ||
 81             unlikely(wait_task_inactive(target, state) != ncsw))
 82                 return -EAGAIN;
 83 
 84         return 0;
 85 }
 86 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us