CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 112
Description
Hi Everyone,
My apologies if this is extra noise... The cpuset_t
caught my eye during HURD and DragonFly compiles. Also see #73 and #75.
I believe the int
type used for cpuid_t
may be incorrect. Additionally, because cpuid_t
could be a struct on 32-bit systems, you have to use memcpy
rather then assignment to assign one. The man pages also state it:
To duplicate a CPU set, use memcpy(3).
Since CPU sets are bit masks allocated in units of long words, the
actual number of CPUs in a dynamically allocated CPU set will be
rounded up to the next multiple of sizeof(unsigned long). An
application should consider the contents of these extra bits to be
undefined.
According to <compat/cpuset.h>
, and focusing on Linux. Notice the int
typedef.
#ifndef HAVE_CPUID_T
#ifdef __linux__
typedef int cpuid_t;
#endif
#ifdef __FreeBSD__
typedef size_t cpuid_t;
#endif
#endif
On Ubuntu 18.04 x86_64 fully patched:
$ grep -IR cpu_set_t /usr/include
/usr/include/x86_64-linux-gnu/bits/cpu-set.h:} cpu_set_t;
...
And then from /usr/include/x86_64-linux-gnu/bits/cpu-set.h
:
typedef struct
{
__cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];
} cpu_set_t;
Then, find __cpu_mask
:
/usr/include/x86_64-linux-gnu/bits/cpu-set.h:typedef __CPU_MASK_TYPE __cpu_mask;
Then, find __CPU_MASK_TYPE
:
$ grep -IR __CPU_MASK_TYPE /usr/include
/usr/include/x86_64-linux-gnu/bits/typesizes.h:#define __CPU_MASK_TYPE __SYSCALL_ULONG_TYPE
Then find __SYSCALL_ULONG_TYPE
:
$ grep -IR __SYSCALL_ULONG_TYPE /usr/include
/usr/include/x86_64-linux-gnu/bits/typesizes.h:# define __SYSCALL_ULONG_TYPE __UQUAD_TYPE
/usr/include/x86_64-linux-gnu/bits/typesizes.h:# define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
This is where the problems arise. __SYSCALL_ULONG_TYPE
is either a 64-bit type (which is not an int
):
/usr/include/x86_64-linux-gnu/bits/typesizes.h:# define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
...
/usr/include/x86_64-linux-gnu/bits/typesizes.h:# define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
/usr/include/x86_64-linux-gnu/bits/types.h:#define __ULONGWORD_TYPE unsigned long int
Or it is either a struct
(which is not an int
) or unsigned long int (which is not an int
):
$ grep -IR __UQUAD_TYPE /usr/include
...
/usr/include/x86_64-linux-gnu/bits/types.h:# define __UQUAD_TYPE __u_quad_t
/usr/include/x86_64-linux-gnu/bits/types.h:# define __UQUAD_TYPE unsigned long int
In either case, it is not an int
. That seems to be important because nsd does this, which appears to slice the high word off:
./nsd.c: cpuset_set((cpuid_t)opt->cpu, nsd.cpuset);
./nsd.c: cpuset_set((cpuid_t)cpu, nsd.xfrd_cpuset);
And in case there is interest:
$ cat t.c
#include <stdio.h>
int main(void)
{
printf("sizeof unsigned long int: %d\n", (int)(sizeof(unsigned long int)));
}
And then:
$ ./t
sizeof unsigned long int: 8
Here's the 32-bit case to save you the trouble:
/* quad_t is also 64 bits. */
#if __WORDSIZE == 64
typedef long int __quad_t;
typedef unsigned long int __u_quad_t;
#elif defined __GLIBC_HAVE_LONG_LONG
__extension__ typedef long long int __quad_t;
__extension__ typedef unsigned long long int __u_quad_t;
#else
typedef struct
{
long __val[2];
} __quad_t;
typedef struct
{
__u_long __val[2];
} __u_quad_t;
#endif