Deleted Added
full compact
kern_procctl.c (84483) kern_procctl.c (84637)
1/*
2 * Copyright (c) 1994, Sean Eric Fagan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 14 unchanged lines hidden (view full) ---

23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
1/*
2 * Copyright (c) 1994, Sean Eric Fagan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 14 unchanged lines hidden (view full) ---

23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $FreeBSD: head/sys/kern/sys_process.c 84483 2001-10-04 16:35:44Z des $
31 * $FreeBSD: head/sys/kern/sys_process.c 84637 2001-10-07 20:08:42Z des $
32 */
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/sysproto.h>
39#include <sys/proc.h>
40#include <sys/vnode.h>
41#include <sys/ptrace.h>
42#include <sys/sx.h>
43#include <sys/user.h>
44
45#include <machine/reg.h>
46
47#include <vm/vm.h>
32 */
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/sysproto.h>
39#include <sys/proc.h>
40#include <sys/vnode.h>
41#include <sys/ptrace.h>
42#include <sys/sx.h>
43#include <sys/user.h>
44
45#include <machine/reg.h>
46
47#include <vm/vm.h>
48#include <vm/vm_param.h>
48#include <vm/pmap.h>
49#include <vm/pmap.h>
50#include <vm/vm_extern.h>
49#include <vm/vm_map.h>
51#include <vm/vm_map.h>
52#include <vm/vm_kern.h>
53#include <vm/vm_object.h>
50#include <vm/vm_page.h>
51
54#include <vm/vm_page.h>
55
52#include <fs/procfs/procfs.h>
53
54/* use the equivalent procfs code */
55#if 0
56static int
57pread(struct proc *procp, unsigned int addr, unsigned int *retval)
56int
57proc_rwmem(struct proc *p, struct uio *uio)
58{
58{
59 int rv;
60 vm_map_t map, tmap;
61 vm_object_t object;
62 vm_offset_t kva = 0;
63 int page_offset; /* offset into page */
64 vm_offset_t pageno; /* page number */
65 vm_map_entry_t out_entry;
66 vm_prot_t out_prot;
67 boolean_t wired;
68 vm_pindex_t pindex;
59 struct vmspace *vm;
60 vm_map_t map;
61 vm_object_t object = NULL;
62 vm_offset_t pageno = 0; /* page number */
63 vm_prot_t reqprot;
64 vm_offset_t kva;
65 int error;
66 int writing;
69
67
70 /* Map page into kernel space */
68 GIANT_REQUIRED;
71
69
72 map = &procp->p_vmspace->vm_map;
70 /*
71 * if the vmspace is in the midst of being deallocated or the
72 * process is exiting, don't try to grab anything. The page table
73 * usage in that process can be messed up.
74 */
75 vm = p->p_vmspace;
76 if ((p->p_flag & P_WEXIT))
77 return (EFAULT);
78 if (vm->vm_refcnt < 1)
79 return (EFAULT);
80 ++vm->vm_refcnt;
81 /*
82 * The map we want...
83 */
84 map = &vm->vm_map;
73
85
74 page_offset = addr - trunc_page(addr);
75 pageno = trunc_page(addr);
86 writing = uio->uio_rw == UIO_WRITE;
87 reqprot = writing ? (VM_PROT_WRITE | VM_PROT_OVERRIDE_WRITE) :
88 VM_PROT_READ;
76
89
77 tmap = map;
78 rv = vm_map_lookup(&tmap, pageno, VM_PROT_READ, &out_entry,
79 &object, &pindex, &out_prot, &wired);
90 kva = kmem_alloc_pageable(kernel_map, PAGE_SIZE);
80
91
81 if (rv != KERN_SUCCESS)
82 return (EINVAL);
92 /*
93 * Only map in one page at a time. We don't have to, but it
94 * makes things easier. This way is trivial - right?
95 */
96 do {
97 vm_map_t tmap;
98 vm_offset_t uva;
99 int page_offset; /* offset into page */
100 vm_map_entry_t out_entry;
101 vm_prot_t out_prot;
102 boolean_t wired;
103 vm_pindex_t pindex;
104 u_int len;
105 vm_page_t m;
83
106
84 vm_map_lookup_done(tmap, out_entry);
107 object = NULL;
85
108
86 /* Find space in kernel_map for the page we're interested in */
87 rv = vm_map_find(kernel_map, object, IDX_TO_OFF(pindex),
88 &kva, PAGE_SIZE, 0, VM_PROT_ALL, VM_PROT_ALL, 0);
109 uva = (vm_offset_t)uio->uio_offset;
89
110
90 if (!rv) {
91 vm_object_reference(object);
111 /*
112 * Get the page number of this segment.
113 */
114 pageno = trunc_page(uva);
115 page_offset = uva - pageno;
92
116
93 rv = vm_map_pageable(kernel_map, kva, kva + PAGE_SIZE, 0);
94 if (!rv) {
95 *retval = 0;
96 bcopy((caddr_t)kva + page_offset,
97 retval, sizeof *retval);
117 /*
118 * How many bytes to copy
119 */
120 len = min(PAGE_SIZE - page_offset, uio->uio_resid);
121
122 /*
123 * Fault the page on behalf of the process
124 */
125 error = vm_fault(map, pageno, reqprot, VM_FAULT_NORMAL);
126 if (error) {
127 error = EFAULT;
128 break;
98 }
129 }
99 vm_map_remove(kernel_map, kva, kva + PAGE_SIZE);
100 }
101
130
102 return (rv);
103}
131 /*
132 * Now we need to get the page. out_entry, out_prot, wired,
133 * and single_use aren't used. One would think the vm code
134 * would be a *bit* nicer... We use tmap because
135 * vm_map_lookup() can change the map argument.
136 */
137 tmap = map;
138 error = vm_map_lookup(&tmap, pageno, reqprot, &out_entry,
139 &object, &pindex, &out_prot, &wired);
104
140
105static int
106pwrite(struct proc *procp, unsigned int addr, unsigned int datum)
107{
108 int rv;
109 vm_map_t map, tmap;
110 vm_object_t object;
111 vm_offset_t kva = 0;
112 int page_offset; /* offset into page */
113 vm_offset_t pageno; /* page number */
114 vm_map_entry_t out_entry;
115 vm_prot_t out_prot;
116 boolean_t wired;
117 vm_pindex_t pindex;
118 boolean_t fix_prot = 0;
141 if (error) {
142 error = EFAULT;
119
143
120 /* Map page into kernel space */
144 /*
145 * Make sure that there is no residue in 'object' from
146 * an error return on vm_map_lookup.
147 */
148 object = NULL;
121
149
122 map = &procp->p_vmspace->vm_map;
150 break;
151 }
123
152
124 page_offset = addr - trunc_page(addr);
125 pageno = trunc_page(addr);
153 m = vm_page_lookup(object, pindex);
126
154
127 /*
128 * Check the permissions for the area we're interested in.
129 */
155 /* Allow fallback to backing objects if we are reading */
130
156
131 if (vm_map_check_protection(map, pageno, pageno + PAGE_SIZE,
132 VM_PROT_WRITE) == FALSE) {
157 while (m == NULL && !writing && object->backing_object) {
158
159 pindex += OFF_TO_IDX(object->backing_object_offset);
160 object = object->backing_object;
161
162 m = vm_page_lookup(object, pindex);
163 }
164
165 if (m == NULL) {
166 error = EFAULT;
167
168 /*
169 * Make sure that there is no residue in 'object' from
170 * an error return on vm_map_lookup.
171 */
172 object = NULL;
173
174 vm_map_lookup_done(tmap, out_entry);
175
176 break;
177 }
178
133 /*
179 /*
134 * If the page was not writable, we make it so.
135 * XXX It is possible a page may *not* be read/executable,
136 * if a process changes that!
180 * Wire the page into memory
137 */
181 */
138 fix_prot = 1;
139 /* The page isn't writable, so let's try making it so... */
140 if ((rv = vm_map_protect(map, pageno, pageno + PAGE_SIZE,
141 VM_PROT_ALL, 0)) != KERN_SUCCESS)
142 return (EFAULT); /* I guess... */
143 }
182 vm_page_wire(m);
144
183
145 /*
146 * Now we need to get the page. out_entry, out_prot, wired, and
147 * single_use aren't used. One would think the vm code would be
148 * a *bit* nicer... We use tmap because vm_map_lookup() can
149 * change the map argument.
150 */
184 /*
185 * We're done with tmap now.
186 * But reference the object first, so that we won't loose
187 * it.
188 */
189 vm_object_reference(object);
190 vm_map_lookup_done(tmap, out_entry);
151
191
152 tmap = map;
153 rv = vm_map_lookup(&tmap, pageno, VM_PROT_WRITE, &out_entry,
154 &object, &pindex, &out_prot, &wired);
155 if (rv != KERN_SUCCESS) {
156 return (EINVAL);
157 }
192 pmap_kenter(kva, VM_PAGE_TO_PHYS(m));
158
193
159 /*
160 * Okay, we've got the page. Let's release tmap.
161 */
194 /*
195 * Now do the i/o move.
196 */
197 error = uiomove((caddr_t)(kva + page_offset), len, uio);
162
198
163 vm_map_lookup_done(tmap, out_entry);
199 pmap_kremove(kva);
164
200
165 /*
166 * Fault the page in...
167 */
201 /*
202 * release the page and the object
203 */
204 vm_page_unwire(m, 1);
205 vm_object_deallocate(object);
168
206
169 rv = vm_fault(map, pageno, VM_PROT_WRITE|VM_PROT_READ, FALSE);
170 if (rv != KERN_SUCCESS)
171 return (EFAULT);
207 object = NULL;
172
208
173 /* Find space in kernel_map for the page we're interested in */
174 rv = vm_map_find(kernel_map, object, IDX_TO_OFF(pindex),
175 &kva, PAGE_SIZE, 0,
176 VM_PROT_ALL, VM_PROT_ALL, 0);
177 if (!rv) {
178 vm_object_reference(object);
209 } while (error == 0 && uio->uio_resid > 0);
179
210
180 rv = vm_map_pageable(kernel_map, kva, kva + PAGE_SIZE, 0);
181 if (!rv) {
182 bcopy(&datum, (caddr_t)kva + page_offset, sizeof datum);
183 }
184 vm_map_remove(kernel_map, kva, kva + PAGE_SIZE);
185 }
211 if (object)
212 vm_object_deallocate(object);
186
213
187 if (fix_prot)
188 vm_map_protect(map, pageno, pageno + PAGE_SIZE,
189 VM_PROT_READ|VM_PROT_EXECUTE, 0);
190 return (rv);
214 kmem_free(kernel_map, kva, PAGE_SIZE);
215 vmspace_free(vm);
216 return (error);
191}
217}
192#endif
193
194/*
195 * Process debugging system call.
196 */
197#ifndef _SYS_SYSPROTO_H_
198struct ptrace_args {
199 int req;
200 pid_t pid;
201 caddr_t addr;
202 int data;
203};
204#endif
205
206int
218
219/*
220 * Process debugging system call.
221 */
222#ifndef _SYS_SYSPROTO_H_
223struct ptrace_args {
224 int req;
225 pid_t pid;
226 caddr_t addr;
227 int data;
228};
229#endif
230
231int
207ptrace(td, uap)
208 struct thread *td;
209 struct ptrace_args *uap;
232ptrace(struct thread *td, struct ptrace_args *uap)
210{
211 struct proc *curp = td->td_proc;
212 struct proc *p;
213 struct iovec iov;
214 struct uio uio;
233{
234 struct proc *curp = td->td_proc;
235 struct proc *p;
236 struct iovec iov;
237 struct uio uio;
238 union {
239 struct reg reg;
240 struct dbreg dbreg;
241 struct fpreg fpreg;
242 } r;
215 int error = 0;
216 int write;
217
218 write = 0;
219 if (uap->req == PT_TRACE_ME) {
220 p = curp;
221 PROC_LOCK(p);
222 } else {
223 if ((p = pfind(uap->pid)) == NULL)
224 return (ESRCH);
225 }
226 if (p_cansee(curp, p)) {
227 PROC_UNLOCK(p);
228 return (ESRCH);
229 }
230
243 int error = 0;
244 int write;
245
246 write = 0;
247 if (uap->req == PT_TRACE_ME) {
248 p = curp;
249 PROC_LOCK(p);
250 } else {
251 if ((p = pfind(uap->pid)) == NULL)
252 return (ESRCH);
253 }
254 if (p_cansee(curp, p)) {
255 PROC_UNLOCK(p);
256 return (ESRCH);
257 }
258
259 if ((error = p_candebug(curp, p)) != 0) {
260 PROC_UNLOCK(p);
261 return (error);
262 }
263
231 /*
264 /*
265 * Don't debug system processes!
266 */
267 if ((p->p_flag & P_SYSTEM) != 0) {
268 PROC_UNLOCK(p);
269 return (EINVAL);
270 }
271
272 /*
232 * Permissions check
233 */
234 switch (uap->req) {
235 case PT_TRACE_ME:
236 /* Always legal. */
237 break;
238
239 case PT_ATTACH:

--- 4 unchanged lines hidden (view full) ---

244 }
245
246 /* Already traced */
247 if (p->p_flag & P_TRACED) {
248 PROC_UNLOCK(p);
249 return (EBUSY);
250 }
251
273 * Permissions check
274 */
275 switch (uap->req) {
276 case PT_TRACE_ME:
277 /* Always legal. */
278 break;
279
280 case PT_ATTACH:

--- 4 unchanged lines hidden (view full) ---

285 }
286
287 /* Already traced */
288 if (p->p_flag & P_TRACED) {
289 PROC_UNLOCK(p);
290 return (EBUSY);
291 }
292
252 if ((error = p_candebug(curp, p))) {
253 PROC_UNLOCK(p);
254 return (error);
255 }
256
257 /* OK */
258 break;
259
260 case PT_READ_I:
261 case PT_READ_D:
262 case PT_WRITE_I:
263 case PT_WRITE_D:
264 case PT_CONTINUE:

--- 164 unchanged lines hidden (view full) ---

429 iov.iov_len = sizeof(int);
430 uio.uio_iov = &iov;
431 uio.uio_iovcnt = 1;
432 uio.uio_offset = (off_t)(uintptr_t)uap->addr;
433 uio.uio_resid = sizeof(int);
434 uio.uio_segflg = UIO_SYSSPACE; /* ie: the uap */
435 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
436 uio.uio_td = td;
293 /* OK */
294 break;
295
296 case PT_READ_I:
297 case PT_READ_D:
298 case PT_WRITE_I:
299 case PT_WRITE_D:
300 case PT_CONTINUE:

--- 164 unchanged lines hidden (view full) ---

465 iov.iov_len = sizeof(int);
466 uio.uio_iov = &iov;
467 uio.uio_iovcnt = 1;
468 uio.uio_offset = (off_t)(uintptr_t)uap->addr;
469 uio.uio_resid = sizeof(int);
470 uio.uio_segflg = UIO_SYSSPACE; /* ie: the uap */
471 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
472 uio.uio_td = td;
437 error = procfs_domem(curp, p, NULL, &uio);
473 error = proc_rwmem(p, &uio);
438 if (uio.uio_resid != 0) {
439 /*
474 if (uio.uio_resid != 0) {
475 /*
440 * XXX procfs_domem() doesn't currently return ENOSPC,
476 * XXX proc_rwmem() doesn't currently return ENOSPC,
441 * so I think write() can bogusly return 0.
442 * XXX what happens for short writes? We don't want
443 * to write partial data.
477 * so I think write() can bogusly return 0.
478 * XXX what happens for short writes? We don't want
479 * to write partial data.
444 * XXX procfs_domem() returns EPERM for other invalid
480 * XXX proc_rwmem() returns EPERM for other invalid
445 * addresses. Convert this to EINVAL. Does this
446 * clobber returns of EPERM for other reasons?
447 */
448 if (error == 0 || error == ENOSPC || error == EPERM)
449 error = EINVAL; /* EOF */
450 }
451 return (error);
452
453 case PT_KILL:
454 uap->data = SIGKILL;
455 goto sendsig; /* in PT_CONTINUE above */
456
457#ifdef PT_SETREGS
458 case PT_SETREGS:
481 * addresses. Convert this to EINVAL. Does this
482 * clobber returns of EPERM for other reasons?
483 */
484 if (error == 0 || error == ENOSPC || error == EPERM)
485 error = EINVAL; /* EOF */
486 }
487 return (error);
488
489 case PT_KILL:
490 uap->data = SIGKILL;
491 goto sendsig; /* in PT_CONTINUE above */
492
493#ifdef PT_SETREGS
494 case PT_SETREGS:
459 write = 1;
460 /* fallthrough */
495 error = copyin(uap->addr, &r.reg, sizeof r.reg);
496 if (error == 0) {
497 PHOLD(p);
498 error = procfs_write_regs(&p->p_thread, &r.reg);
499 PRELE(p);
500 }
501 return (error);
461#endif /* PT_SETREGS */
502#endif /* PT_SETREGS */
503
462#ifdef PT_GETREGS
463 case PT_GETREGS:
504#ifdef PT_GETREGS
505 case PT_GETREGS:
464 /* write = 0 above */
506 PHOLD(p);
507 error = procfs_read_regs(&p->p_thread, &r.reg);
508 PRELE(p);
509 if (error == 0)
510 error = copyout(&r.reg, uap->addr, sizeof r.reg);
511 return (error);
465#endif /* PT_SETREGS */
512#endif /* PT_SETREGS */
466#if defined(PT_SETREGS) || defined(PT_GETREGS)
467 if (!procfs_validregs(td)) /* no P_SYSTEM procs please */
468 return (EINVAL);
469 else {
470 iov.iov_base = uap->addr;
471 iov.iov_len = sizeof(struct reg);
472 uio.uio_iov = &iov;
473 uio.uio_iovcnt = 1;
474 uio.uio_offset = 0;
475 uio.uio_resid = sizeof(struct reg);
476 uio.uio_segflg = UIO_USERSPACE;
477 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
478 uio.uio_td = td;
479 return (procfs_doregs(curp, p, NULL, &uio));
480 }
481#endif /* defined(PT_SETREGS) || defined(PT_GETREGS) */
482
483#ifdef PT_SETFPREGS
484 case PT_SETFPREGS:
513
514#ifdef PT_SETFPREGS
515 case PT_SETFPREGS:
485 write = 1;
486 /* fallthrough */
516 error = copyin(uap->addr, &r.fpreg, sizeof r.fpreg);
517 if (error == 0) {
518 PHOLD(p);
519 error = procfs_write_fpregs(&p->p_thread, &r.fpreg);
520 PRELE(p);
521 }
522 return (error);
487#endif /* PT_SETFPREGS */
523#endif /* PT_SETFPREGS */
524
488#ifdef PT_GETFPREGS
489 case PT_GETFPREGS:
525#ifdef PT_GETFPREGS
526 case PT_GETFPREGS:
490 /* write = 0 above */
527 PHOLD(p);
528 error = procfs_read_fpregs(&p->p_thread, &r.fpreg);
529 PRELE(p);
530 if (error == 0)
531 error = copyout(&r.fpreg, uap->addr, sizeof r.fpreg);
532 return (error);
491#endif /* PT_SETFPREGS */
533#endif /* PT_SETFPREGS */
492#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
493 if (!procfs_validfpregs(td)) /* no P_SYSTEM procs please */
494 return (EINVAL);
495 else {
496 iov.iov_base = uap->addr;
497 iov.iov_len = sizeof(struct fpreg);
498 uio.uio_iov = &iov;
499 uio.uio_iovcnt = 1;
500 uio.uio_offset = 0;
501 uio.uio_resid = sizeof(struct fpreg);
502 uio.uio_segflg = UIO_USERSPACE;
503 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
504 uio.uio_td = td;
505 return (procfs_dofpregs(curp, p, NULL, &uio));
506 }
507#endif /* defined(PT_SETFPREGS) || defined(PT_GETFPREGS) */
508
509#ifdef PT_SETDBREGS
510 case PT_SETDBREGS:
534
535#ifdef PT_SETDBREGS
536 case PT_SETDBREGS:
511 write = 1;
512 /* fallthrough */
537 error = copyin(uap->addr, &r.dbreg, sizeof r.dbreg);
538 if (error == 0) {
539 PHOLD(p);
540 error = procfs_write_dbregs(&p->p_thread, &r.dbreg);
541 PRELE(p);
542 }
543 return (error);
513#endif /* PT_SETDBREGS */
544#endif /* PT_SETDBREGS */
545
514#ifdef PT_GETDBREGS
515 case PT_GETDBREGS:
546#ifdef PT_GETDBREGS
547 case PT_GETDBREGS:
516 /* write = 0 above */
548 PHOLD(p);
549 error = procfs_read_dbregs(&p->p_thread, &r.dbreg);
550 PRELE(p);
551 if (error == 0)
552 error = copyout(&r.dbreg, uap->addr, sizeof r.dbreg);
553 return (error);
517#endif /* PT_SETDBREGS */
554#endif /* PT_SETDBREGS */
518#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS)
519 if (!procfs_validdbregs(td)) /* no P_SYSTEM procs please */
520 return (EINVAL);
521 else {
522 iov.iov_base = uap->addr;
523 iov.iov_len = sizeof(struct dbreg);
524 uio.uio_iov = &iov;
525 uio.uio_iovcnt = 1;
526 uio.uio_offset = 0;
527 uio.uio_resid = sizeof(struct dbreg);
528 uio.uio_segflg = UIO_USERSPACE;
529 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
530 uio.uio_td = td;
531 return (procfs_dodbregs(curp, p, NULL, &uio));
532 }
533#endif /* defined(PT_SETDBREGS) || defined(PT_GETDBREGS) */
534
535 default:
555
556 default:
557 KASSERT(0, ("unreachable code\n"));
536 break;
537 }
538
558 break;
559 }
560
561 KASSERT(0, ("unreachable code\n"));
539 return (0);
540}
541
542int
562 return (0);
563}
564
565int
543trace_req(p)
544 struct proc *p;
566trace_req(struct proc *p)
545{
546 return (1);
547}
548
549/*
550 * stopevent()
567{
568 return (1);
569}
570
571/*
572 * stopevent()
551 * Stop a process because of a procfs event;
573 * Stop a process because of a debugging event;
552 * stay stopped until p->p_step is cleared
553 * (cleared by PIOCCONT in procfs).
554 *
555 * Must be called with the proc struct mutex held.
556 */
557
558void
574 * stay stopped until p->p_step is cleared
575 * (cleared by PIOCCONT in procfs).
576 *
577 * Must be called with the proc struct mutex held.
578 */
579
580void
559stopevent(p, event, val)
560 struct proc *p;
561 unsigned int event;
562 unsigned int val;
581stopevent(struct proc *p, unsigned int event, unsigned int val)
563{
564
565 PROC_LOCK_ASSERT(p, MA_OWNED | MA_NOTRECURSED);
566 p->p_step = 1;
567
568 do {
569 p->p_xstat = val;
570 p->p_stype = event; /* Which event caused the stop? */
571 wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */
572 msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0);
573 } while (p->p_step);
574}
582{
583
584 PROC_LOCK_ASSERT(p, MA_OWNED | MA_NOTRECURSED);
585 p->p_step = 1;
586
587 do {
588 p->p_xstat = val;
589 p->p_stype = event; /* Which event caused the stop? */
590 wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */
591 msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0);
592 } while (p->p_step);
593}