about summary refs log tree commit diff
path: root/arch/x32/src
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2014-03-06 00:26:03 +0100
committerrofl0r <retnyg@gmx.net>2014-03-06 05:35:13 +0100
commitdae8ca738c37c7ca619f575de7a88823db17976a (patch)
treee0765125f28da929f657c0b89f3df9b89e3a8c9a /arch/x32/src
parentabdd2e48df01511603cae570695a7a3d78190e7e (diff)
downloadmusl-dae8ca738c37c7ca619f575de7a88823db17976a.tar.gz
musl-dae8ca738c37c7ca619f575de7a88823db17976a.tar.xz
musl-dae8ca738c37c7ca619f575de7a88823db17976a.zip
x32: fix sysinfo()
the kernel uses long longs in the struct, but the documentation
says they're long. so we need to fixup the mismatch between the
userspace and kernelspace structs.
since the struct offers a mem_unit member, we can avoid truncation
by adjusting that value.
Diffstat (limited to 'arch/x32/src')
-rw-r--r--arch/x32/src/sysinfo.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/arch/x32/src/sysinfo.c b/arch/x32/src/sysinfo.c
new file mode 100644
index 00000000..0f11cf3c
--- /dev/null
+++ b/arch/x32/src/sysinfo.c
@@ -0,0 +1,47 @@
+#include <sys/sysinfo.h>
+#include "syscall.h"
+
+#define klong long long
+#define kulong unsigned long long
+
+struct kernel_sysinfo {
+	klong uptime;
+	kulong loads[3];
+	kulong totalram;
+	kulong freeram;
+	kulong sharedram;
+	kulong bufferram;
+	kulong totalswap;
+	kulong freeswap;
+	short procs;
+	short pad;
+	kulong totalhigh;
+	kulong freehigh;
+	unsigned mem_unit;
+};
+
+int __x32_sysinfo(struct sysinfo *info)
+{
+	struct kernel_sysinfo tmp;
+	int ret = syscall(SYS_sysinfo, &tmp);
+	if(ret == -1) return ret;
+	info->uptime = tmp.uptime;
+	info->loads[0] = tmp.loads[0];
+	info->loads[1] = tmp.loads[1];
+	info->loads[2] = tmp.loads[2];
+	kulong shifts;
+	kulong max = tmp.totalram | tmp.totalswap;
+	__asm__("bsr %1,%0" : "=r"(shifts) : "r"(max));
+	shifts = shifts >= 32 ? shifts - 31 : 0;
+	info->totalram = tmp.totalram >> shifts;
+	info->freeram = tmp.freeram >> shifts;
+	info->sharedram = tmp.sharedram >> shifts;
+	info->bufferram = tmp.bufferram >> shifts;
+	info->totalswap = tmp.totalswap >> shifts;
+	info->freeswap = tmp.freeswap >> shifts;
+	info->procs = tmp.procs ;
+	info->totalhigh = tmp.totalhigh >> shifts;
+	info->freehigh = tmp.freehigh >> shifts;
+	info->mem_unit = (tmp.mem_unit ? tmp.mem_unit : 1) << shifts;
+	return ret;
+}