Browse Source

avoid linear-time if/else special cases in sysconf

the previous handling of cases that could not fit in the 16-bit table
or which required non-constant results was extremely ugly and could
not scale. the new code remaps these keys into a contiguous range
that's efficient for a switch statement.
master
Rich Felker 12 years ago
parent
commit
233767b48a
  1. 55
      src/conf/sysconf.c

55
src/conf/sysconf.c

@ -6,15 +6,21 @@
#include "syscall.h" #include "syscall.h"
#include "libc.h" #include "libc.h"
#define VER (-2) #define JT(x) (-256|(x))
#define OFLOW (-3) #define VER JT(1)
#define CPUCNT (-4) #define JT_ARG_MAX JT(2)
#define JT_MQ_PRIO_MAX JT(3)
#define JT_PAGE_SIZE JT(4)
#define JT_SEM_VALUE_MAX JT(5)
#define JT_NPROCESSORS_CONF JT(6)
#define JT_NPROCESSORS_ONLN JT(7)
#define RLIM(x) (-32768|(RLIMIT_ ## x)) #define RLIM(x) (-32768|(RLIMIT_ ## x))
long sysconf(int name) long sysconf(int name)
{ {
static const short values[] = { static const short values[] = {
[_SC_ARG_MAX] = OFLOW, [_SC_ARG_MAX] = JT_ARG_MAX,
[_SC_CHILD_MAX] = RLIM(NPROC), [_SC_CHILD_MAX] = RLIM(NPROC),
[_SC_CLK_TCK] = 100, [_SC_CLK_TCK] = 100,
[_SC_NGROUPS_MAX] = 32, [_SC_NGROUPS_MAX] = 32,
@ -42,12 +48,12 @@ long sysconf(int name)
[_SC_AIO_PRIO_DELTA_MAX] = 0, /* ?? */ [_SC_AIO_PRIO_DELTA_MAX] = 0, /* ?? */
[_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX, [_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX,
[_SC_MQ_OPEN_MAX] = -1, [_SC_MQ_OPEN_MAX] = -1,
[_SC_MQ_PRIO_MAX] = OFLOW, [_SC_MQ_PRIO_MAX] = JT_MQ_PRIO_MAX,
[_SC_VERSION] = VER, [_SC_VERSION] = VER,
[_SC_PAGE_SIZE] = OFLOW, [_SC_PAGE_SIZE] = JT_PAGE_SIZE,
[_SC_RTSIG_MAX] = _NSIG - 1 - 31 - 3, [_SC_RTSIG_MAX] = _NSIG - 1 - 31 - 3,
[_SC_SEM_NSEMS_MAX] = SEM_NSEMS_MAX, [_SC_SEM_NSEMS_MAX] = SEM_NSEMS_MAX,
[_SC_SEM_VALUE_MAX] = OFLOW, [_SC_SEM_VALUE_MAX] = JT_SEM_VALUE_MAX,
[_SC_SIGQUEUE_MAX] = -1, [_SC_SIGQUEUE_MAX] = -1,
[_SC_TIMER_MAX] = -1, [_SC_TIMER_MAX] = -1,
[_SC_BC_BASE_MAX] = _POSIX2_BC_BASE_MAX, [_SC_BC_BASE_MAX] = _POSIX2_BC_BASE_MAX,
@ -97,8 +103,8 @@ long sysconf(int name)
[_SC_THREAD_PRIO_INHERIT] = -1, [_SC_THREAD_PRIO_INHERIT] = -1,
[_SC_THREAD_PRIO_PROTECT] = -1, [_SC_THREAD_PRIO_PROTECT] = -1,
[_SC_THREAD_PROCESS_SHARED] = VER, [_SC_THREAD_PROCESS_SHARED] = VER,
[_SC_NPROCESSORS_CONF] = CPUCNT, [_SC_NPROCESSORS_CONF] = JT_NPROCESSORS_CONF,
[_SC_NPROCESSORS_ONLN] = CPUCNT, [_SC_NPROCESSORS_ONLN] = JT_NPROCESSORS_ONLN,
[_SC_PHYS_PAGES] = -1, [_SC_PHYS_PAGES] = -1,
[_SC_AVPHYS_PAGES] = -1, [_SC_AVPHYS_PAGES] = -1,
[_SC_ATEXIT_MAX] = -1, [_SC_ATEXIT_MAX] = -1,
@ -215,28 +221,37 @@ long sysconf(int name)
[_SC_THREAD_ROBUST_PRIO_INHERIT] = -1, [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1,
[_SC_THREAD_ROBUST_PRIO_PROTECT] = -1, [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1,
}; };
if (name > sizeof(values)/sizeof(values[0])) { if (name > sizeof(values)/sizeof(values[0])) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} else if (values[name] == VER) { } else if (values[name] >= -1) {
return values[name];
} else if (values[name] < -256) {
long lim[2];
__syscall(SYS_getrlimit, values[name]&16383, lim);
return lim[0] < 0 ? LONG_MAX : lim[0];
}
switch ((unsigned char)values[name]) {
case VER & 255:
return _POSIX_VERSION; return _POSIX_VERSION;
} else if (values[name] == OFLOW) { case JT_ARG_MAX & 255:
if (name == _SC_ARG_MAX) return ARG_MAX; return ARG_MAX;
if (name == _SC_SEM_VALUE_MAX) return SEM_VALUE_MAX; case JT_MQ_PRIO_MAX & 255:
if (name == _SC_MQ_PRIO_MAX) return MQ_PRIO_MAX; return MQ_PRIO_MAX;
/* name == _SC_PAGE_SIZE */ case JT_PAGE_SIZE & 255:
return PAGE_SIZE; return PAGE_SIZE;
} else if (values[name] == CPUCNT) { case JT_SEM_VALUE_MAX & 255:
return SEM_VALUE_MAX;
case JT_NPROCESSORS_CONF & 255:
case JT_NPROCESSORS_ONLN & 255: ;
unsigned char set[128] = {1}; unsigned char set[128] = {1};
int i, cnt; int i, cnt;
__syscall(SYS_sched_getaffinity, 0, sizeof set, set); __syscall(SYS_sched_getaffinity, 0, sizeof set, set);
for (i=cnt=0; i<sizeof set; i++) for (i=cnt=0; i<sizeof set; i++)
for (; set[i]; set[i]&=set[i]-1, cnt++); for (; set[i]; set[i]&=set[i]-1, cnt++);
return cnt; return cnt;
} else if (values[name] < OFLOW) {
long lim[2];
__syscall(SYS_getrlimit, values[name]&16383, lim);
return lim[0] < 0 ? LONG_MAX : lim[0];
} }
return values[name]; return values[name];
} }

Loading…
Cancel
Save