1
2
3
4
5 package sysconf
6
7 import (
8 "bufio"
9 "io/ioutil"
10 "os"
11 "runtime"
12 "strconv"
13 "strings"
14
15 "github.com/tklauser/numcpus"
16 "golang.org/x/sys/unix"
17 )
18
19 const (
20
21
22
23
24
25 _SYSTEM_CLK_TCK = 100
26 )
27
28 func readProcFsInt64(path string, fallback int64) int64 {
29 data, err := ioutil.ReadFile(path)
30 if err != nil {
31 return fallback
32 }
33 i, err := strconv.ParseInt(string(data[:len(data)-1]), 0, 64)
34 if err != nil {
35 return fallback
36 }
37 return i
38 }
39
40
41 func getMemPages(mem uint64, unit uint32) int64 {
42 pageSize := os.Getpagesize()
43 for unit > 1 && pageSize > 1 {
44 unit >>= 1
45 pageSize >>= 1
46 }
47 mem *= uint64(unit)
48 for pageSize > 1 {
49 pageSize >>= 1
50 mem >>= 1
51 }
52 return int64(mem)
53 }
54
55 func getPhysPages() int64 {
56 var si unix.Sysinfo_t
57 err := unix.Sysinfo(&si)
58 if err != nil {
59 return int64(0)
60 }
61 return getMemPages(uint64(si.Totalram), si.Unit)
62 }
63
64 func getAvPhysPages() int64 {
65 var si unix.Sysinfo_t
66 err := unix.Sysinfo(&si)
67 if err != nil {
68 return int64(0)
69 }
70 return getMemPages(uint64(si.Freeram), si.Unit)
71 }
72
73 func getNprocsSysfs() (int64, error) {
74 n, err := numcpus.GetOnline()
75 return int64(n), err
76 }
77
78 func getNprocsProcStat() (int64, error) {
79 f, err := os.Open("/proc/stat")
80 if err != nil {
81 return -1, err
82 }
83 defer f.Close()
84
85 count := int64(0)
86 s := bufio.NewScanner(f)
87 for s.Scan() {
88 if line := strings.TrimSpace(s.Text()); strings.HasPrefix(line, "cpu") {
89 l := strings.SplitN(line, " ", 2)
90 _, err := strconv.ParseInt(l[0][3:], 10, 64)
91 if err == nil {
92 count++
93 }
94 } else {
95
96
97
98 break
99 }
100 }
101 return count, nil
102 }
103
104 func getNprocs() int64 {
105 count, err := getNprocsSysfs()
106 if err == nil {
107 return count
108 }
109
110 count, err = getNprocsProcStat()
111 if err == nil {
112 return count
113 }
114
115
116 return int64(runtime.NumCPU())
117 }
118
119 func getNprocsConf() int64 {
120 count, err := numcpus.GetConfigured()
121 if err == nil {
122 return int64(count)
123 }
124
125
126
127
128 return getNprocs()
129 }
130
131 func hasClock(clockid int32) bool {
132 var res unix.Timespec
133 if err := unix.ClockGetres(clockid, &res); err != nil {
134 return false
135 }
136 return true
137 }
138
139 func max(a, b int64) int64 {
140 if a > b {
141 return a
142 }
143 return b
144 }
145
146 func sysconf(name int) (int64, error) {
147 switch name {
148 case SC_AIO_LISTIO_MAX:
149 return -1, nil
150 case SC_AIO_MAX:
151 return -1, nil
152 case SC_AIO_PRIO_DELTA_MAX:
153 return _AIO_PRIO_DELTA_MAX, nil
154 case SC_ARG_MAX:
155 argMax := int64(_POSIX_ARG_MAX)
156 var rlim unix.Rlimit
157 if err := unix.Getrlimit(unix.RLIMIT_STACK, &rlim); err == nil {
158 argMax = max(argMax, int64(rlim.Cur/4))
159 }
160 return argMax, nil
161 case SC_ATEXIT_MAX:
162 return _INT_MAX, nil
163 case SC_CHILD_MAX:
164 childMax := int64(-1)
165 var rlim unix.Rlimit
166 if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlim); err == nil && rlim.Cur != unix.RLIM_INFINITY {
167 childMax = int64(rlim.Cur)
168 }
169 return childMax, nil
170 case SC_CLK_TCK:
171 return _SYSTEM_CLK_TCK, nil
172 case SC_DELAYTIMER_MAX:
173 return _DELAYTIMER_MAX, nil
174 case SC_GETGR_R_SIZE_MAX:
175 return _NSS_BUFLEN_GROUP, nil
176 case SC_GETPW_R_SIZE_MAX:
177 return _NSS_BUFLEN_PASSWD, nil
178 case SC_MQ_OPEN_MAX:
179 return -1, nil
180 case SC_MQ_PRIO_MAX:
181 return _MQ_PRIO_MAX, nil
182 case SC_NGROUPS_MAX:
183 return readProcFsInt64("/proc/sys/kernel/ngroups_max", _NGROUPS_MAX), nil
184 case SC_OPEN_MAX:
185 openMax := int64(_OPEN_MAX)
186 var rlim unix.Rlimit
187 if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlim); err == nil {
188 openMax = int64(rlim.Cur)
189 }
190 return openMax, nil
191 case SC_RTSIG_MAX:
192 return _RTSIG_MAX, nil
193 case SC_SEM_NSEMS_MAX:
194 return -1, nil
195 case SC_SEM_VALUE_MAX:
196 return _SEM_VALUE_MAX, nil
197 case SC_SIGQUEUE_MAX:
198 var rlim unix.Rlimit
199 if err := unix.Getrlimit(unix.RLIMIT_SIGPENDING, &rlim); err == nil {
200 return int64(rlim.Cur), nil
201 }
202 return readProcFsInt64("/proc/sys/kernel/rtsig-max", _POSIX_SIGQUEUE_MAX), nil
203 case SC_STREAM_MAX:
204 return _STREAM_MAX, nil
205 case SC_THREAD_DESTRUCTOR_ITERATIONS:
206 return _POSIX_THREAD_DESTRUCTOR_ITERATIONS, nil
207 case SC_THREAD_KEYS_MAX:
208 return _PTHREAD_KEYS_MAX, nil
209 case SC_THREAD_PRIO_INHERIT:
210 return _POSIX_THREAD_PRIO_INHERIT, nil
211 case SC_THREAD_PRIO_PROTECT:
212 return _POSIX_THREAD_PRIO_PROTECT, nil
213 case SC_THREAD_STACK_MIN:
214 return _PTHREAD_STACK_MIN, nil
215 case SC_THREAD_THREADS_MAX:
216 return -1, nil
217 case SC_TIMER_MAX:
218 return -1, nil
219 case SC_TTY_NAME_MAX:
220 return _TTY_NAME_MAX, nil
221 case SC_TZNAME_MAX:
222 return -1, nil
223
224 case SC_CPUTIME:
225 if hasClock(unix.CLOCK_PROCESS_CPUTIME_ID) {
226 return _POSIX_VERSION, nil
227 }
228 return -1, nil
229 case SC_MONOTONIC_CLOCK:
230 if hasClock(unix.CLOCK_MONOTONIC) {
231 return _POSIX_VERSION, nil
232 }
233 return -1, nil
234 case SC_SAVED_IDS:
235 return _POSIX_SAVED_IDS, nil
236 case SC_SPAWN:
237 return _POSIX_SPAWN, nil
238 case SC_SPIN_LOCKS:
239 return _POSIX_SPIN_LOCKS, nil
240 case SC_SPORADIC_SERVER:
241 return _POSIX_SPORADIC_SERVER, nil
242 case SC_SYNCHRONIZED_IO:
243 return _POSIX_SYNCHRONIZED_IO, nil
244 case SC_THREAD_ATTR_STACKADDR:
245 return _POSIX_THREAD_ATTR_STACKADDR, nil
246 case SC_THREAD_ATTR_STACKSIZE:
247 return _POSIX_THREAD_ATTR_STACKSIZE, nil
248 case SC_THREAD_CPUTIME:
249 if hasClock(unix.CLOCK_THREAD_CPUTIME_ID) {
250 return _POSIX_VERSION, nil
251 }
252 return -1, nil
253 case SC_THREAD_PRIORITY_SCHEDULING:
254 return _POSIX_THREAD_PRIORITY_SCHEDULING, nil
255 case SC_THREAD_PROCESS_SHARED:
256 return _POSIX_THREAD_PROCESS_SHARED, nil
257 case SC_THREAD_SAFE_FUNCTIONS:
258 return _POSIX_THREAD_SAFE_FUNCTIONS, nil
259 case SC_THREAD_SPORADIC_SERVER:
260 return _POSIX_THREAD_SPORADIC_SERVER, nil
261 case SC_TRACE:
262 return _POSIX_TRACE, nil
263 case SC_TRACE_EVENT_FILTER:
264 return _POSIX_TRACE_EVENT_FILTER, nil
265 case SC_TRACE_EVENT_NAME_MAX:
266 return -1, nil
267 case SC_TRACE_INHERIT:
268 return _POSIX_TRACE_INHERIT, nil
269 case SC_TRACE_LOG:
270 return _POSIX_TRACE_LOG, nil
271 case SC_TRACE_NAME_MAX:
272 return -1, nil
273 case SC_TRACE_SYS_MAX:
274 return -1, nil
275 case SC_TRACE_USER_EVENT_MAX:
276 return -1, nil
277 case SC_TYPED_MEMORY_OBJECTS:
278 return _POSIX_TYPED_MEMORY_OBJECTS, nil
279
280 case SC_V7_ILP32_OFF32:
281 return _POSIX_V7_ILP32_OFF32, nil
282 case SC_V7_ILP32_OFFBIG:
283 return _POSIX_V7_ILP32_OFFBIG, nil
284 case SC_V7_LP64_OFF64:
285 return _POSIX_V7_LP64_OFF64, nil
286 case SC_V7_LPBIG_OFFBIG:
287 return _POSIX_V7_LPBIG_OFFBIG, nil
288
289 case SC_V6_ILP32_OFF32:
290 return _POSIX_V6_ILP32_OFF32, nil
291 case SC_V6_ILP32_OFFBIG:
292 return _POSIX_V6_ILP32_OFFBIG, nil
293 case SC_V6_LP64_OFF64:
294 return _POSIX_V6_LP64_OFF64, nil
295 case SC_V6_LPBIG_OFFBIG:
296 return _POSIX_V6_LPBIG_OFFBIG, nil
297
298 case SC_2_C_VERSION:
299 return _POSIX2_C_VERSION, nil
300 case SC_2_CHAR_TERM:
301 return _POSIX2_CHAR_TERM, nil
302 case SC_2_PBS,
303 SC_2_PBS_ACCOUNTING,
304 SC_2_PBS_CHECKPOINT,
305 SC_2_PBS_LOCATE,
306 SC_2_PBS_MESSAGE,
307 SC_2_PBS_TRACK:
308 return -1, nil
309 case SC_2_UPE:
310 return -1, nil
311
312 case SC_XOPEN_CRYPT:
313
314 return -1, nil
315 case SC_XOPEN_ENH_I18N:
316 return _XOPEN_ENH_I18N, nil
317 case SC_XOPEN_REALTIME:
318 return _XOPEN_REALTIME, nil
319 case SC_XOPEN_REALTIME_THREADS:
320 return _XOPEN_REALTIME_THREADS, nil
321 case SC_XOPEN_SHM:
322 return _XOPEN_SHM, nil
323 case SC_XOPEN_STREAMS:
324 return -1, nil
325 case SC_XOPEN_UNIX:
326 return _XOPEN_UNIX, nil
327 case SC_XOPEN_VERSION:
328 return _XOPEN_VERSION, nil
329 case SC_XOPEN_XCU_VERSION:
330 return _XOPEN_XCU_VERSION, nil
331
332 case SC_PHYS_PAGES:
333 return getPhysPages(), nil
334 case SC_AVPHYS_PAGES:
335 return getAvPhysPages(), nil
336 case SC_NPROCESSORS_CONF:
337 return getNprocsConf(), nil
338 case SC_NPROCESSORS_ONLN:
339 return getNprocs(), nil
340 case SC_UIO_MAXIOV:
341 return _UIO_MAXIOV, nil
342 }
343
344 return sysconfGeneric(name)
345 }
346
View as plain text