diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -12,7 +12,7 @@ LIB= util SHLIB_MAJOR= 9 -SRCS= _secure_path.c auth.c expand_number.c flopen.c fparseln.c \ +SRCS= _secure_path.c auth.c cpuset.c expand_number.c flopen.c fparseln.c \ getlocalbase.c gr_util.c \ hexdump.c humanize_number.c kinfo_getfile.c \ kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c \ @@ -31,7 +31,7 @@ CFLAGS+= -I${.CURDIR} -I${SRCTOP}/lib/libc/gen/ -MAN+= expand_number.3 flopen.3 fparseln.3 getlocalbase.3 hexdump.3 \ +MAN+= cpuset.3 expand_number.3 flopen.3 fparseln.3 getlocalbase.3 hexdump.3 \ humanize_number.3 kinfo_getallproc.3 kinfo_getfile.3 \ kinfo_getproc.3 kinfo_getvmmap.3 kinfo_getvmobject.3 kld.3 \ login_auth.3 login_cap.3 \ @@ -88,6 +88,7 @@ pw_util.3 pw_scan.3 \ pw_util.3 pw_tempname.3 \ pw_util.3 pw_tmp.3 +MLINKS+=cpuset.3 cpuset_parselist.3 HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/lib/libutil/cpuset.3 b/lib/libutil/cpuset.3 new file mode 100644 --- /dev/null +++ b/lib/libutil/cpuset.3 @@ -0,0 +1,80 @@ +.\" Copyright (c) 2017 Baptiste Daroussin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 31, 2017 +.Dt CPUSET 3 +.Os +.Sh NAME +.Nm cpuset_parselist +.Nd utility functions for +.Xr cpuset 2 +handling +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/cpuset.h +.In libutil.h +.Ft int +.Fn cpuset_parselist "const char *cpu-list" "cpuset_t *mask" +.Sh DESCRIPTION +The +.Fn cpuset_parselist +function parses a +.Va cpu-list +filling the +.Va mask . +.Pp +The +.Va cpu-list +may include numbers separated by '-' for ranges and commas separating individual +numbers. +A special list of +.Dq all +may be specified in which case the list includes all CPUs from the root set. +.Sh RETURN VALUES +Return values can be the following +.Bl -tag -width Er +.It Dv CPUSET_PARSE_OK +The parsing was successful +.It Dv CPUSET_PARSE_ERROR +The +.Va cpu-list +format is invalid +.It Dv CPUSET_PARSE_GETAFFINITY +The +.Xr cpuset_getaffinity 2 +call has failed +.It Dv CPUSET_PARSE_INVALID_CPU +The number of supported CPUs has been exceeded. +The maximum number being +.Va CPU_SETSIZE . +.El +.Sh SEE ALSO +.Xr cpuset 1 , +.Xr cpuset 2 , +.Xr cpuset 9 +.Sh AUTHORS +.An Jeffrey Roberson Aq Mt jeff@FreeBSD.org diff --git a/lib/libutil/cpuset.c b/lib/libutil/cpuset.c new file mode 100644 --- /dev/null +++ b/lib/libutil/cpuset.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2007, 2008 Jeffrey Roberson + * All rights reserved. + * + * Copyright (c) 2008 Nokia Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include + +int +cpuset_parselist(const char *list, cpuset_t *mask) +{ + enum { NONE, NUM, DASH } state; + int lastnum; + int curnum; + const char *l; + + if (strcasecmp(list, "all") == 0) { + if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1, + sizeof(*mask), mask) != 0) + return (CPUSET_PARSE_GETAFFINITY); + return (CPUSET_PARSE_OK); + } + state = NONE; + curnum = lastnum = 0; + for (l = list; *l != '\0';) { + if (isdigit(*l)) { + curnum = atoi(l); + if (curnum > CPU_SETSIZE) + return (CPUSET_PARSE_INVALID_CPU); + while (isdigit(*l)) + l++; + switch (state) { + case NONE: + lastnum = curnum; + state = NUM; + break; + case DASH: + for (; lastnum <= curnum; lastnum++) + CPU_SET(lastnum, mask); + state = NONE; + break; + case NUM: + default: + goto parserr; + } + continue; + } + switch (*l) { + case ',': + switch (state) { + case NONE: + break; + case NUM: + CPU_SET(curnum, mask); + state = NONE; + break; + case DASH: + goto parserr; + break; + } + break; + case '-': + if (state != NUM) + goto parserr; + state = DASH; + break; + default: + goto parserr; + } + l++; + } + switch (state) { + case NONE: + break; + case NUM: + CPU_SET(curnum, mask); + break; + case DASH: + goto parserr; + } + return (CPUSET_PARSE_OK); +parserr: + return (CPUSET_PARSE_ERROR); +} diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -210,6 +210,14 @@ int quota_write_usage(struct quotafile *_qf, struct dqblk *_dqb, int _id); #endif +#ifdef _SYS_CPUSET_H_ +int cpuset_parselist(const char *list, cpuset_t *mask); +#define CPUSET_PARSE_OK 0 +#define CPUSET_PARSE_GETAFFINITY -1 +#define CPUSET_PARSE_ERROR -2 +#define CPUSET_PARSE_INVALID_CPU -3 +#endif + __END_DECLS /* fparseln(3) */