1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28/*	  All Rights Reserved	*/
29
30#include <sys/param.h>
31#include <sys/types.h>
32#include <sys/sysmacros.h>
33#include <sys/systm.h>
34#include <sys/tuneable.h>
35#include <sys/errno.h>
36#include <sys/var.h>
37#include <sys/signal.h>
38#include <sys/time.h>
39#include <sys/sysconfig.h>
40#include <sys/resource.h>
41#include <sys/ulimit.h>
42#include <sys/unistd.h>
43#include <sys/debug.h>
44#include <sys/cpuvar.h>
45#include <sys/mman.h>
46#include <sys/timer.h>
47#include <sys/zone.h>
48#include <sys/vm_usage.h>
49
50extern rctl_hndl_t rc_process_sigqueue;
51
52long
53sysconfig(int which)
54{
55	switch (which) {
56
57	/*
58	 * if it is not handled in mach_sysconfig either
59	 * it must be EINVAL.
60	 */
61	default:
62		return (mach_sysconfig(which)); /* `uname -i`/os */
63
64	case _CONFIG_CLK_TCK:
65		return ((long)hz);	/* clock frequency per second */
66
67	case _CONFIG_PROF_TCK:
68		return ((long)hz);	/* profiling clock freq per sec */
69
70	case _CONFIG_NGROUPS:
71		/*
72		 * Maximum number of supplementary groups.
73		 */
74		return (ngroups_max);
75
76	case _CONFIG_OPEN_FILES:
77		/*
78		 * Maximum number of open files (soft limit).
79		 */
80		{
81			rlim64_t fd_ctl;
82			mutex_enter(&curproc->p_lock);
83			fd_ctl = rctl_enforced_value(
84			    rctlproc_legacy[RLIMIT_NOFILE], curproc->p_rctls,
85			    curproc);
86			mutex_exit(&curproc->p_lock);
87			return ((ulong_t)fd_ctl);
88		}
89
90	case _CONFIG_CHILD_MAX:
91		/*
92		 * Maximum number of processes.
93		 */
94		return (v.v_maxup);
95
96	case _CONFIG_POSIX_VER:
97		return (_POSIX_VERSION); /* current POSIX version */
98
99	case _CONFIG_PAGESIZE:
100		return (PAGESIZE);
101
102	case _CONFIG_XOPEN_VER:
103		return (_XOPEN_VERSION); /* current XOPEN version */
104
105	case _CONFIG_NPROC_CONF:
106		return (zone_ncpus_get(curproc->p_zone));
107
108	case _CONFIG_NPROC_ONLN:
109		return (zone_ncpus_online_get(curproc->p_zone));
110
111	case _CONFIG_NPROC_MAX:
112		return (max_ncpus);
113
114	case _CONFIG_STACK_PROT:
115		return (curproc->p_stkprot & ~PROT_USER);
116
117	case _CONFIG_AIO_LISTIO_MAX:
118		return (_AIO_LISTIO_MAX);
119
120	case _CONFIG_AIO_MAX:
121		return (_AIO_MAX);
122
123	case _CONFIG_AIO_PRIO_DELTA_MAX:
124		return (0);
125
126	case _CONFIG_DELAYTIMER_MAX:
127		return (INT_MAX);
128
129	case _CONFIG_MQ_OPEN_MAX:
130		return (_MQ_OPEN_MAX);
131
132	case _CONFIG_MQ_PRIO_MAX:
133		return (_MQ_PRIO_MAX);
134
135	case _CONFIG_RTSIG_MAX:
136		return (_SIGRTMAX - _SIGRTMIN + 1);
137
138	case _CONFIG_SEM_NSEMS_MAX:
139		return (_SEM_NSEMS_MAX);
140
141	case _CONFIG_SEM_VALUE_MAX:
142		return (_SEM_VALUE_MAX);
143
144	case _CONFIG_SIGQUEUE_MAX:
145		/*
146		 * Maximum number of outstanding queued signals.
147		 */
148		{
149			rlim64_t sigqsz_max;
150			mutex_enter(&curproc->p_lock);
151			sigqsz_max = rctl_enforced_value(rc_process_sigqueue,
152			    curproc->p_rctls, curproc);
153			mutex_exit(&curproc->p_lock);
154			return ((uint_t)sigqsz_max);
155		}
156
157	case _CONFIG_SIGRT_MIN:
158		return (_SIGRTMIN);
159
160	case _CONFIG_SIGRT_MAX:
161		return (_SIGRTMAX);
162
163	case _CONFIG_TIMER_MAX:
164		return (timer_max);
165
166	case _CONFIG_PHYS_PAGES:
167		/*
168		 * If the non-global zone has a phys. memory cap, use that.
169		 * We always report the system-wide value for the global zone,
170		 * even though rcapd can be used on the global zone too.
171		 */
172		if (!INGLOBALZONE(curproc) &&
173		    curproc->p_zone->zone_phys_mcap != 0)
174			return (MIN(btop(curproc->p_zone->zone_phys_mcap),
175			    physinstalled));
176
177		return (physinstalled);
178
179	case _CONFIG_AVPHYS_PAGES:
180		/*
181		 * If the non-global zone has a phys. memory cap, use
182		 * the phys. memory cap - zone's current rss.  We always
183		 * report the system-wide value for the global zone, even
184		 * though rcapd can be used on the global zone too.
185		 */
186		if (!INGLOBALZONE(curproc) &&
187		    curproc->p_zone->zone_phys_mcap != 0) {
188			pgcnt_t cap, rss, free;
189			vmusage_t in_use;
190			size_t cnt = 1;
191
192			cap = btop(curproc->p_zone->zone_phys_mcap);
193			if (cap > physinstalled)
194				return (freemem);
195
196			if (vm_getusage(VMUSAGE_ZONE, 1, &in_use, &cnt,
197			    FKIOCTL) != 0)
198				in_use.vmu_rss_all = 0;
199			rss = btop(in_use.vmu_rss_all);
200			/*
201			 * Because rcapd implements a soft cap, it is possible
202			 * for rss to be temporarily over the cap.
203			 */
204			if (cap > rss)
205				free = cap - rss;
206			else
207				free = 0;
208			return (MIN(free, freemem));
209		}
210
211		return (freemem);
212
213	case _CONFIG_MAXPID:
214		return (maxpid);
215
216	case _CONFIG_CPUID_MAX:
217		return (max_cpuid);
218
219	case _CONFIG_EPHID_MAX:
220		return (MAXEPHUID);
221
222	case _CONFIG_SYMLOOP_MAX:
223		return (MAXSYMLINKS);
224	}
225}
226