Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Jun 2011 10:20:20 +0800
From:      David Xu <davidxu@freebsd.org>
To:        Sergey Kandaurov <pluknet@freebsd.org>
Cc:        Attilio Rao <attilio@freebsd.org>, FreeBSD Current <freebsd-current@freebsd.org>, Bruce Evans <bde@freebsd.org>
Subject:   Re: svn commit: r214611 - head/sys/kern
Message-ID:  <4DF816E4.1080003@freebsd.org>
In-Reply-To: <BANLkTi=TL4Yz5oR88qqorBvouWm0aYYmiQ@mail.gmail.com>
References:  <201011010042.oA10gPeg016326@svn.freebsd.org> <BANLkTi=TL4Yz5oR88qqorBvouWm0aYYmiQ@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2011/06/14 20:02, Sergey Kandaurov wrote:
> On 1 November 2010 03:42, David Xu <davidxu@freebsd.org> wrote:
>> Author: davidxu
>> Date: Mon Nov  1 00:42:25 2010
>> New Revision: 214611
>> URL: http://svn.freebsd.org/changeset/base/214611
>>
>> Log:
>>  Use integer for size of cpuset, as it won't be bigger than INT_MAX,
>>  This is requested by bge.
>>  Also move the sysctl into file kern_cpuset.c, because it should
>>  always be there, it is independent of thread scheduler.
> 
> Hi.
> This breaks for me fetching a cpusetsize value with sysconf(3) interface,
> as after this change sysconf(3) consumers expect a long return type, while
> sysctl kern.sched.cpusetsize has switched from long to int type in kernel.
> That makes for me sizeof(cpusize_t) from 8 to incorrect 34359738376.
> 
> In particular, kvm_getpcpu(3) uses sysconf(3) to fetch cpusetsize on
> live kernel. That gives me a broken result:
> kvm_open: kcpusetsize: 8
> pcpu[0] = 0x801072300
> kvm_open: kcpusetsize: 34359738376
> pcpu[1] = 0xffffffffffffffff
> kvm_open: kcpusetsize: 8
> pcpu[2] = 0x801072600
> kvm_open: kcpusetsize: 34359738376
> pcpu[3] = 0xffffffffffffffff
> 
> This small test indicates that that's due to int->long type conversion:
>         long lvalue;
>         size_t len;
> 
>         len = sizeof(lvalue);
>         if (sysctlbyname("kern.sched.cpusetsize", &lvalue, &len, NULL, 0) < 0)
>                 err(1, "sysctlbyname");
>         printf("sysctl: %ld\n", lvalue);
>         printf("sysctl: %d -- explicitly casted to (int)\n", (int)lvalue);
>         printf("sysconf: %ld\n", sysconf(_SC_CPUSET_SIZE));
>         printf("sysconf: %d -- explicitly casted to (int)\n",
> (int)sysconf(_SC_CPUSET_SIZE));
> 
> That prints:
> sysctl: 34359738376
> sysctl: 8 -- explicitly casted to (int)
> sysconf: 34359738376
> sysconf: 8 -- explicitly casted to (int)
> 
> The other way to solve this other than reverting is to "fix" all cpusetsize
> consumers in userland. Now sysconf() saves long returned value to int:
> 
> Index: lib/libkvm/kvm_pcpu.c
> ===================================================================
> --- lib/libkvm/kvm_pcpu.c       (revision 223073)
> +++ lib/libkvm/kvm_pcpu.c       (working copy)
> @@ -120,7 +120,7 @@
>  void *
>  kvm_getpcpu(kvm_t *kd, int cpu)
>  {
> -       long kcpusetsize;
> +       int kcpusetsize;
>         ssize_t nbytes;
>         uintptr_t readptr;
>         char *buf;
> 
> So, after applying the above change all is ok:
> kvm_open: kcpusetsize: 8
> pcpu[0] = 0x801072300
> kvm_open: kcpusetsize: 8
> pcpu[1] = 0x801072600
> kvm_open: kcpusetsize: 8
> pcpu[2] = 0x801072900
> kvm_open: kcpusetsize: 8
> pcpu[3] = 0x801072c00
> 
> 
Try this patch, I think it should fix it.

Index: lib/libc/gen/sysconf.c
===================================================================
--- lib/libc/gen/sysconf.c	(revision 221356)
+++ lib/libc/gen/sysconf.c	(working copy)
@@ -599,11 +599,11 @@

 #ifdef _SC_CPUSET_SIZE
 	case _SC_CPUSET_SIZE:
-		len = sizeof(lvalue);
-		if (sysctlbyname("kern.sched.cpusetsize", &lvalue, &len, NULL,
+		len = sizeof(value);
+		if (sysctlbyname("kern.sched.cpusetsize", &value, &len, NULL,
 		    0) == -1)
 			return (-1);
-		return (lvalue);
+		return ((long)(value));
 #endif

 	default:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4DF816E4.1080003>