summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2011-02-07 01:05:55 -0500
committerRiku Voipio <riku.voipio@nokia.com>2011-02-09 10:33:54 +0200
commit737de1d1357b13f162b26ca0b775eb375594833a (patch)
treeb0212efdf216f31d3d753cbf046eb3532fa6b6fd
parentc3109ba1b109f84929abbfe0462d910d5aa8617c (diff)
downloadqemu-737de1d1357b13f162b26ca0b775eb375594833a.tar.gz
qemu-737de1d1357b13f162b26ca0b775eb375594833a.tar.bz2
qemu-737de1d1357b13f162b26ca0b775eb375594833a.zip
linux-user: implement sched_{g,s}etaffinity
Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Riku Voipio <riku.voipio@nokia.com>
-rw-r--r--linux-user/syscall.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bb6ef43a9e..4412a9b143 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -235,6 +235,12 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif
#endif
+#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
+_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
+ unsigned long *, user_mask_ptr);
+#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
+_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
+ unsigned long *, user_mask_ptr);
static bitmask_transtbl fcntl_flags_tbl[] = {
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
@@ -6354,6 +6360,67 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
return value. */
ret = -TARGET_ENOTDIR;
break;
+ case TARGET_NR_sched_getaffinity:
+ {
+ unsigned int mask_size;
+ unsigned long *mask;
+
+ /*
+ * sched_getaffinity needs multiples of ulong, so need to take
+ * care of mismatches between target ulong and host ulong sizes.
+ */
+ if (arg2 & (sizeof(abi_ulong) - 1)) {
+ ret = -TARGET_EINVAL;
+ break;
+ }
+ mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
+
+ mask = alloca(mask_size);
+ ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
+
+ if (!is_error(ret)) {
+ if (arg2 > ret) {
+ /* Zero out any extra space kernel didn't fill */
+ unsigned long zero = arg2 - ret;
+ p = alloca(zero);
+ memset(p, 0, zero);
+ if (copy_to_user(arg3 + zero, p, zero)) {
+ goto efault;
+ }
+ arg2 = ret;
+ }
+ if (copy_to_user(arg3, mask, arg2)) {
+ goto efault;
+ }
+ ret = arg2;
+ }
+ }
+ break;
+ case TARGET_NR_sched_setaffinity:
+ {
+ unsigned int mask_size;
+ unsigned long *mask;
+
+ /*
+ * sched_setaffinity needs multiples of ulong, so need to take
+ * care of mismatches between target ulong and host ulong sizes.
+ */
+ if (arg2 & (sizeof(abi_ulong) - 1)) {
+ ret = -TARGET_EINVAL;
+ break;
+ }
+ mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
+
+ mask = alloca(mask_size);
+ if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
+ goto efault;
+ }
+ memcpy(mask, p, arg2);
+ unlock_user_struct(p, arg2, 0);
+
+ ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
+ }
+ break;
case TARGET_NR_sched_setparam:
{
struct sched_param *target_schp;