Skip to contentSkip to conversation

2.5: (better) syscalls for setting task affinity

PATCH In review Robert Love 2 participants 3 messages Feb 27, 2002 – Feb 28, 2002

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 2.5: (better) syscalls for setting task affinity

[ This post adds length and pointer checks to the syscalls such that we can portably change the size of cpus_allowed. ]

The attached patch implements a syscall interface for setting and retrieving a task's CPU affinity (task->cpus_allowed):

int sched_set_affinity(pid_t pid, unsigned int len,
unsigned long *new_mask_ptr);

int sched_get_affinity(pid_t pid, unsigned int *user_len_ptr,
unsigned long *user_mask_ptr)

sched_set_affinity uses the set_cpus_allowed function in Ingo's new scheduler to do all the hard work. Additionally, this patch is based off Ingo's previous syscall affinity patch and my proc-based affinity patch. Much credit to Ingo for this past work and his current scheduler.

Security is enforced: calling user must match task's uid or euid or possess CAP_SYS_NICE.

We can safely change the size of cpus_allowed. One can use:

	sched_get_affinity(0, &len, NULL);

to get the size of cpus_allowed. The use of this interface, thus, should be portable as we scale cpus_allowed over sizeof(long).

I think exporting cpus_allowed as a bit mask is the proper user interface for CPU affinity. Certainly more complicated solutions exist, but this should get the job done. I have also updated my proc-based solution although Ingo and others have flamed^Wconvinced me a syscall-based interface is ideal. I agree, mostly on the basis that /proc may not be mounted but I have posted an updated proc-based solution anyhow for proper discussion.

Patch is against 2.5.6-pre1. Enjoy,

Robert Love

arch/i386/kernel/entry.S +2 -0
diff -urN linus/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
@@ -716,6 +716,8 @@
 	.long SYMBOL_NAME(sys_lremovexattr)
 	.long SYMBOL_NAME(sys_fremovexattr)
 	.long SYMBOL_NAME(sys_tkill)
+	.long SYMBOL_NAME(sys_sched_set_affinity)
+	.long SYMBOL_NAME(sys_sched_get_affinity)	/* 240 */
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long SYMBOL_NAME(sys_ni_syscall)
include/asm-i386/unistd.h +2 -0
diff -urN linus/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
@@ -243,6 +243,8 @@
 #define __NR_lremovexattr	236
 #define __NR_fremovexattr	237
 #define __NR_tkill		238
+#define __NR_sched_set_affinity 239
+#define __NR_sched_get_affinity 240
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
kernel/sched.c +93 -0

99 lines not on this page · raw message

#1 lore raw
Quoted 2 lines · Robert Love

The attached patch implements a syscall interface for setting and retrieving a task's CPU affinity (task->cpus_allowed):

I should posted a test program to demonstrate the syscalls - find such an attachment below. It demonstrates using sched_get_affinity to find the length of the cpu bitmask and then get and set a new value.

`pid_t p' is the process in question.
`unsigned long new_mask' is the new bitmask.

Robert Love

/*
* Example of sched_set_affinity and sched_get_affinity
* Robert Love, 20020227
*/

#include <stdio.h>
#include <stdlib.h>
#include <linux/unistd.h>
#include <unistd.h>

#define __NR_sched_set_affinity 239
#define __NR_sched_get_affinity 240

_syscall3 (int, sched_set_affinity, pid_t, pid, unsigned int, len, unsigned long *, new_mask_ptr) _syscall3 (int, sched_get_affinity, pid_t, pid, unsigned int *, user_len_ptr, unsigned long *, user_mask_ptr)

int main(int argc, char * argv[])

{
	unsigned long new_mask = 2;
	unsigned int len;
	unsigned long cur_mask;
	pid_t p = getpid();
	int ret;

	ret = sched_get_affinity(p, &len, NULL);
	printf(" len = %u\n", len);

	ret = sched_get_affinity(p, &len, &cur_mask);
	printf(" sched_get_affinity = %d, cur_mask = %ld\n", ret, cur_mask);

	ret = sched_set_affinity(p, len, &new_mask);
	printf(" sched_set_affinity = %d, new_mask = %ld\n", ret, new_mask);

	ret = sched_get_affinity(p, &len, &cur_mask);
	printf(" sched_get_affinity = %d, cur_mask = %ld\n", ret, cur_mask);

	return 0;
}
#2 lore raw
In reply to Robert Love
Quoted 2 lines · Robert Love

[ This post adds length and pointer checks to the syscalls such that we can portably change the size of cpus_allowed. ]

Great! That is what I was going to suggest to your first patch.

Signature · 1 line
Mike