difference for sysctlbyname() on i386/amd64

Hello,

Somebody can explain strange behaviour of this code on i386 and amd64 platform FreeBSD?

test.c
Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>

int main()
{
unsigned int physmem=0;
size_t len;

len = sizeof(physmem);
if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == -1)
    printf("sysctlbyname ;(",0);
else printf("%d",physmem);
}

on the first host:
% sysctl hw.machine_arch kern.osrelease
hw.machine_arch: i386
kern.osrelease: 7.1-PRERELEASE
% cc test.c -o test
% ./test
Result (it correct numbers byte for my RAM):
Code:
1592954880

at the second host:
% sysctl hw.machine_arch kern.osrelease
hw.machine_arch: amd64
kern.osrelease: 7.1-PRERELEASE
% cc test.c -o test
test.c: In function 'main':
test.c:11: warning: passing argument 3 of 'sysctlbyname' from incompatible pointer type
% ./test
Result:
Code:
sysctlbyname ;(

What the difference ( Without taking in the follow sample for "-W" Warning level in cc ) between i386/amd64 ?

Thanks!
 
Hi Ole,

Can you try to put
Code:
short len;

instead of
Code:
size_t len;

when running the program on the AMD64 and see what happens?
 
Interesting!

On my i386 system, your program works fine. Also,
Code:
printf("%d", sizeof(size_t));

gives 4.

If I declare len as of another type i.e.
Code:
short len;
or
Code:
long len;

I get the very same message
test.c: In function 'main':
test.c:11: warning: passing argument 3 of 'sysctlbyname' from incompatible pointer type
though it is just a warning and the program runs correctly.

Oddly enough, the result taken in the first case is correct, though the number produced by a 2GByte system cannot be showed by an unsigned short (max. (2^16) - 1).

Unfortunately, I can't help you because I don't have a AMD64 system to test "things".
However, if you find out anything I'd appreciate if you let me know.

EDIT: The only thing I can see is that in amd64/include/_types.h:
Code:
typedef __uint64_t __size_t;
whereas in i386/include/_types.h is:
Code:
typedef __uint32_t __size_t;

which are both:
Code:
typedef __size_t size_t;
 
  • Thanks
Reactions: Ole
anemos said:
EDIT: The only thing I can see is that in amd64/include/_types.h:
Code:
typedef __uint64_t __size_t;
whereas in i386/include/_types.h is:
Code:
typedef __uint32_t __size_t;

which are both:
Code:
typedef __size_t size_t;

Yea, i find it too ;)

now list of code
Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>

int main()
{
int mb=0;
uint64_t physmem;
size_t len = sizeof(physmem);

printf("size %d\n",len);

if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == -1)
    printf("sysctlbyname ;(");
//mb=(physmem >>= 20);
else printf("%e",physmem);   //%e (or %u ) instead %d because size is "double int", 8bytes
}

Compile&Execute on amd64 platform is fine!:
Code:
./a.out
size 8
1060519936


Thanks for response!
 
code from first post works for me.

> sysctl hw.machine_arch kern.osrelease kern.osreldate
hw.machine_arch: amd64
kern.osrelease: 8.0-CURRENT
kern.osreldate: 800060
> gcc -o test test.c
> ./test
2131050496
 
Ole said:
What the difference ( Without taking in the follow sample for "-W" Warning level in cc ) between i386/amd64 ?

I think that physmem must be 64-bit wide on AMD64:
If the amount of data available is greater than the size of the buffer supplied, the call supplies as much data as fits in the buffer provided and returns with the error code ENOMEM.
sysctlbyname()
 
Hi everyone,

I tried to rund the code in the first post, but I got warning saying "implicit declaration of sysctlbyname". I include the header file. What could be the reason for this?
 
I have this following in my sysctl.h:

...
Code:
#include<sys/cdefs.h>

--BEGIN_DECLS
int sysctl(int *, u_int , void *, size_t *, void *, size_t);
int sysctlbyname(const char *, void *, size_t *, void *, size_t);
int sysctlnametomib(const char *, int *, size_t *);
--END_DECLS
...

and I get "implicit declaration of function sysctlbyname"
 
Back
Top