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 * Copyright 2016 Joyent, Inc.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
34 #include <sys/systm.h>
35 #include <sys/tuneable.h>
36 #include <sys/errno.h>
37 #include <sys/var.h>
38 #include <sys/signal.h>
39 #include <sys/time.h>
40 #include <sys/sysconfig.h>
41 #include <sys/resource.h>
42 #include <sys/ulimit.h>
43 #include <sys/unistd.h>
44 #include <sys/debug.h>
45 #include <sys/cpuvar.h>
46 #include <sys/mman.h>
47 #include <sys/timer.h>
48 #include <sys/zone.h>
49 #include <sys/vm_usage.h>
50 #include <vm/as.h>
51
52 extern rctl_hndl_t rc_process_sigqueue;
53
54 long
sysconfig(int which)55 sysconfig(int which)
56 {
57 switch (which) {
58
59 /*
60 * if it is not handled in mach_sysconfig either
61 * it must be EINVAL.
62 */
63 default:
64 return (mach_sysconfig(which)); /* `uname -i`/os */
65
66 case _CONFIG_CLK_TCK:
67 return ((long)hz); /* clock frequency per second */
68
69 case _CONFIG_PROF_TCK:
70 return ((long)hz); /* profiling clock freq per sec */
71
72 case _CONFIG_NGROUPS:
73 /*
74 * Maximum number of supplementary groups.
75 */
76 return (ngroups_max);
77
78 case _CONFIG_OPEN_FILES:
79 /*
80 * Maximum number of open files (soft limit).
81 */
82 {
83 rlim64_t fd_ctl;
84 mutex_enter(&curproc->p_lock);
85 fd_ctl = rctl_enforced_value(
86 rctlproc_legacy[RLIMIT_NOFILE], curproc->p_rctls,
87 curproc);
88 mutex_exit(&curproc->p_lock);
89 return ((ulong_t)fd_ctl);
90 }
91
92 case _CONFIG_CHILD_MAX:
93 /*
94 * Maximum number of processes.
95 */
96 return (v.v_maxup);
97
98 case _CONFIG_POSIX_VER:
99 return (_POSIX_VERSION); /* current POSIX version */
100
101 case _CONFIG_PAGESIZE:
102 return (PAGESIZE);
103
104 case _CONFIG_XOPEN_VER:
105 return (_XOPEN_VERSION); /* current XOPEN version */
106
107 case _CONFIG_NPROC_CONF:
108 return (zone_ncpus_get(curproc->p_zone));
109
110 case _CONFIG_NPROC_ONLN:
111 return (zone_ncpus_online_get(curproc->p_zone));
112
113 case _CONFIG_NPROC_MAX:
114 return (max_ncpus);
115
116 case _CONFIG_NPROC_NCPU:
117 return (NCPU); /* Private sysconfig for direct NCPU access */
118
119 case _CONFIG_STACK_PROT:
120 return (curproc->p_stkprot & ~PROT_USER);
121
122 case _CONFIG_AIO_LISTIO_MAX:
123 return (_AIO_LISTIO_MAX);
124
125 case _CONFIG_AIO_MAX:
126 return (_AIO_MAX);
127
128 case _CONFIG_AIO_PRIO_DELTA_MAX:
129 return (0);
130
131 case _CONFIG_DELAYTIMER_MAX:
132 return (INT_MAX);
133
134 case _CONFIG_MQ_OPEN_MAX:
135 return (_MQ_OPEN_MAX);
136
137 case _CONFIG_MQ_PRIO_MAX:
138 return (_MQ_PRIO_MAX);
139
140 case _CONFIG_RTSIG_MAX:
141 return (_SIGRTMAX - _SIGRTMIN + 1);
142
143 case _CONFIG_SEM_NSEMS_MAX:
144 return (_SEM_NSEMS_MAX);
145
146 case _CONFIG_SEM_VALUE_MAX:
147 return (_SEM_VALUE_MAX);
148
149 case _CONFIG_SIGQUEUE_MAX:
150 /*
151 * Maximum number of outstanding queued signals.
152 */
153 {
154 rlim64_t sigqsz_max;
155 mutex_enter(&curproc->p_lock);
156 sigqsz_max = rctl_enforced_value(rc_process_sigqueue,
157 curproc->p_rctls, curproc);
158 mutex_exit(&curproc->p_lock);
159 return ((uint_t)sigqsz_max);
160 }
161
162 case _CONFIG_SIGRT_MIN:
163 return (_SIGRTMIN);
164
165 case _CONFIG_SIGRT_MAX:
166 return (_SIGRTMAX);
167
168 case _CONFIG_TIMER_MAX:
169 return (timer_max);
170
171 case _CONFIG_PHYS_PAGES:
172 /*
173 * If the non-global zone has a phys. memory cap, use that.
174 * We always report the system-wide value for the global zone,
175 * even though rcapd can be used on the global zone too.
176 */
177 if (!INGLOBALZONE(curproc) &&
178 curproc->p_zone->zone_phys_mcap != 0)
179 return (MIN(btop(curproc->p_zone->zone_phys_mcap),
180 physinstalled));
181
182 return (physinstalled);
183
184 case _CONFIG_AVPHYS_PAGES:
185 /*
186 * If the non-global zone has a phys. memory cap, use
187 * the phys. memory cap - zone's current rss. We always
188 * report the system-wide value for the global zone, even
189 * though rcapd can be used on the global zone too.
190 */
191 if (!INGLOBALZONE(curproc) &&
192 curproc->p_zone->zone_phys_mcap != 0) {
193 pgcnt_t cap, rss, free;
194 vmusage_t in_use;
195 size_t cnt = 1;
196
197 cap = btop(curproc->p_zone->zone_phys_mcap);
198 if (cap > physinstalled)
199 return (freemem);
200
201 if (vm_getusage(VMUSAGE_ZONE, 1, &in_use, &cnt,
202 FKIOCTL) != 0)
203 in_use.vmu_rss_all = 0;
204 rss = btop(in_use.vmu_rss_all);
205 /*
206 * Because rcapd implements a soft cap, it is possible
207 * for rss to be temporarily over the cap.
208 */
209 if (cap > rss)
210 free = cap - rss;
211 else
212 free = 0;
213 return (MIN(free, freemem));
214 }
215
216 return (freemem);
217
218 case _CONFIG_MAXPID:
219 return (maxpid);
220
221 case _CONFIG_CPUID_MAX:
222 return (max_cpuid);
223
224 case _CONFIG_EPHID_MAX:
225 return (MAXEPHUID);
226
227 case _CONFIG_UADDR_MAX:
228 return ((long)(uintptr_t)curproc->p_as->a_userlimit);
229
230 case _CONFIG_SYMLOOP_MAX:
231 return (MAXSYMLINKS);
232 }
233 }
234