aboutsummaryrefslogtreecommitdiff
path: root/sys/sys/proc.h
blob: 357c0c0d52c91f01faf14091ba2c464358000952 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
/*	$OpenBSD: proc.h,v 1.295 2020/04/28 08:29:40 mpi Exp $	*/
/*	$NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $	*/

/*-
 * Copyright (c) 1986, 1989, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)proc.h	8.8 (Berkeley) 1/21/94
 */

#ifndef _SYS_PROC_H_
#define	_SYS_PROC_H_

#include <machine/proc.h>		/* Machine-dependent proc substruct. */
#include <sys/selinfo.h>		/* For struct selinfo */
#include <sys/syslimits.h>		/* For LOGIN_NAME_MAX */
#include <sys/queue.h>
#include <sys/timeout.h>		/* For struct timeout */
#include <sys/event.h>			/* For struct klist */
#include <sys/mutex.h>			/* For struct mutex */
#include <sys/resource.h>		/* For struct rusage */
#include <sys/rwlock.h>			/* For struct rwlock */
#include <sys/sigio.h>			/* For struct sigio */

#ifdef _KERNEL
#include <sys/atomic.h>
#define __need_process
#endif

/*
 * One structure allocated per session.
 */
struct process;
struct	session {
	int	s_count;		/* Ref cnt; pgrps in session. */
	struct	process *s_leader;	/* Session leader. */
	struct	vnode *s_ttyvp;		/* Vnode of controlling terminal. */
	struct	tty *s_ttyp;		/* Controlling terminal. */
	char	s_login[LOGIN_NAME_MAX];	/* Setlogin() name. */
	pid_t	s_verauthppid;
	uid_t	s_verauthuid;
	struct timeout s_verauthto;
};

void zapverauth(/* struct session */ void *);

/*
 * One structure allocated per process group.
 */
struct	pgrp {
	LIST_ENTRY(pgrp) pg_hash;	/* Hash chain. */
	LIST_HEAD(, process) pg_members;/* Pointer to pgrp members. */
	struct	session *pg_session;	/* Pointer to session. */
	struct	sigiolst pg_sigiolst;	/* List of sigio structures. */
	pid_t	pg_id;			/* Pgrp id. */
	int	pg_jobc;	/* # procs qualifying pgrp for job control */
};

/*
 * One structure allocated per emulation.
 */
struct exec_package;
struct proc;
struct ps_strings;
struct uvm_object;
union sigval;

struct	emul {
	char	e_name[8];		/* Symbolic name */
	int	*e_errno;		/* Errno array */
	int	e_nosys;		/* Offset of the nosys() syscall */
	int	e_nsysent;		/* Number of system call entries */
	struct sysent *e_sysent;	/* System call array */
	char	**e_syscallnames;	/* System call name array */
	int	e_arglen;		/* Extra argument size in words */
					/* Copy arguments on the stack */
	void	*(*e_copyargs)(struct exec_package *, struct ps_strings *,
				    void *, void *);
					/* Set registers before execution */
	void	(*e_setregs)(struct proc *, struct exec_package *,
				  u_long, register_t *);
	int	(*e_fixup)(struct proc *, struct exec_package *);
	int	(*e_coredump)(struct proc *, void *cookie);
	char	*e_sigcode;		/* Start of sigcode */
	char	*e_esigcode;		/* End of sigcode */
	char	*e_esigret;		/* sigaction RET position */
	struct uvm_object *e_sigobject;	/* shared sigcode object */
};

/*
 * time usage: accumulated times in ticks
 * Once a second, each thread's immediate counts (p_[usi]ticks) are
 * accumulated into these.
 */
struct tusage {
	struct	timespec tu_runtime;	/* Realtime. */
	uint64_t	tu_uticks;	/* Statclock hits in user mode. */
	uint64_t	tu_sticks;	/* Statclock hits in system mode. */
	uint64_t	tu_iticks;	/* Statclock hits processing intr. */
};

/*
 * Description of a process.
 *
 * These structures contain the information needed to manage a thread of
 * control, known in UN*X as a process; it has references to substructures
 * containing descriptions of things that the process uses, but may share
 * with related processes.
 *
 * struct process is the higher level process containing information
 * shared by all threads in a process, while struct proc contains the
 * run-time information needed by threads.
 */
#ifdef __need_process
struct futex;
LIST_HEAD(futex_list, futex);
struct tslpentry;
TAILQ_HEAD(tslpqueue, tslpentry);
struct unveil;

/*
 * Locks used to protect struct members in this file:
 *	a	atomic operations
 *	m	this process' `ps_mtx'
 *	p	this process' `ps_lock'
 *	r	rlimit_lock
 */
struct process {
	/*
	 * ps_mainproc is the original thread in the process.
	 * It's only still special for the handling of
	 * some signal and ptrace behaviors that need to be fixed.
	 */
	struct	proc *ps_mainproc;
	struct	ucred *ps_ucred;	/* Process owner's identity. */

	LIST_ENTRY(process) ps_list;	/* List of all processes. */
	TAILQ_HEAD(,proc) ps_threads;	/* Threads in this process. */

	LIST_ENTRY(process) ps_pglist;	/* List of processes in pgrp. */
	struct	process *ps_pptr; 	/* Pointer to parent process. */
	LIST_ENTRY(process) ps_sibling;	/* List of sibling processes. */
	LIST_HEAD(, process) ps_children;/* Pointer to list of children. */
	LIST_ENTRY(process) ps_hash;    /* Hash chain. */

	/*
	 * An orphan is the child that has been re-parented to the
	 * debugger as a result of attaching to it.  Need to keep
	 * track of them for parent to be able to collect the exit
	 * status of what used to be children.
	 */
	LIST_ENTRY(process) ps_orphan;	/* List of orphan processes. */
	LIST_HEAD(, process) ps_orphans;/* Pointer to list of orphans. */

	struct	sigiolst ps_sigiolst;	/* List of sigio structures. */
	struct	sigacts *ps_sigacts;	/* Signal actions, state */
	struct	vnode *ps_textvp;	/* Vnode of executable. */
	struct	filedesc *ps_fd;	/* Ptr to open files structure */
	struct	vmspace *ps_vmspace;	/* Address space */
	pid_t	ps_pid;			/* Process identifier. */

	struct	futex_list ps_ftlist;	/* futexes attached to this process */
	struct	tslpqueue ps_tslpqueue;	/* [p] queue of threads in thrsleep */
	struct	rwlock	ps_lock;	/* per-process rwlock */
	struct  mutex	ps_mtx;		/* per-process mutex */

/* The following fields are all zeroed upon creation in process_new. */
#define	ps_startzero	ps_klist
	struct	klist ps_klist;		/* knotes attached to this process */
	u_int	ps_flags;		/* [a] PS_* flags. */
	int	ps_siglist;		/* Signals pending for the process. */

	struct	proc *ps_single;	/* Single threading to this thread. */
	u_int	ps_singlecount;		/* [a] Not yet suspended threads. */

	int	ps_traceflag;		/* Kernel trace points. */
	struct	vnode *ps_tracevp;	/* Trace to vnode. */
	struct	ucred *ps_tracecred;	/* Creds for writing trace */

	u_int	ps_xexit;		/* Exit status for wait */
	int	ps_xsig;		/* Stopping or killing signal */

	pid_t	ps_oppid;	 	/* Save parent pid during ptrace. */
	int	ps_ptmask;		/* Ptrace event mask */
	struct	ptrace_state *ps_ptstat;/* Ptrace state */

	struct	rusage *ps_ru;		/* sum of stats for dead threads. */
	struct	tusage ps_tu;		/* accumulated times. */
	struct	rusage ps_cru;		/* sum of stats for reaped children */
	struct	itimerspec ps_timer[3];	/* timers, indexed by ITIMER_* */
	struct	timeout ps_rucheck_to;	/* [] resource limit check timer */
	time_t	ps_nextxcpu;		/* when to send next SIGXCPU, */
					/* in seconds of process runtime */

	u_int64_t ps_wxcounter;

	struct unveil *ps_uvpaths;	/* unveil vnodes and names */
	struct unveil *ps_uvpcwd;	/* pointer to unveil of cwd, NULL if none */
	ssize_t ps_uvvcount;		/* count of unveil vnodes held */
	size_t ps_uvncount;		/* count of unveil names allocated */
	int ps_uvshrink;		/* do we need to shrink vnode list */
	int ps_uvdone;			/* no more unveil is permitted */

/* End area that is zeroed on creation. */
#define	ps_endzero	ps_startcopy

/* The following fields are all copied upon creation in process_new. */
#define	ps_startcopy	ps_limit
	struct	plimit *ps_limit;	/* [m,r] Process limits. */
	struct	pgrp *ps_pgrp;		/* Pointer to process group. */
	struct	emul *ps_emul;		/* Emulation information */

	char	ps_comm[MAXCOMLEN+1];

	vaddr_t	ps_strings;		/* User pointers to argv/env */
	vaddr_t	ps_sigcode;		/* User pointer to the signal code */
	vaddr_t ps_sigcoderet;		/* User pointer to sigreturn retPC */
	u_long	ps_sigcookie;
	u_int	ps_rtableid;		/* Process routing table/domain. */
	char	ps_nice;		/* Process "nice" value. */

	struct uprof {			/* profile arguments */
		caddr_t	pr_base;	/* buffer base */
		size_t  pr_size;	/* buffer size */
		u_long	pr_off;		/* pc offset */
		u_int   pr_scale;	/* pc scaling */
	} ps_prof;

	u_short	ps_acflag;		/* Accounting flags. */

	uint64_t ps_pledge;
	uint64_t ps_execpledge;

	int64_t ps_kbind_cookie;
	u_long  ps_kbind_addr;

/* End area that is copied on creation. */
#define ps_endcopy	ps_refcnt
	int	ps_refcnt;		/* Number of references. */

	struct	timespec ps_start;	/* starting uptime. */
	struct	timeout ps_realit_to;	/* real-time itimer trampoline. */
};

#define	ps_session	ps_pgrp->pg_session
#define	ps_pgid		ps_pgrp->pg_id

#endif /* __need_process */

/*
 * These flags are kept in ps_flags.
 */
#define	PS_CONTROLT	0x00000001	/* Has a controlling terminal. */
#define	PS_EXEC		0x00000002	/* Process called exec. */
#define	PS_INEXEC	0x00000004	/* Process is doing an exec right now */
#define	PS_EXITING	0x00000008	/* Process is exiting. */
#define	PS_SUGID	0x00000010	/* Had set id privs since last exec. */
#define	PS_SUGIDEXEC	0x00000020	/* last execve() was set[ug]id */
#define	PS_PPWAIT	0x00000040	/* Parent waits for exec/exit. */
#define	PS_ISPWAIT	0x00000080	/* Is parent of PPWAIT child. */
#define	PS_PROFIL	0x00000100	/* Has started profiling. */
#define	PS_TRACED	0x00000200	/* Being ptraced. */
#define	PS_WAITED	0x00000400	/* Stopped proc was waited for. */
#define	PS_COREDUMP	0x00000800	/* Busy coredumping */
#define	PS_SINGLEEXIT	0x00001000	/* Other threads must die. */
#define	PS_SINGLEUNWIND	0x00002000	/* Other threads must unwind. */
#define	PS_NOZOMBIE	0x00004000	/* No signal or zombie at exit. */
#define	PS_STOPPED	0x00008000	/* Just stopped, need sig to parent. */
#define	PS_SYSTEM	0x00010000	/* No sigs, stats or swapping. */
#define	PS_EMBRYO	0x00020000	/* New process, not yet fledged */
#define	PS_ZOMBIE	0x00040000	/* Dead and ready to be waited for */
#define	PS_NOBROADCASTKILL 0x00080000	/* Process excluded from kill -1. */
#define	PS_PLEDGE	0x00100000	/* Has called pledge(2) */
#define	PS_WXNEEDED	0x00200000	/* Process may violate W^X */
#define	PS_EXECPLEDGE	0x00400000	/* Has exec pledges */
#define	PS_ORPHAN	0x00800000	/* Process is on an orphan list */

#define	PS_BITS \
    ("\20" "\01CONTROLT" "\02EXEC" "\03INEXEC" "\04EXITING" "\05SUGID" \
     "\06SUGIDEXEC" "\07PPWAIT" "\010ISPWAIT" "\011PROFIL" "\012TRACED" \
     "\013WAITED" "\014COREDUMP" "\015SINGLEEXIT" "\016SINGLEUNWIND" \
     "\017NOZOMBIE" "\020STOPPED" "\021SYSTEM" "\022EMBRYO" "\023ZOMBIE" \
     "\024NOBROADCASTKILL" "\025PLEDGE" "\026WXNEEDED" "\027EXECPLEDGE" \
     "\028ORPHAN")


struct kcov_dev;
struct lock_list_entry;

struct p_inentry {
	u_long	 ie_serial;
	vaddr_t	 ie_start;
	vaddr_t	 ie_end;
};

/*
 *  Locks used to protect struct members in this file:
 *	I	immutable after creation
 *	s	scheduler lock
 *	l	read only reference, see lim_read_enter()
 *	o	owned (read/modified only) by this thread
 */
struct proc {
	TAILQ_ENTRY(proc) p_runq;	/* [s] current run/sleep queue */
	LIST_ENTRY(proc) p_list;	/* List of all threads. */

	struct	process *p_p;		/* [I] The process of this thread. */
	TAILQ_ENTRY(proc) p_thr_link;	/* Threads in a process linkage. */

	TAILQ_ENTRY(proc) p_fut_link;	/* Threads in a futex linkage. */
	struct	futex	*p_futex;	/* Current sleeping futex. */

	/* substructures: */
	struct	filedesc *p_fd;		/* copy of p_p->ps_fd */
	struct	vmspace *p_vmspace;	/* [I] copy of p_p->ps_vmspace */
	struct	p_inentry p_spinentry;	/* [o] cache for SP check */
	struct	p_inentry p_pcinentry;	/* [o] cache for PC check */

	int	p_flag;			/* P_* flags. */
	u_char	p_spare;		/* unused */
	char	p_stat;			/* [s] S* process status. */
	u_char	p_runpri;		/* [s] Runqueue priority */
	u_char	p_descfd;		/* if not 255, fdesc permits this fd */

	pid_t	p_tid;			/* Thread identifier. */
	LIST_ENTRY(proc) p_hash;	/* Hash chain. */

/* The following fields are all zeroed upon creation in fork. */
#define	p_startzero	p_dupfd
	int	p_dupfd;	 /* Sideways return value from filedescopen. XXX */

	/* scheduling */
	int	p_cpticks;	 /* Ticks of cpu time. */
	const volatile void *p_wchan;	/* [s] Sleep address. */
	struct	timeout p_sleep_to;/* timeout for tsleep() */
	const char *p_wmesg;		/* [s] Reason for sleep. */
	fixpt_t	p_pctcpu;		/* [s] %cpu for this thread */
	u_int	p_slptime;		/* [s] Time since last blocked. */
	u_int	p_uticks;		/* Statclock hits in user mode. */
	u_int	p_sticks;		/* Statclock hits in system mode. */
	u_int	p_iticks;		/* Statclock hits processing intr. */
	struct	cpu_info * volatile p_cpu; /* [s] CPU we're running on. */

	struct	rusage p_ru;		/* Statistics */
	struct	tusage p_tu;		/* accumulated times. */
	struct	timespec p_rtime;	/* Real time. */

	struct	plimit	*p_limit;	/* [l] read ref. of p_p->ps_limit */
	struct	kcov_dev *p_kd;		/* kcov device handle */
	struct	lock_list_entry *p_sleeplocks;	/* WITNESS lock tracking */ 

	int	 p_siglist;		/* Signals arrived but not delivered. */

/* End area that is zeroed on creation. */
#define	p_endzero	p_startcopy

/* The following fields are all copied upon creation in fork. */
#define	p_startcopy	p_sigmask
	sigset_t p_sigmask;	/* Current signal mask. */

	u_char	p_slppri;		/* [s] Sleeping priority */
	u_char	p_usrpri;	/* [s] Priority based on p_estcpu & ps_nice */
	u_int	p_estcpu;		/* [s] Time averaged val of p_cpticks */
	int	p_pledge_syscall;	/* Cache of current syscall */

	struct	ucred *p_ucred;		/* [o] cached credentials */
	struct	sigaltstack p_sigstk;	/* sp & on stack state variable */

	u_long	p_prof_addr;	/* tmp storage for profiling addr until AST */
	u_long	p_prof_ticks;	/* tmp storage for profiling ticks until AST */

/* End area that is copied on creation. */
#define	p_endcopy	p_addr
	struct	user *p_addr;	/* Kernel virtual addr of u-area */
	struct	mdproc p_md;	/* Any machine-dependent fields. */

	sigset_t p_oldmask;	/* Saved mask from before sigpause */
	int	p_sisig;	/* For core dump/debugger XXX */
	union sigval p_sigval;	/* For core dump/debugger XXX */
	long	p_sitrapno;	/* For core dump/debugger XXX */
	int	p_sicode;	/* For core dump/debugger XXX */
};

/* Status values. */
#define	SIDL	1		/* Thread being created by fork. */
#define	SRUN	2		/* Currently runnable. */
#define	SSLEEP	3		/* Sleeping on an address. */
#define	SSTOP	4		/* Debugging or suspension. */
#define	SZOMB	5		/* unused */
#define	SDEAD	6		/* Thread is almost gone */
#define	SONPROC	7		/* Thread is currently on a CPU. */

#define	P_ZOMBIE(p)	((p)->p_stat == SDEAD)
#define	P_HASSIBLING(p)	(TAILQ_FIRST(&(p)->p_p->ps_threads) != (p) || \
			 TAILQ_NEXT((p), p_thr_link) != NULL)

/*
 * These flags are per-thread and kept in p_flag
 */
#define	P_INKTR		0x00000001	/* In a ktrace op, don't recurse */
#define	P_PROFPEND	0x00000002	/* SIGPROF needs to be posted */
#define	P_ALRMPEND	0x00000004	/* SIGVTALRM needs to be posted */
#define	P_SIGSUSPEND	0x00000008	/* Need to restore before-suspend mask*/
#define	P_CANTSLEEP	0x00000010	/* insomniac thread */
#define	P_SELECT	0x00000040	/* Selecting; wakeup/waiting danger. */
#define	P_SINTR		0x00000080	/* Sleep is interruptible. */
#define	P_SYSTEM	0x00000200	/* No sigs, stats or swapping. */
#define	P_TIMEOUT	0x00000400	/* Timing out during sleep. */
#define	P_WEXIT		0x00002000	/* Working on exiting. */
#define	P_OWEUPC	0x00008000	/* Owe proc an addupc() at next ast. */
#define	P_SUSPSINGLE	0x00080000	/* Need to stop for single threading. */
#define P_CONTINUED	0x00800000	/* Proc has continued from a stopped state. */
#define	P_THREAD	0x04000000	/* Only a thread, not a real process */
#define	P_SUSPSIG	0x08000000	/* Stopped from signal. */
#define	P_SOFTDEP	0x10000000	/* Stuck processing softdep worklist */
#define P_CPUPEG	0x40000000	/* Do not move to another cpu. */

#define	P_BITS \
    ("\20" "\01INKTR" "\02PROFPEND" "\03ALRMPEND" "\04SIGSUSPEND" \
     "\05CANTSLEEP" "\07SELECT" "\010SINTR" "\012SYSTEM" "\013TIMEOUT" \
     "\016WEXIT" "\020OWEUPC" "\024SUSPSINGLE" "\027XX" \
     "\030CONTINUED" "\033THREAD" "\034SUSPSIG" "\035SOFTDEP" "\037CPUPEG")

#define	THREAD_PID_OFFSET	100000

#ifdef _KERNEL

struct uidinfo {
	LIST_ENTRY(uidinfo) ui_hash;
	uid_t   ui_uid;
	long    ui_proccnt;	/* proc structs */
	long	ui_lockcnt;	/* lockf structs */
};

struct uidinfo *uid_find(uid_t);
void uid_release(struct uidinfo *);

/*
 * We use process IDs <= PID_MAX; PID_MAX + 1 must also fit in a pid_t,
 * as it is used to represent "no process group".
 * We set PID_MAX to 99999 to keep it in 5 columns in ps
 * When exposed to userspace, thread IDs have THREAD_PID_OFFSET
 * added to keep them from overlapping the PID range.  For them,
 * we use a * a (0 .. 2^n] range for cheapness, picking 'n' such
 * that 2^n + THREAD_PID_OFFSET and THREAD_PID_OFFSET have
 * the same number of columns when printed.
 */
#define	PID_MAX			99999
#define	TID_MASK		0x7ffff

#define	NO_PID		(PID_MAX+1)

#define SESS_LEADER(pr)	((pr)->ps_session->s_leader == (pr))
#define	SESSHOLD(s)	((s)->s_count++)
#define	SESSRELE(s) do {						\
	if (--(s)->s_count == 0) {					\
		timeout_del(&(s)->s_verauthto);			\
		pool_put(&session_pool, (s));				\
	}								\
} while (/* CONSTCOND */ 0)

/*
 * Flags to fork1().
 */
#define FORK_FORK	0x00000001
#define FORK_VFORK	0x00000002
#define FORK_IDLE	0x00000004
#define FORK_PPWAIT	0x00000008
#define FORK_SHAREFILES	0x00000010
#define FORK_SYSTEM	0x00000020
#define FORK_NOZOMBIE	0x00000040
#define FORK_SHAREVM	0x00000080
#define FORK_PTRACE	0x00000400

#define EXIT_NORMAL		0x00000001
#define EXIT_THREAD		0x00000002
#define EXIT_THREAD_NOCHECK	0x00000003

#define	TIDHASH(tid)	(&tidhashtbl[(tid) & tidhash])
extern LIST_HEAD(tidhashhead, proc) *tidhashtbl;
extern u_long tidhash;

#define	PIDHASH(pid)	(&pidhashtbl[(pid) & pidhash])
extern LIST_HEAD(pidhashhead, process) *pidhashtbl;
extern u_long pidhash;

#define	PGRPHASH(pgid)	(&pgrphashtbl[(pgid) & pgrphash])
extern LIST_HEAD(pgrphashhead, pgrp) *pgrphashtbl;
extern u_long pgrphash;

extern struct proc proc0;		/* Process slot for swapper. */
extern struct process process0;		/* Process slot for kernel threads. */
extern int nprocesses, maxprocess;	/* Cur and max number of processes. */
extern int nthreads, maxthread;		/* Cur and max number of threads. */
extern int randompid;			/* fork() should create random pid's */

LIST_HEAD(proclist, proc);
LIST_HEAD(processlist, process);
extern struct processlist allprocess;	/* List of all processes. */
extern struct processlist zombprocess;	/* List of zombie processes. */
extern struct proclist allproc;		/* List of all threads. */

extern struct process *initprocess;	/* Process slot for init. */
extern struct proc *reaperproc;		/* Thread slot for reaper. */
extern struct proc *syncerproc;		/* filesystem syncer daemon */

extern struct pool process_pool;	/* memory pool for processes */
extern struct pool proc_pool;		/* memory pool for procs */
extern struct pool rusage_pool;		/* memory pool for zombies */
extern struct pool ucred_pool;		/* memory pool for ucreds */
extern struct pool session_pool;	/* memory pool for sessions */
extern struct pool pgrp_pool;		/* memory pool for pgrps */

void	freepid(pid_t);

struct process *prfind(pid_t);	/* Find process by id. */
struct process *zombiefind(pid_t); /* Find zombie process by id. */
struct proc *tfind(pid_t);	/* Find thread by id. */
struct pgrp *pgfind(pid_t);	/* Find process group by id. */
void	proc_printit(struct proc *p, const char *modif,
    int (*pr)(const char *, ...));

int	chgproccnt(uid_t uid, int diff);
void	enternewpgrp(struct process *, struct pgrp *, struct session *);
void	enterthispgrp(struct process *, struct pgrp *);
int	inferior(struct process *, struct process *);
void	leavepgrp(struct process *);
void	killjobc(struct process *);
void	preempt(void);
void	procinit(void);
void	setpriority(struct proc *, uint32_t, uint8_t);
void	setrunnable(struct proc *);
void	endtsleep(void *);
int	wakeup_proc(struct proc *, const volatile void *);
void	unsleep(struct proc *);
void	reaper(void *);
void	exit1(struct proc *, int, int, int);
void	exit2(struct proc *);
int	dowait4(struct proc *, pid_t, int *, int, struct rusage *,
	    register_t *);
void	cpu_fork(struct proc *_curp, struct proc *_child, void *_stack,
	    void *_tcb, void (*_func)(void *), void *_arg);
void	cpu_exit(struct proc *);
void	process_initialize(struct process *, struct proc *);
int	fork1(struct proc *_curp, int _flags, void (*_func)(void *),
	    void *_arg, register_t *_retval, struct proc **_newprocp);
int	thread_fork(struct proc *_curp, void *_stack, void *_tcb,
	    pid_t *_tidptr, register_t *_retval);
int	groupmember(gid_t, struct ucred *);
void	dorefreshcreds(struct process *, struct proc *);
void	dosigsuspend(struct proc *, sigset_t);

static inline void
refreshcreds(struct proc *p)
{
	struct process *pr = p->p_p;

	/* this is an unlocked access to ps_ucred, but the result is benign */
	if (pr->ps_ucred != p->p_ucred)
		dorefreshcreds(pr, p);
}

enum single_thread_mode {
	SINGLE_SUSPEND,		/* other threads to stop wherever they are */
	SINGLE_PTRACE,		/* other threads to stop but don't wait */
	SINGLE_UNWIND,		/* other threads to unwind and stop */
	SINGLE_EXIT		/* other threads to unwind and then exit */
};
int	single_thread_set(struct proc *, enum single_thread_mode, int);
int	single_thread_wait(struct process *, int);
void	single_thread_clear(struct proc *, int);
int	single_thread_check(struct proc *, int);

void	child_return(void *);

int	proc_cansugid(struct proc *);

struct sleep_state {
	int sls_s;
	int sls_catch;
	int sls_do_sleep;
	int sls_locked;
	int sls_sig;
	int sls_unwind;
	int sls_timeout;
};

struct cond {
	int	c_wait;
};

#define COND_INITIALIZER()		{ 1 }

#if defined(MULTIPROCESSOR)
void	proc_trampoline_mp(void);	/* XXX */
#endif

/*
 * functions to handle sets of cpus.
 *
 * For now we keep the cpus in ints so that we can use the generic
 * atomic ops.
 */
#define CPUSET_ASIZE(x) (((x) - 1)/32 + 1)
#define CPUSET_SSIZE CPUSET_ASIZE(MAXCPUS)
struct cpuset {
	int cs_set[CPUSET_SSIZE];
};

void cpuset_init_cpu(struct cpu_info *);

void cpuset_clear(struct cpuset *);
void cpuset_add(struct cpuset *, struct cpu_info *);
void cpuset_del(struct cpuset *, struct cpu_info *);
int cpuset_isset(struct cpuset *, struct cpu_info *);
void cpuset_add_all(struct cpuset *);
void cpuset_copy(struct cpuset *, struct cpuset *);
void cpuset_union(struct cpuset *, struct cpuset *, struct cpuset *);
void cpuset_intersection(struct cpuset *t, struct cpuset *, struct cpuset *);
void cpuset_complement(struct cpuset *, struct cpuset *, struct cpuset *);
int cpuset_cardinality(struct cpuset *);
struct cpu_info *cpuset_first(struct cpuset *);

#endif	/* _KERNEL */
#endif	/* !_SYS_PROC_H_ */