diff options
author | Rich Felker <dalias@aerifal.cx> | 2014-04-15 13:30:20 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2014-04-15 13:30:20 -0400 |
commit | 233767b48a083f526557ee39aa1c773efa345972 (patch) | |
tree | edee31b5097d4a1dc594975e5e82cf903d9083e3 /src | |
parent | 805698401dbac7ce3079fa97eaad5ba0508377f4 (diff) | |
download | musl-233767b48a083f526557ee39aa1c773efa345972.tar.gz musl-233767b48a083f526557ee39aa1c773efa345972.tar.xz musl-233767b48a083f526557ee39aa1c773efa345972.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/conf/sysconf.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c index 12e81368..e225c3dd 100644 --- a/src/conf/sysconf.c +++ b/src/conf/sysconf.c @@ -6,15 +6,21 @@ #include "syscall.h" #include "libc.h" -#define VER (-2) -#define OFLOW (-3) -#define CPUCNT (-4) +#define JT(x) (-256|(x)) +#define VER JT(1) +#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)) long sysconf(int name) { static const short values[] = { - [_SC_ARG_MAX] = OFLOW, + [_SC_ARG_MAX] = JT_ARG_MAX, [_SC_CHILD_MAX] = RLIM(NPROC), [_SC_CLK_TCK] = 100, [_SC_NGROUPS_MAX] = 32, @@ -42,12 +48,12 @@ long sysconf(int name) [_SC_AIO_PRIO_DELTA_MAX] = 0, /* ?? */ [_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX, [_SC_MQ_OPEN_MAX] = -1, - [_SC_MQ_PRIO_MAX] = OFLOW, + [_SC_MQ_PRIO_MAX] = JT_MQ_PRIO_MAX, [_SC_VERSION] = VER, - [_SC_PAGE_SIZE] = OFLOW, + [_SC_PAGE_SIZE] = JT_PAGE_SIZE, [_SC_RTSIG_MAX] = _NSIG - 1 - 31 - 3, [_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_TIMER_MAX] = -1, [_SC_BC_BASE_MAX] = _POSIX2_BC_BASE_MAX, @@ -97,8 +103,8 @@ long sysconf(int name) [_SC_THREAD_PRIO_INHERIT] = -1, [_SC_THREAD_PRIO_PROTECT] = -1, [_SC_THREAD_PROCESS_SHARED] = VER, - [_SC_NPROCESSORS_CONF] = CPUCNT, - [_SC_NPROCESSORS_ONLN] = CPUCNT, + [_SC_NPROCESSORS_CONF] = JT_NPROCESSORS_CONF, + [_SC_NPROCESSORS_ONLN] = JT_NPROCESSORS_ONLN, [_SC_PHYS_PAGES] = -1, [_SC_AVPHYS_PAGES] = -1, [_SC_ATEXIT_MAX] = -1, @@ -215,28 +221,37 @@ long sysconf(int name) [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1, [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1, }; + if (name > sizeof(values)/sizeof(values[0])) { errno = EINVAL; 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; - } else if (values[name] == OFLOW) { - if (name == _SC_ARG_MAX) return ARG_MAX; - if (name == _SC_SEM_VALUE_MAX) return SEM_VALUE_MAX; - if (name == _SC_MQ_PRIO_MAX) return MQ_PRIO_MAX; - /* name == _SC_PAGE_SIZE */ + case JT_ARG_MAX & 255: + return ARG_MAX; + case JT_MQ_PRIO_MAX & 255: + return MQ_PRIO_MAX; + case JT_PAGE_SIZE & 255: 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}; int i, cnt; __syscall(SYS_sched_getaffinity, 0, sizeof set, set); for (i=cnt=0; i<sizeof set; i++) for (; set[i]; set[i]&=set[i]-1, 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]; } |