taskset: support CPU masks for more than 64 CPUs
function old new delta taskset_main 522 631 +109 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		| @@ -342,7 +342,6 @@ IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP)) | ||||
| IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP)) | ||||
| IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac)) | ||||
| IF_TAIL(APPLET(tail, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||||
| IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||||
| /* IF_TC(APPLET(tc, BB_DIR_SBIN, BB_SUID_DROP)) */ | ||||
| IF_TCPSVD(APPLET_ODDNAME(tcpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, tcpsvd)) | ||||
| IF_TEE(APPLET(tee, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||||
|   | ||||
| @@ -499,22 +499,6 @@ config STRINGS | ||||
| 	  strings prints the printable character sequences for each file | ||||
| 	  specified. | ||||
|  | ||||
| config TASKSET | ||||
| 	bool "taskset" | ||||
| 	default n  # doesn't build on some non-x86 targets (m68k) | ||||
| 	help | ||||
| 	  Retrieve or set a processes's CPU affinity. | ||||
| 	  This requires sched_{g,s}etaffinity support in your libc. | ||||
|  | ||||
| config FEATURE_TASKSET_FANCY | ||||
| 	bool "Fancy output" | ||||
| 	default y | ||||
| 	depends on TASKSET | ||||
| 	help | ||||
| 	  Add code for fancy output. This merely silences a compiler-warning | ||||
| 	  and adds about 135 Bytes. May be needed for machines with alot | ||||
| 	  of CPUs. | ||||
|  | ||||
| config TIME | ||||
| 	bool "time" | ||||
| 	default y | ||||
|   | ||||
| @@ -39,7 +39,6 @@ lib-$(CONFIG_RUNLEVEL)    += runlevel.o | ||||
| lib-$(CONFIG_RX)          += rx.o | ||||
| lib-$(CONFIG_SETSID)      += setsid.o | ||||
| lib-$(CONFIG_STRINGS)     += strings.o | ||||
| lib-$(CONFIG_TASKSET)     += taskset.o | ||||
| lib-$(CONFIG_TIME)        += time.o | ||||
| lib-$(CONFIG_TIMEOUT)     += timeout.o | ||||
| lib-$(CONFIG_TTYSIZE)     += ttysize.o | ||||
|   | ||||
| @@ -6,6 +6,25 @@ | ||||
|  * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||||
|  */ | ||||
|  | ||||
| //config:config TASKSET | ||||
| //config:	bool "taskset" | ||||
| //config:	default n  # doesn't build on some non-x86 targets (m68k) | ||||
| //config:	help | ||||
| //config:	  Retrieve or set a processes's CPU affinity. | ||||
| //config:	  This requires sched_{g,s}etaffinity support in your libc. | ||||
| //config: | ||||
| //config:config FEATURE_TASKSET_FANCY | ||||
| //config:	bool "Fancy output" | ||||
| //config:	default y | ||||
| //config:	depends on TASKSET | ||||
| //config:	help | ||||
| //config:	  Add code for fancy output. This merely silences a compiler-warning | ||||
| //config:	  and adds about 135 Bytes. May be needed for machines with alot | ||||
| //config:	  of CPUs. | ||||
|  | ||||
| //applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||||
| //kbuild:lib-$(CONFIG_TASKSET) += taskset.o | ||||
|  | ||||
| //usage:#define taskset_trivial_usage | ||||
| //usage:       "[-p] [MASK] [PID | PROG ARGS]" | ||||
| //usage:#define taskset_full_usage "\n\n" | ||||
| @@ -22,6 +41,11 @@ | ||||
| //usage:       "pid 6671's new affinity mask: 1\n" | ||||
| //usage:       "$ taskset -p 1\n" | ||||
| //usage:       "pid 1's current affinity mask: 3\n" | ||||
| /* | ||||
|  Not yet implemented: | ||||
|  * -a/--all-tasks (affect all threads) | ||||
|  * -c/--cpu-list  (specify CPUs via "1,3,5-7") | ||||
|  */ | ||||
|  | ||||
| #include <sched.h> | ||||
| #include "libbb.h" | ||||
| @@ -128,17 +152,65 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) | ||||
| 		current_new += 8; /* "new" */ | ||||
| 	} | ||||
|  | ||||
| 	{ /* Affinity was specified, translate it into cpu_set_t */ | ||||
| 		unsigned i; | ||||
| 		/* Do not allow zero mask: */ | ||||
| 		unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); | ||||
| 		enum { CNT_BIT = CPU_SETSIZE < sizeof(m)*8 ? CPU_SETSIZE : sizeof(m)*8 }; | ||||
|  | ||||
| 	/* Affinity was specified, translate it into cpu_set_t */ | ||||
| 	CPU_ZERO(&mask); | ||||
| 		for (i = 0; i < CNT_BIT; i++) { | ||||
| 			unsigned long long bit = (1ULL << i); | ||||
| 			if (bit & m) | ||||
| 	if (!ENABLE_FEATURE_TASKSET_FANCY) { | ||||
| 		unsigned i; | ||||
| 		unsigned long long m; | ||||
|  | ||||
| 		/* Do not allow zero mask: */ | ||||
| 		m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); | ||||
| 		i = 0; | ||||
| 		do { | ||||
| 			if (m & 1) | ||||
| 				CPU_SET(i, &mask); | ||||
| 			i++; | ||||
| 			m >>= 1; | ||||
| 		} while (m != 0); | ||||
| 	} else { | ||||
| 		unsigned i; | ||||
| 		char *last_byte; | ||||
| 		char *bin; | ||||
| 		uint8_t bit_in_byte; | ||||
|  | ||||
| 		/* Cheap way to get "long enough" buffer */ | ||||
| 		bin = xstrdup(aff); | ||||
|  | ||||
| 		if (aff[0] != '0' && (aff[1]|0x20) != 'x') { | ||||
| /* TODO: decimal/octal masks are still limited to 2^64 */ | ||||
| 			unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); | ||||
| 			bin += strlen(bin); | ||||
| 			last_byte = bin - 1; | ||||
| 			while (m) { | ||||
| 				*--bin = m & 0xff; | ||||
| 				m >>= 8; | ||||
| 			} | ||||
| 		} else { | ||||
| 			/* aff is "0x.....", we accept very long masks in this form */ | ||||
| 			last_byte = hex2bin(bin, aff + 2, INT_MAX); | ||||
| 			if (!last_byte) { | ||||
|  bad_aff: | ||||
| 				bb_error_msg_and_die("bad affinity '%s'", aff); | ||||
| 			} | ||||
| 			last_byte--; /* now points to the last byte */ | ||||
| 		} | ||||
|  | ||||
| 		i = 0; | ||||
| 		bit_in_byte = 1; | ||||
| 		while (last_byte >= bin) { | ||||
| 			if (bit_in_byte & *last_byte) { | ||||
| 				if (i >= CPU_SETSIZE) | ||||
| 					goto bad_aff; | ||||
| 				CPU_SET(i, &mask); | ||||
| 				//bb_error_msg("bit %d set", i); | ||||
| 			} | ||||
| 			i++; | ||||
| 			/* bit_in_byte is uint8_t! & 0xff is implied */ | ||||
| 			bit_in_byte = (bit_in_byte << 1); | ||||
| 			if (!bit_in_byte) { | ||||
| 				bit_in_byte = 1; | ||||
| 				last_byte--; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user