4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-25 16:47:20 +08:00
Corinna Vinschen ca2a4ec243 Cygwin: execve: drop argument size limit
Before commit 44f73c5a6206 ("Cygwin: Fix segfalt when too many command
line args are specified.") we had no actual argument size limit, except
for the fact that the child process created another copy of the argv
array on the stack, which could result in a stack overflow and a
subsequent SEGV.  Commit 44f73c5a6206 changed that by allocating the
additional argv array via malloc, and it introduced a new SC_ARG_MAX
limit along the lines of the typical Linux limit.

However, this new limit is artificial. Cygwin allocates all argument
and environment data on the cygheap.  We only run out of ARG_MAX space
if we're out of memory resources.

Change argument size handling accordingly:
- Drop the args size check from  child_info_spawn::worker.
- Return -1 from sysconf (SC_ARG_MAX), i. e., the argument size limit
  is undefined.
- Change argv handling in class av, so that a failing cmalloc is not
  fatal.  This allows the parent process to return E2BIG if it's out
  of cygheap resources.
- In the child, add a check around the new malloc call, so that it
  doesn't result in a SEGV if the child process gets unexpectedly into
  an ENOMEM situation at this point. In this (unlikely) case, proceed
  with the original __argv array instead.  Add comment to explain why.

Fixes: 44f73c5a6206 ("Cygwin: Fix segfalt when too many command line args are specified.")
Tested-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2023-08-29 14:17:04 +02:00

828 lines
25 KiB
C++

/* sysconf.cc
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <unistd.h>
#include <sys/param.h>
#include <sys/sysinfo.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "pinfo.h"
#include "ntdll.h"
#include "tls_pbuf.h"
#include "cpuid.h"
#include "clock.h"
static long
get_page_size (int in)
{
return wincap.allocation_granularity ();
}
static bool
__nt_query_system (PSYSTEM_BASIC_INFORMATION psbi)
{
NTSTATUS status;
status = NtQuerySystemInformation (SystemBasicInformation, (PVOID) psbi,
sizeof *psbi, NULL);
return NT_SUCCESS (status);
}
#define add_size(p,s) ((p) = ((__typeof__(p))((PBYTE)(p)+(s))))
static long
get_nproc_values (int in)
{
tmp_pathbuf tp;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX lpi, plpi;
DWORD lpi_size = NT_MAX_PATH;
long cnt = 0;
lpi = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) tp.c_get ();
if (!GetLogicalProcessorInformationEx (RelationGroup, lpi, &lpi_size))
return -1;
plpi = lpi;
for (DWORD size = lpi_size; size > 0;
size -= plpi->Size, add_size (plpi, plpi->Size))
if (plpi->Relationship == RelationGroup)
{
for (WORD i = 0; i < plpi->Group.MaximumGroupCount; ++i)
switch (in)
{
case _SC_NPROCESSORS_CONF:
cnt += plpi->Group.GroupInfo[0].MaximumProcessorCount;
break;
case _SC_NPROCESSORS_ONLN:
cnt += plpi->Group.GroupInfo[0].ActiveProcessorCount;
break;
}
}
return cnt;
}
static long
get_phys_pages (int in)
{
SYSTEM_BASIC_INFORMATION sbi;
if (!__nt_query_system (&sbi))
return -1;
return sbi.NumberOfPhysicalPages
/ (wincap.allocation_granularity () / wincap.page_size ());
}
static long
get_avphys (int in)
{
NTSTATUS status;
SYSTEM_PERFORMANCE_INFORMATION spi;
status = NtQuerySystemInformation (SystemPerformanceInformation,
(PVOID) &spi, sizeof spi, NULL);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
debug_printf ("NtQuerySystemInformation: status %y, %E", status);
return -1;
}
return spi.AvailablePages
/ (wincap.allocation_granularity () / wincap.page_size ());
}
enum cache_level
{
LevelNone,
Level1I,
Level1D,
Level2,
Level3,
Level4
};
struct cpuid2_cache_desc
{
uint8_t desc;
cache_level level;
uint32_t size;
uint32_t assoc;
uint32_t linesize;
};
static const cpuid2_cache_desc cpuid2_cache_descriptor[] =
{
{ 0x06, Level1I, 8, 4, 32 },
{ 0x08, Level1I, 16, 4, 32 },
{ 0x09, Level1I, 32, 4, 64 },
{ 0x0a, Level1D, 8, 2, 32 },
{ 0x0c, Level1D, 16, 4, 32 },
{ 0x0d, Level1D, 16, 4, 64 },
{ 0x0e, Level1D, 24, 6, 64 },
{ 0x21, Level2, 256, 8, 64 },
{ 0x22, Level3, 512, 4, 64 },
{ 0x23, Level3, 1024, 8, 64 },
{ 0x25, Level3, 2048, 8, 64 },
{ 0x29, Level3, 4096, 8, 64 },
{ 0x2c, Level1D, 32, 8, 64 },
{ 0x30, Level1I, 32, 8, 64 },
{ 0x39, Level2, 128, 4, 64 },
{ 0x3a, Level2, 192, 6, 64 },
{ 0x3b, Level2, 128, 2, 64 },
{ 0x3c, Level2, 256, 4, 64 },
{ 0x3d, Level2, 384, 6, 64 },
{ 0x3e, Level2, 512, 4, 64 },
{ 0x3f, Level2, 256, 2, 64 },
{ 0x41, Level2, 128, 4, 32 },
{ 0x42, Level2, 256, 4, 32 },
{ 0x43, Level2, 512, 4, 32 },
{ 0x44, Level2, 1024, 4, 32 },
{ 0x45, Level2, 2048, 4, 32 },
{ 0x46, Level3, 4096, 4, 64 },
{ 0x47, Level3, 8192, 8, 64 },
{ 0x48, Level2, 3072, 12, 64 },
{ 0x49, Level3, 4096, 16, 64 },
{ 0x4a, Level3, 6144, 12, 64 },
{ 0x4b, Level3, 8192, 16, 64 },
{ 0x4c, Level3, 12288, 12, 64 },
{ 0x4d, Level3, 16384, 16, 64 },
{ 0x4e, Level2, 6144, 24, 64 },
{ 0x60, Level1D, 16, 8, 64 },
{ 0x66, Level1D, 8, 4, 64 },
{ 0x67, Level1D, 16, 4, 64 },
{ 0x68, Level1D, 32, 4, 64 },
{ 0x78, Level2, 1024, 4, 64 },
{ 0x79, Level2, 128, 8, 64 },
{ 0x7a, Level2, 256, 8, 64 },
{ 0x7b, Level2, 512, 8, 64 },
{ 0x7c, Level2, 1024, 8, 64 },
{ 0x7d, Level2, 2048, 8, 64 },
{ 0x7f, Level2, 512, 2, 64 },
{ 0x80, Level2, 512, 8, 64 },
{ 0x82, Level2, 256, 8, 32 },
{ 0x83, Level2, 512, 8, 32 },
{ 0x84, Level2, 1024, 8, 32 },
{ 0x85, Level2, 2048, 8, 32 },
{ 0x86, Level2, 512, 4, 64 },
{ 0x87, Level2, 1024, 8, 64 },
{ 0xd0, Level3, 512, 4, 64 },
{ 0xd1, Level3, 1024, 4, 64 },
{ 0xd2, Level3, 2048, 4, 64 },
{ 0xd6, Level3, 1024, 8, 64 },
{ 0xd7, Level3, 2048, 8, 64 },
{ 0xd8, Level3, 4096, 12, 64 },
{ 0xdc, Level3, 2048, 12, 64 },
{ 0xdd, Level3, 4096, 12, 64 },
{ 0xde, Level3, 8192, 12, 64 },
{ 0xe2, Level3, 2048, 16, 64 },
{ 0xe3, Level3, 4096, 16, 64 },
{ 0xe4, Level3, 8192, 16, 64 },
{ 0xea, Level3, 12288, 24, 64 },
{ 0xeb, Level3, 18432, 24, 64 },
{ 0xec, Level3, 24576, 24, 64 },
};
static int
cpuid2_cache_desc_compar (const void *key, const void *memb)
{
cpuid2_cache_desc *ckey = (cpuid2_cache_desc *) key;
cpuid2_cache_desc *cmemb = (cpuid2_cache_desc *) memb;
return ckey->desc - cmemb->desc;
}
static long
get_cpu_cache_intel_cpuid2 (int in)
{
uint32_t reg[4];
long ret = 0;
int num;
cpuid (reg, reg + 1, reg + 2, reg + 3, 0x00000002);
num = reg[0] & 0xff;
for (int i = 0; i < num; ++i)
{
cpuid (reg, reg + 1, reg + 2, reg + 3, 0x00000002);
for (int r = 0; r < 4; ++r)
{
if (reg[r] & 0x80000000)
continue;
for (int b = (r == 0) ? 1 : 0; b < 4; ++b)
{
cpuid2_cache_desc key, *cdp;
key.desc = ((uint8_t *) &reg[r])[b];
cdp = (cpuid2_cache_desc *)
bsearch (&key, cpuid2_cache_descriptor,
sizeof cpuid2_cache_descriptor
/ sizeof *cpuid2_cache_descriptor,
sizeof *cpuid2_cache_descriptor,
cpuid2_cache_desc_compar);
if (!cdp)
continue;
switch (in)
{
case _SC_LEVEL1_ICACHE_SIZE:
if (cdp->level == Level1I)
ret += cdp->size * 1024;
break;
case _SC_LEVEL1_ICACHE_ASSOC:
if (cdp->level == Level1I)
return cdp->assoc;
break;
case _SC_LEVEL1_ICACHE_LINESIZE:
if (cdp->level == Level1I)
return cdp->linesize;
break;
case _SC_LEVEL1_DCACHE_SIZE:
if (cdp->level == Level1D)
ret += cdp->size * 1024;
break;
case _SC_LEVEL1_DCACHE_ASSOC:
if (cdp->level == Level1D)
return cdp->assoc;
break;
case _SC_LEVEL1_DCACHE_LINESIZE:
if (cdp->level == Level1D)
return cdp->linesize;
break;
case _SC_LEVEL2_CACHE_SIZE:
if (cdp->level == Level2)
ret += cdp->size * 1024;
break;
case _SC_LEVEL2_CACHE_ASSOC:
if (cdp->level == Level2)
return cdp->assoc;
break;
case _SC_LEVEL2_CACHE_LINESIZE:
if (cdp->level == Level2)
return cdp->linesize;
break;
case _SC_LEVEL3_CACHE_SIZE:
if (cdp->level == Level3)
ret += cdp->size * 1024;
break;
case _SC_LEVEL3_CACHE_ASSOC:
if (cdp->level == Level3)
return cdp->assoc;
break;
case _SC_LEVEL3_CACHE_LINESIZE:
if (cdp->level == Level3)
return cdp->linesize;
break;
}
}
}
}
return ret;
}
static long
get_cpu_cache_intel_cpuid4 (int in)
{
uint32_t eax, ebx, ecx, edx;
long ret = 0;
for (int idx = 0; ; ++idx)
{
uint32_t cache_type, cur_level, assoc, part, linesize, sets;
cpuid (&eax, &ebx, &ecx, &edx, 0x00000004, idx);
if ((cache_type = (eax & 0x1f))== 0)
break;
cur_level = ((eax >> 5) & 0x7);
assoc = ((ebx >> 22) & 0x3ff) + 1;
part = ((ebx >> 12) & 0x3ff) + 1;
linesize = (ebx & 0xfff) + 1;
sets = ecx + 1;
switch (in)
{
case _SC_LEVEL1_ICACHE_SIZE:
if (cur_level == 1 && cache_type == 2)
ret += assoc * part * linesize * sets;
break;
case _SC_LEVEL1_ICACHE_ASSOC:
if (cur_level == 1 && cache_type == 2)
return assoc;
break;
case _SC_LEVEL1_ICACHE_LINESIZE:
if (cur_level == 1 && cache_type == 2)
return linesize;
break;
case _SC_LEVEL1_DCACHE_SIZE:
if (cur_level == 1 && cache_type == 1)
ret += assoc * part * linesize * sets;
break;
case _SC_LEVEL1_DCACHE_ASSOC:
if (cur_level == 1 && cache_type == 1)
return assoc;
break;
case _SC_LEVEL1_DCACHE_LINESIZE:
if (cur_level == 1 && cache_type == 1)
return linesize;
break;
case _SC_LEVEL2_CACHE_SIZE:
if (cur_level == 2)
ret += assoc * part * linesize * sets;
break;
case _SC_LEVEL2_CACHE_ASSOC:
if (cur_level == 2)
return assoc;
break;
case _SC_LEVEL2_CACHE_LINESIZE:
if (cur_level == 2)
return linesize;
break;
case _SC_LEVEL3_CACHE_SIZE:
if (cur_level == 3)
ret += assoc * part * linesize * sets;
break;
case _SC_LEVEL3_CACHE_ASSOC:
if (cur_level == 3)
return assoc;
break;
case _SC_LEVEL3_CACHE_LINESIZE:
if (cur_level == 3)
return linesize;
break;
}
}
return ret;
}
/* Also called from format_proc_cpuinfo */
long
get_cpu_cache_intel (int in, uint32_t maxf)
{
long ret = 0;
switch (in)
{
case _SC_LEVEL1_ICACHE_SIZE:
case _SC_LEVEL1_ICACHE_ASSOC:
case _SC_LEVEL1_ICACHE_LINESIZE:
case _SC_LEVEL1_DCACHE_SIZE:
case _SC_LEVEL1_DCACHE_ASSOC:
case _SC_LEVEL1_DCACHE_LINESIZE:
case _SC_LEVEL2_CACHE_SIZE:
case _SC_LEVEL2_CACHE_ASSOC:
case _SC_LEVEL2_CACHE_LINESIZE:
case _SC_LEVEL3_CACHE_SIZE:
case _SC_LEVEL3_CACHE_ASSOC:
case _SC_LEVEL3_CACHE_LINESIZE:
if (maxf >= 4)
ret = get_cpu_cache_intel_cpuid4 (in);
else if (maxf >= 2)
ret = get_cpu_cache_intel_cpuid2 (in);
break;
default:
break;
}
return ret;
}
static const long assoc[16] = { 0, 1, 2, 2, 4, 4, 8, 8,
16, 16, 32, 48, 64, 96, 128, 0x8000 };
/* Also called from format_proc_cpuinfo */
long
get_cpu_cache_amd (int in, uint32_t maxe)
{
uint32_t eax, ebx, ecx, edx;
long ret = 0;
if (in >= _SC_LEVEL1_ICACHE_SIZE && in <= _SC_LEVEL1_DCACHE_LINESIZE
&& maxe >= 0x80000005)
cpuid (&eax, &ebx, &ecx, &edx, 0x80000005);
else if (in >= _SC_LEVEL2_CACHE_SIZE && in <= _SC_LEVEL3_CACHE_LINESIZE
&& maxe >= 0x80000006)
cpuid (&eax, &ebx, &ecx, &edx, 0x80000006);
else
return 0;
switch (in)
{
case _SC_LEVEL1_ICACHE_SIZE:
ret = (edx & 0xff000000) >> 14;
break;
case _SC_LEVEL1_ICACHE_ASSOC:
ret = (edx & 0xff0000) >> 16;
if (ret == 0xff)
ret = 0x8000;
break;
case _SC_LEVEL1_ICACHE_LINESIZE:
ret = (edx & 0xff);
break;
case _SC_LEVEL1_DCACHE_SIZE:
ret = (ecx & 0xff000000) >> 14;
break;
case _SC_LEVEL1_DCACHE_ASSOC:
ret = (ecx & 0xff0000) >> 16;
if (ret == 0xff)
ret = 0x8000;
break;
case _SC_LEVEL1_DCACHE_LINESIZE:
ret = (ecx & 0xff);
break;
case _SC_LEVEL2_CACHE_SIZE:
ret = (ecx & 0xffff0000) >> 6;
break;
case _SC_LEVEL2_CACHE_ASSOC:
ret = assoc[(ecx & 0xf000) >> 12];
break;
case _SC_LEVEL2_CACHE_LINESIZE:
ret = (ecx & 0xff);
break;
case _SC_LEVEL3_CACHE_SIZE:
ret = (long) ((edx & 0xfffc0000) >> 18) * 512 * 1024;
break;
case _SC_LEVEL3_CACHE_ASSOC:
ret = assoc[(edx & 0xf000) >> 12];
break;
case _SC_LEVEL3_CACHE_LINESIZE:
ret = (edx & 0xff);
break;
default:
break;
}
return ret;
}
static long
get_cpu_cache (int in)
{
uint32_t maxf, vendor_id[4];
cpuid (&maxf, &vendor_id[0], &vendor_id[2], &vendor_id[1], 0x00000000);
vendor_id[3] = 0;
if (!strcmp ((char*) vendor_id, "GenuineIntel"))
return get_cpu_cache_intel (in, maxf & 0xffff);
else if (!strcmp ((char*)vendor_id, "AuthenticAMD")
|| !strcmp((char*)vendor_id, "HygonGenuine"))
{
uint32_t maxe = 0, unused;
cpuid (&maxe, &unused, &unused, &unused, 0x80000000);
return get_cpu_cache_amd (in, maxe);
}
return 0;
}
enum sc_type { cons, func };
static struct
{
sc_type type;
union
{
long c;
long (*f)(int);
};
} sca[] =
{
{cons, {c:-1L}}, /* 0, _SC_ARG_MAX */
{cons, {c:CHILD_MAX}}, /* 1, _SC_CHILD_MAX */
{cons, {c:CLOCKS_PER_SEC}}, /* 2, _SC_CLK_TCK */
{cons, {c:NGROUPS_MAX}}, /* 3, _SC_NGROUPS_MAX */
{cons, {c:OPEN_MAX}}, /* 4, _SC_OPEN_MAX */
{cons, {c:_POSIX_JOB_CONTROL}}, /* 5, _SC_JOB_CONTROL */
{cons, {c:_POSIX_SAVED_IDS}}, /* 6, _SC_SAVED_IDS */
{cons, {c:_POSIX_VERSION}}, /* 7, _SC_VERSION */
{func, {f:get_page_size}}, /* 8, _SC_PAGESIZE */
{func, {f:get_nproc_values}}, /* 9, _SC_NPROCESSORS_CONF */
{func, {f:get_nproc_values}}, /* 10, _SC_NPROCESSORS_ONLN */
{func, {f:get_phys_pages}}, /* 11, _SC_PHYS_PAGES */
{func, {f:get_avphys}}, /* 12, _SC_AVPHYS_PAGES */
{cons, {c:MQ_OPEN_MAX}}, /* 13, _SC_MQ_OPEN_MAX */
{cons, {c:MQ_PRIO_MAX}}, /* 14, _SC_MQ_PRIO_MAX */
{cons, {c:RTSIG_MAX}}, /* 15, _SC_RTSIG_MAX */
{cons, {c:-1L}}, /* 16, _SC_SEM_NSEMS_MAX */
{cons, {c:SEM_VALUE_MAX}}, /* 17, _SC_SEM_VALUE_MAX */
{cons, {c:SIGQUEUE_MAX}}, /* 18, _SC_SIGQUEUE_MAX */
{cons, {c:TIMER_MAX}}, /* 19, _SC_TIMER_MAX */
{cons, {c:-1L}}, /* 20, _SC_TZNAME_MAX */
{cons, {c:_POSIX_ASYNCHRONOUS_IO}}, /* 21, _SC_ASYNCHRONOUS_IO */
{cons, {c:_POSIX_FSYNC}}, /* 22, _SC_FSYNC */
{cons, {c:_POSIX_MAPPED_FILES}}, /* 23, _SC_MAPPED_FILES */
{cons, {c:-1L}}, /* 24, _SC_MEMLOCK */
{cons, {c:_POSIX_MEMLOCK_RANGE}}, /* 25, _SC_MEMLOCK_RANGE */
{cons, {c:_POSIX_MEMORY_PROTECTION}}, /* 26, _SC_MEMORY_PROTECTION */
{cons, {c:_POSIX_MESSAGE_PASSING}}, /* 27, _SC_MESSAGE_PASSING */
{cons, {c:-1L}}, /* 28, _SC_PRIORITIZED_IO */
{cons, {c:_POSIX_REALTIME_SIGNALS}}, /* 29, _SC_REALTIME_SIGNALS */
{cons, {c:_POSIX_SEMAPHORES}}, /* 30, _SC_SEMAPHORES */
{cons, {c:_POSIX_SHARED_MEMORY_OBJECTS}}, /* 31, _SC_SHARED_MEMORY_OBJECTS */
{cons, {c:_POSIX_SYNCHRONIZED_IO}}, /* 32, _SC_SYNCHRONIZED_IO */
{cons, {c:_POSIX_TIMERS}}, /* 33, _SC_TIMERS */
{cons, {c:AIO_LISTIO_MAX}}, /* 34, _SC_AIO_LISTIO_MAX */
{cons, {c:AIO_MAX}}, /* 35, _SC_AIO_MAX */
{cons, {c:AIO_PRIO_DELTA_MAX}}, /* 36, _SC_AIO_PRIO_DELTA_MAX */
{cons, {c:DELAYTIMER_MAX}}, /* 37, _SC_DELAYTIMER_MAX */
{cons, {c:PTHREAD_KEYS_MAX}}, /* 38, _SC_THREAD_KEYS_MAX */
{cons, {c:PTHREAD_STACK_MIN}}, /* 39, _SC_THREAD_STACK_MIN */
{cons, {c:-1L}}, /* 40, _SC_THREAD_THREADS_MAX */
{cons, {c:TTY_NAME_MAX}}, /* 41, _SC_TTY_NAME_MAX */
{cons, {c:_POSIX_THREADS}}, /* 42, _SC_THREADS */
{cons, {c:_POSIX_THREAD_ATTR_STACKADDR}},/* 43, _SC_THREAD_ATTR_STACKADDR */
{cons, {c:_POSIX_THREAD_ATTR_STACKSIZE}},/* 44, _SC_THREAD_ATTR_STACKSIZE */
{cons, {c:_POSIX_THREAD_PRIORITY_SCHEDULING}}, /* 45, _SC_THREAD_PRIORITY_SCHEDULING */
{cons, {c:-1L}}, /* 46, _SC_THREAD_PRIO_INHERIT */
{cons, {c:-1L}}, /* 47, _SC_THREAD_PRIO_PROTECT */
{cons, {c:_POSIX_THREAD_PROCESS_SHARED}}, /* 48, _SC_THREAD_PROCESS_SHARED */
{cons, {c:_POSIX_THREAD_SAFE_FUNCTIONS}}, /* 49, _SC_THREAD_SAFE_FUNCTIONS */
{cons, {c:16384L}}, /* 50, _SC_GETGR_R_SIZE_MAX */
{cons, {c:16384L}}, /* 51, _SC_GETPW_R_SIZE_MAX */
{cons, {c:LOGIN_NAME_MAX}}, /* 52, _SC_LOGIN_NAME_MAX */
{cons, {c:PTHREAD_DESTRUCTOR_ITERATIONS}}, /* 53, _SC_THREAD_DESTRUCTOR_ITERATIONS */
{cons, {c:_POSIX_ADVISORY_INFO}}, /* 54, _SC_ADVISORY_INFO */
{cons, {c:ATEXIT_MAX}}, /* 55, _SC_ATEXIT_MAX */
{cons, {c:_POSIX_BARRIERS}}, /* 56, _SC_BARRIERS */
{cons, {c:BC_BASE_MAX}}, /* 57, _SC_BC_BASE_MAX */
{cons, {c:BC_DIM_MAX}}, /* 58, _SC_BC_DIM_MAX */
{cons, {c:BC_SCALE_MAX}}, /* 59, _SC_BC_SCALE_MAX */
{cons, {c:BC_STRING_MAX}}, /* 60, _SC_BC_STRING_MAX */
{cons, {c:_POSIX_CLOCK_SELECTION}}, /* 61, _SC_CLOCK_SELECTION */
{cons, {c:-1L}}, /* 62, _SC_COLL_WEIGHTS_MAX */
{cons, {c:_POSIX_CPUTIME}}, /* 63, _SC_CPUTIME */
{cons, {c:EXPR_NEST_MAX}}, /* 64, _SC_EXPR_NEST_MAX */
{cons, {c:HOST_NAME_MAX}}, /* 65, _SC_HOST_NAME_MAX */
{cons, {c:IOV_MAX}}, /* 66, _SC_IOV_MAX */
{cons, {c:_POSIX_IPV6}}, /* 67, _SC_IPV6 */
{cons, {c:LINE_MAX}}, /* 68, _SC_LINE_MAX */
{cons, {c:_POSIX_MONOTONIC_CLOCK}}, /* 69, _SC_MONOTONIC_CLOCK */
{cons, {c:_POSIX_RAW_SOCKETS}}, /* 70, _SC_RAW_SOCKETS */
{cons, {c:_POSIX_READER_WRITER_LOCKS}}, /* 71, _SC_READER_WRITER_LOCKS */
{cons, {c:_POSIX_REGEXP}}, /* 72, _SC_REGEXP */
{cons, {c:RE_DUP_MAX}}, /* 73, _SC_RE_DUP_MAX */
{cons, {c:_POSIX_SHELL}}, /* 74, _SC_SHELL */
{cons, {c:_POSIX_SPAWN}}, /* 75, _SC_SPAWN */
{cons, {c:_POSIX_SPIN_LOCKS}}, /* 76, _SC_SPIN_LOCKS */
{cons, {c:-1L}}, /* 77, _SC_SPORADIC_SERVER */
{cons, {c:-1L}}, /* 78, _SC_SS_REPL_MAX */
{cons, {c:SYMLOOP_MAX}}, /* 79, _SC_SYMLOOP_MAX */
{cons, {c:_POSIX_THREAD_CPUTIME}}, /* 80, _SC_THREAD_CPUTIME */
{cons, {c:-1L}}, /* 81, _SC_THREAD_SPORADIC_SERVER */
{cons, {c:_POSIX_TIMEOUTS}}, /* 82, _SC_TIMEOUTS */
{cons, {c:-1L}}, /* 83, _SC_TRACE */
{cons, {c:-1L}}, /* 84, _SC_TRACE_EVENT_FILTER */
{cons, {c:-1}}, /* 85, _SC_TRACE_EVENT_NAME_MAX */
{cons, {c:-1L}}, /* 86, _SC_TRACE_INHERIT */
{cons, {c:-1L}}, /* 87, _SC_TRACE_LOG */
{cons, {c:-1L}}, /* 88, _SC_TRACE_NAME_MAX */
{cons, {c:-1L}}, /* 89, _SC_TRACE_SYS_MAX */
{cons, {c:-1L}}, /* 90, _SC_TRACE_USER_EVENT_MAX */
{cons, {c:-1L}}, /* 91, _SC_TYPED_MEMORY_OBJECTS */
{cons, {c:_POSIX_V6_ILP32_OFF32}}, /* 92, _SC_V6_ILP32_OFF32 */
{cons, {c:_POSIX_V6_ILP32_OFFBIG}}, /* 93, _SC_V6_ILP32_OFFBIG */
{cons, {c:_POSIX_V6_LP64_OFF64}}, /* 94, _SC_V6_LP64_OFF64 */
{cons, {c:_POSIX_V6_LPBIG_OFFBIG}}, /* 95, _SC_V6_LPBIG_OFFBIG */
{cons, {c:_XOPEN_CRYPT}}, /* 96, _SC_XOPEN_CRYPT */
{cons, {c:_XOPEN_ENH_I18N}}, /* 97, _SC_XOPEN_ENH_I18N */
{cons, {c:-1L}}, /* 98, _SC_XOPEN_LEGACY */
{cons, {c:-1L}}, /* 99, _SC_XOPEN_REALTIME */
{cons, {c:STREAM_MAX}}, /* 100, _SC_STREAM_MAX */
{cons, {c:_POSIX_PRIORITY_SCHEDULING}}, /* 101, _SC_PRIORITY_SCHEDULING */
{cons, {c:-1L}}, /* 102, _SC_XOPEN_REALTIME_THREADS */
{cons, {c:_XOPEN_SHM}}, /* 103, _SC_XOPEN_SHM */
{cons, {c:-1L}}, /* 104, _SC_XOPEN_STREAMS */
{cons, {c:-1L}}, /* 105, _SC_XOPEN_UNIX */
{cons, {c:_XOPEN_VERSION}}, /* 106, _SC_XOPEN_VERSION */
{cons, {c:_POSIX2_CHAR_TERM}}, /* 107, _SC_2_CHAR_TERM */
{cons, {c:_POSIX2_C_BIND}}, /* 108, _SC_2_C_BIND */
{cons, {c:_POSIX2_C_DEV}}, /* 109, _SC_2_C_DEV */
{cons, {c:-1L}}, /* 110, _SC_2_FORT_DEV */
{cons, {c:-1L}}, /* 111, _SC_2_FORT_RUN */
{cons, {c:-1L}}, /* 112, _SC_2_LOCALEDEF */
{cons, {c:-1L}}, /* 113, _SC_2_PBS */
{cons, {c:-1L}}, /* 114, _SC_2_PBS_ACCOUNTING */
{cons, {c:-1L}}, /* 115, _SC_2_PBS_CHECKPOINT */
{cons, {c:-1L}}, /* 116, _SC_2_PBS_LOCATE */
{cons, {c:-1L}}, /* 117, _SC_2_PBS_MESSAGE */
{cons, {c:-1L}}, /* 118, _SC_2_PBS_TRACK */
{cons, {c:_POSIX2_SW_DEV}}, /* 119, _SC_2_SW_DEV */
{cons, {c:_POSIX2_UPE}}, /* 120, _SC_2_UPE */
{cons, {c:_POSIX2_VERSION}}, /* 121, _SC_2_VERSION */
{cons, {c:-1L}}, /* 122, _SC_THREAD_ROBUST_PRIO_INHERIT */
{cons, {c:-1L}}, /* 123, _SC_THREAD_ROBUST_PRIO_PROTECT */
{cons, {c:-1L}}, /* 124, _SC_XOPEN_UUCP */
{func, {f:get_cpu_cache}}, /* 125, _SC_LEVEL1_ICACHE_SIZE */
{func, {f:get_cpu_cache}}, /* 126, _SC_LEVEL1_ICACHE_ASSOC */
{func, {f:get_cpu_cache}}, /* 127, _SC_LEVEL1_ICACHE_LINESIZE */
{func, {f:get_cpu_cache}}, /* 128, _SC_LEVEL1_DCACHE_SIZE */
{func, {f:get_cpu_cache}}, /* 129, _SC_LEVEL1_DCACHE_ASSOC */
{func, {f:get_cpu_cache}}, /* 130, _SC_LEVEL1_DCACHE_LINESIZE */
{func, {f:get_cpu_cache}}, /* 131, _SC_LEVEL2_CACHE_SIZE */
{func, {f:get_cpu_cache}}, /* 132, _SC_LEVEL2_CACHE_ASSOC */
{func, {f:get_cpu_cache}}, /* 133, _SC_LEVEL2_CACHE_LINESIZE */
{func, {f:get_cpu_cache}}, /* 134, _SC_LEVEL3_CACHE_SIZE */
{func, {f:get_cpu_cache}}, /* 135, _SC_LEVEL3_CACHE_ASSOC */
{func, {f:get_cpu_cache}}, /* 136, _SC_LEVEL3_CACHE_LINESIZE */
{func, {f:get_cpu_cache}}, /* 137, _SC_LEVEL4_CACHE_SIZE */
{func, {f:get_cpu_cache}}, /* 138, _SC_LEVEL4_CACHE_ASSOC */
{func, {f:get_cpu_cache}}, /* 139, _SC_LEVEL4_CACHE_LINESIZE */
};
#define SC_MIN _SC_ARG_MAX
#define SC_MAX _SC_LEVEL4_CACHE_LINESIZE
/* sysconf: POSIX 4.8.1.1 */
/* Allows a portable app to determine quantities of resources or
presence of an option at execution time. */
long int
sysconf (int in)
{
if (in >= SC_MIN && in <= SC_MAX)
{
switch (sca[in].type)
{
case cons:
return sca[in].c;
case func:
return sca[in].f (in);
}
}
/* Unimplemented sysconf name or invalid option value. */
set_errno (EINVAL);
return -1L;
}
#define ls(s) sizeof(s),s
static struct
{
size_t l;
const char *s;
} csa[] =
{
{ls ("/bin:/usr/bin")}, /* _CS_PATH */
{0, NULL}, /* _CS_POSIX_V6_ILP32_OFF32_CFLAGS */
{0, NULL}, /* _CS_POSIX_V6_ILP32_OFF32_LDFLAGS */
{0, NULL}, /* _CS_POSIX_V6_ILP32_OFF32_LIBS */
{0, NULL}, /* _CS_XBS5_ILP32_OFF32_LINTFLAGS */
{0, NULL}, /* _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS */
{0, NULL}, /* _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS */
{0, NULL}, /* _CS_POSIX_V6_ILP32_OFFBIG_LIBS */
{0, NULL}, /* _CS_XBS5_ILP32_OFFBIG_LINTFLAGS */
{ls ("")}, /* _CS_POSIX_V6_LP64_OFF64_CFLAGS */
{ls ("")}, /* _CS_POSIX_V6_LP64_OFF64_LDFLAGS */
{ls ("")}, /* _CS_POSIX_V6_LP64_OFF64_LIBS */
{ls ("")}, /* _CS_XBS5_LP64_OFF64_LINTFLAGS */
{ls ("")}, /* _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS */
{ls ("")}, /* _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS */
{ls ("")}, /* _CS_POSIX_V6_LPBIG_OFFBIG_LIBS */
{ls ("")}, /* _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS */
{ls ("POSIX_V6_LP64_OFF64")}, /* _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS */
{ls ("")}, /* _CS_POSIX_V7_THREADS_CFLAGS */
{ls ("")}, /* _CS_POSIX_V7_THREADS_LDFLAGS */
{ls ("POSIXLY_CORRECT=1")}, /* _CS_V7_ENV */
{ls ("")}, /* _CS_LFS_CFLAGS */
{ls ("")}, /* _CS_LFS_LDFLAGS */
{ls ("")}, /* _CS_LFS_LIBS */
{ls ("")}, /* _CS_LFS_LINTFLAGS */
};
#define CS_MIN _CS_PATH
#define CS_MAX _CS_LFS_LINTFLAGS
extern "C" size_t
confstr (int in, char *buf, size_t len)
{
if (in >= CS_MIN && in <= CS_MAX)
{
if (csa[in].l && len)
{
buf[0] = 0;
strncat (buf, csa[in].s, MIN (len, csa[in].l) - 1);
}
return csa[in].l;
}
/* Invalid option value. */
set_errno (EINVAL);
return 0;
}
extern "C" int
get_nprocs_conf (void)
{
return get_nproc_values (_SC_NPROCESSORS_CONF);
}
extern "C" int
get_nprocs (void)
{
return get_nproc_values (_SC_NPROCESSORS_ONLN);
}
extern "C" long
get_phys_pages (void)
{
return get_phys_pages (_SC_PHYS_PAGES);
}
extern "C" long
get_avphys_pages (void)
{
return get_avphys (_SC_AVPHYS_PAGES);
}
extern "C" int
sysinfo (struct sysinfo *info)
{
unsigned long long uptime = 0ULL, totalram = 0ULL, freeram = 0ULL,
totalswap = 0ULL, freeswap = 0ULL;
MEMORYSTATUSEX memory_status;
PSYSTEM_PAGEFILE_INFORMATION spi = NULL;
ULONG sizeof_spi = 512;
PSYSTEM_TIMEOFDAY_INFORMATION stodi = NULL;
const ULONG sizeof_stodi = sizeof (SYSTEM_TIMEOFDAY_INFORMATION);
NTSTATUS status = STATUS_SUCCESS;
winpids pids ((DWORD) 0);
if (!info)
{
set_errno (EFAULT);
return -1;
}
stodi = (PSYSTEM_TIMEOFDAY_INFORMATION) malloc (sizeof_stodi);
status = NtQuerySystemInformation (SystemTimeOfDayInformation, (PVOID) stodi,
sizeof_stodi, NULL);
if (NT_SUCCESS (status))
uptime = (stodi->CurrentTime.QuadPart - stodi->BootTime.QuadPart)
/ NS100PERSEC;
else
debug_printf ("NtQuerySystemInformation(SystemTimeOfDayInformation), "
"status %y", status);
if (stodi)
free (stodi);
memory_status.dwLength = sizeof (MEMORYSTATUSEX);
GlobalMemoryStatusEx (&memory_status);
totalram = memory_status.ullTotalPhys / wincap.page_size ();
freeram = memory_status.ullAvailPhys / wincap.page_size ();
spi = (PSYSTEM_PAGEFILE_INFORMATION) malloc (sizeof_spi);
if (spi)
{
status = NtQuerySystemInformation (SystemPagefileInformation, (PVOID) spi,
sizeof_spi, &sizeof_spi);
if (status == STATUS_INFO_LENGTH_MISMATCH)
{
free (spi);
spi = (PSYSTEM_PAGEFILE_INFORMATION) malloc (sizeof_spi);
if (spi)
status = NtQuerySystemInformation (SystemPagefileInformation,
(PVOID) spi, sizeof_spi,
&sizeof_spi);
}
}
if (!spi || !NT_SUCCESS (status))
{
debug_printf ("NtQuerySystemInformation(SystemPagefileInformation), "
"status %y", status);
totalswap = (memory_status.ullTotalPageFile - memory_status.ullTotalPhys)
/ wincap.page_size ();
freeswap = (memory_status.ullAvailPageFile - memory_status.ullTotalPhys)
/ wincap.page_size ();
}
else
{
PSYSTEM_PAGEFILE_INFORMATION spp = spi;
do
{
totalswap += spp->CurrentSize;
freeswap += spp->CurrentSize - spp->TotalUsed;
}
while (spp->NextEntryOffset
&& (spp = (PSYSTEM_PAGEFILE_INFORMATION)
((char *) spp + spp->NextEntryOffset)));
}
if (spi)
free (spi);
info->uptime = (long) uptime;
info->totalram = (unsigned long) totalram;
info->freeram = (unsigned long) freeram;
info->totalswap = (unsigned long) totalswap;
info->freeswap = (unsigned long) freeswap;
info->procs = (unsigned short) pids.npids;
info->mem_unit = (unsigned int) wincap.page_size ();
/* FIXME: unsupported */
info->loads[0] = 0UL;
info->loads[1] = 0UL;
info->loads[2] = 0UL;
info->sharedram = 0UL;
info->bufferram = 0UL;
info->totalhigh = 0UL;
info->freehigh = 0UL;
return 0;
}