diff options
Diffstat (limited to 'schedutils')
-rw-r--r-- | schedutils/Makefile.am | 8 | ||||
-rw-r--r-- | schedutils/Makefile.in | 609 | ||||
-rw-r--r-- | schedutils/chrt.1 | 103 | ||||
-rw-r--r-- | schedutils/chrt.c | 223 | ||||
-rw-r--r-- | schedutils/ionice.1 | 71 | ||||
-rw-r--r-- | schedutils/ionice.c | 143 | ||||
-rw-r--r-- | schedutils/taskset.1 | 115 | ||||
-rw-r--r-- | schedutils/taskset.c | 334 |
8 files changed, 1606 insertions, 0 deletions
diff --git a/schedutils/Makefile.am b/schedutils/Makefile.am new file mode 100644 index 00000000..33235f2f --- /dev/null +++ b/schedutils/Makefile.am @@ -0,0 +1,8 @@ +include $(top_srcdir)/config/include-Makefile.am + +if BUILD_SCHEDUTILS + +usrbin_PROGRAMS = chrt ionice taskset +man_MANS = chrt.1 ionice.1 taskset.1 + +endif diff --git a/schedutils/Makefile.in b/schedutils/Makefile.in new file mode 100644 index 00000000..8d6d468d --- /dev/null +++ b/schedutils/Makefile.in @@ -0,0 +1,609 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/config/include-Makefile.am +@BUILD_SCHEDUTILS_TRUE@usrbin_PROGRAMS = chrt$(EXEEXT) ionice$(EXEEXT) \ +@BUILD_SCHEDUTILS_TRUE@ taskset$(EXEEXT) +subdir = schedutils +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(usrbindir)" "$(DESTDIR)$(man1dir)" +usrbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(usrbin_PROGRAMS) +chrt_SOURCES = chrt.c +chrt_OBJECTS = chrt.$(OBJEXT) +chrt_LDADD = $(LDADD) +ionice_SOURCES = ionice.c +ionice_OBJECTS = ionice.$(OBJEXT) +ionice_LDADD = $(LDADD) +taskset_SOURCES = taskset.c +taskset_OBJECTS = taskset.$(OBJEXT) +taskset_LDADD = $(LDADD) +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = chrt.c ionice.c taskset.c +DIST_SOURCES = chrt.c ionice.c taskset.c +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_AGETTY_FALSE = @BUILD_AGETTY_FALSE@ +BUILD_AGETTY_TRUE = @BUILD_AGETTY_TRUE@ +BUILD_ELVTUNE_FALSE = @BUILD_ELVTUNE_FALSE@ +BUILD_ELVTUNE_TRUE = @BUILD_ELVTUNE_TRUE@ +BUILD_INIT_FALSE = @BUILD_INIT_FALSE@ +BUILD_INIT_TRUE = @BUILD_INIT_TRUE@ +BUILD_KILL_FALSE = @BUILD_KILL_FALSE@ +BUILD_KILL_TRUE = @BUILD_KILL_TRUE@ +BUILD_LAST_FALSE = @BUILD_LAST_FALSE@ +BUILD_LAST_TRUE = @BUILD_LAST_TRUE@ +BUILD_LOGIN_UTILS_FALSE = @BUILD_LOGIN_UTILS_FALSE@ +BUILD_LOGIN_UTILS_TRUE = @BUILD_LOGIN_UTILS_TRUE@ +BUILD_MESG_FALSE = @BUILD_MESG_FALSE@ +BUILD_MESG_TRUE = @BUILD_MESG_TRUE@ +BUILD_PARTX_FALSE = @BUILD_PARTX_FALSE@ +BUILD_PARTX_TRUE = @BUILD_PARTX_TRUE@ +BUILD_RAW_FALSE = @BUILD_RAW_FALSE@ +BUILD_RAW_TRUE = @BUILD_RAW_TRUE@ +BUILD_RDEV_FALSE = @BUILD_RDEV_FALSE@ +BUILD_RDEV_TRUE = @BUILD_RDEV_TRUE@ +BUILD_RENAME_FALSE = @BUILD_RENAME_FALSE@ +BUILD_RENAME_TRUE = @BUILD_RENAME_TRUE@ +BUILD_RESET_FALSE = @BUILD_RESET_FALSE@ +BUILD_RESET_TRUE = @BUILD_RESET_TRUE@ +BUILD_SCHEDUTILS_FALSE = @BUILD_SCHEDUTILS_FALSE@ +BUILD_SCHEDUTILS_TRUE = @BUILD_SCHEDUTILS_TRUE@ +BUILD_WALL_FALSE = @BUILD_WALL_FALSE@ +BUILD_WALL_TRUE = @BUILD_WALL_TRUE@ +BUILD_WRITE_FALSE = @BUILD_WRITE_FALSE@ +BUILD_WRITE_TRUE = @BUILD_WRITE_TRUE@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GMSGFMT = @GMSGFMT@ +HAVE_BLKID_FALSE = @HAVE_BLKID_FALSE@ +HAVE_BLKID_TRUE = @HAVE_BLKID_TRUE@ +HAVE_LIBUTIL_FALSE = @HAVE_LIBUTIL_FALSE@ +HAVE_LIBUTIL_TRUE = @HAVE_LIBUTIL_TRUE@ +HAVE_NCURSES_FALSE = @HAVE_NCURSES_FALSE@ +HAVE_NCURSES_TRUE = @HAVE_NCURSES_TRUE@ +HAVE_PAM_FALSE = @HAVE_PAM_FALSE@ +HAVE_PAM_TRUE = @HAVE_PAM_TRUE@ +HAVE_PIVOT_ROOT_FALSE = @HAVE_PIVOT_ROOT_FALSE@ +HAVE_PIVOT_ROOT_TRUE = @HAVE_PIVOT_ROOT_TRUE@ +HAVE_RAW_FALSE = @HAVE_RAW_FALSE@ +HAVE_RAW_TRUE = @HAVE_RAW_TRUE@ +HAVE_SELINUX_FALSE = @HAVE_SELINUX_FALSE@ +HAVE_SELINUX_TRUE = @HAVE_SELINUX_TRUE@ +HAVE_TERMCAP_FALSE = @HAVE_TERMCAP_FALSE@ +HAVE_TERMCAP_TRUE = @HAVE_TERMCAP_TRUE@ +HAVE_UUID_FALSE = @HAVE_UUID_FALSE@ +HAVE_UUID_TRUE = @HAVE_UUID_TRUE@ +HAVE_ZLIB_FALSE = @HAVE_ZLIB_FALSE@ +HAVE_ZLIB_TRUE = @HAVE_ZLIB_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTEL_FALSE = @INTEL_FALSE@ +INTEL_TRUE = @INTEL_TRUE@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NEED_LIBCRYPT_FALSE = @NEED_LIBCRYPT_FALSE@ +NEED_LIBCRYPT_TRUE = @NEED_LIBCRYPT_TRUE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPARC_FALSE = @SPARC_FALSE@ +SPARC_TRUE = @SPARC_TRUE@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +USE_SLANG_FALSE = @USE_SLANG_FALSE@ +USE_SLANG_TRUE = @USE_SLANG_TRUE@ +USE_TTY_GROUP_FALSE = @USE_TTY_GROUP_FALSE@ +USE_TTY_GROUP_TRUE = @USE_TTY_GROUP_TRUE@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = $(prefix)/usr/share +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = $(datadir)/info +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = $(datadir)/man +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +usrbindir = $(prefix)/usr/bin +usrsbindir = $(prefix)/usr/sbin +AM_CPPFLAGS = -include ../config.h -I$(top_srcdir)/include +DEFAULT_INCLUDES = +@BUILD_SCHEDUTILS_TRUE@man_MANS = chrt.1 ionice.1 taskset.1 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/config/include-Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign schedutils/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign schedutils/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-usrbinPROGRAMS: $(usrbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(usrbindir)" || $(mkdir_p) "$(DESTDIR)$(usrbindir)" + @list='$(usrbin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(usrbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(usrbindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(usrbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(usrbindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-usrbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(usrbin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(usrbindir)/$$f'"; \ + rm -f "$(DESTDIR)$(usrbindir)/$$f"; \ + done + +clean-usrbinPROGRAMS: + @list='$(usrbin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done + +installcheck-usrbinPROGRAMS: $(usrbin_PROGRAMS) + bad=0; pid=$$$$; list="$(usrbin_PROGRAMS)"; for p in $$list; do \ + case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ + *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ + esac; \ + f=`echo "$$p" | \ + sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + for opt in --help --version; do \ + if "$(DESTDIR)$(usrbindir)/$$f" $$opt >c$${pid}_.out \ + 2>c$${pid}_.err </dev/null \ + && test -n "`cat c$${pid}_.out`" \ + && test -z "`cat c$${pid}_.err`"; then :; \ + else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \ + done; \ + done; rm -f c$${pid}_.???; exit $$bad +chrt$(EXEEXT): $(chrt_OBJECTS) $(chrt_DEPENDENCIES) + @rm -f chrt$(EXEEXT) + $(LINK) $(chrt_LDFLAGS) $(chrt_OBJECTS) $(chrt_LDADD) $(LIBS) +ionice$(EXEEXT): $(ionice_OBJECTS) $(ionice_DEPENDENCIES) + @rm -f ionice$(EXEEXT) + $(LINK) $(ionice_LDFLAGS) $(ionice_OBJECTS) $(ionice_LDADD) $(LIBS) +taskset$(EXEEXT): $(taskset_OBJECTS) $(taskset_DEPENDENCIES) + @rm -f taskset$(EXEEXT) + $(LINK) $(taskset_LDFLAGS) $(taskset_OBJECTS) $(taskset_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chrt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ionice.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/taskset.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(mkdir_p) $(distdir)/../config + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(usrbindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-usrbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-man install-usrbinPROGRAMS + +install-exec-am: + +install-info: install-info-am + +install-man: install-man1 + +installcheck-am: installcheck-usrbinPROGRAMS + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-man uninstall-usrbinPROGRAMS + +uninstall-man: uninstall-man1 + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-usrbinPROGRAMS ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-man1 install-strip install-usrbinPROGRAMS installcheck \ + installcheck-am installcheck-usrbinPROGRAMS installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-info-am uninstall-man uninstall-man1 \ + uninstall-usrbinPROGRAMS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/schedutils/chrt.1 b/schedutils/chrt.1 new file mode 100644 index 00000000..57e046ea --- /dev/null +++ b/schedutils/chrt.1 @@ -0,0 +1,103 @@ +.\" chrt(1) manpage +.\" +.\" Copyright (C) 2004 Robert Love +.\" +.\" This is free documentation; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2 of +.\" the License. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with this manual; if not, write to the Free +.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, +.\" USA. +.\" +.\" 2002-05-11 Robert Love <rml@tech9.net> +.\" Initial version +.\" +.TH CHRT "1" "Apr 2003" "schedutils" "Linux User's Manual" +.SH NAME +chrt \- manipulate real-time attributes of a process +.SH SYNOPSIS +.B chrt +[\fIoptions\fR] [\fIprio\fR] [\fIpid\fR | \fIcommand\fR [\fIarg\fR]...] +.SH DESCRIPTION +.PP +.BR chrt (1) +sets or retrieves the real-time scheduling attributes of an existing PID or +runs COMMAND with the given attributes. Both policy (one of +.BR SCHED_FIFO , +.BR SCHED_RR , +or +.BR SCHED_OTHER ) +and priority can be set and retrieved. +.SH OPTIONS +.TP +.B -p, --pid +operate on an existing PID and do not launch a new task +.TP + +.TP +.B -f, --fifo +set scheduling policy to +.BR SCHED_FIFO +.TP +.B -m, --max +show minimum and maximum valid priorities, then exit +.TP +.B -o, --other +set policy scheduling policy to +.BR SCHED_OTHER +.TP +.B -r, --rr +set scheduling policy to +.BR SCHED_RR +(the default) +.TP +.B -h, --help +display usage information and exit +.TP +.B -v, --version +output version information and exit +.SH USAGE +.TP +The default behavior is to run a new command:: +chrt [prio] -- [command] [arguments] +.TP +You can also retrieve the real-time attributes of an existing task: +chrt -p [pid] +.TP +Or set them: +chrt -p [prio] [pid] +.SH PERMISSIONS +A user must possess +.BR CAP_SYS_NICE +to change the scheduling attributes of a process. Any user can retrieve the +scheduling information. +.SH AUTHOR +Written by Robert M. Love. +.SH "REPORTING BUGS" +Report bugs to <rml@tech9.net>. +.SH COPYRIGHT +Copyright \(co 2004 Robert M. Love +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +.SH "SEE ALSO" +.BR taskset (1), +.BR nice (1), +.BR renice (1) +.sp +See +.BR sched_setscheduler (2) +for a description of the Linux scheduling scheme. diff --git a/schedutils/chrt.c b/schedutils/chrt.c new file mode 100644 index 00000000..b61ed52a --- /dev/null +++ b/schedutils/chrt.c @@ -0,0 +1,223 @@ +/* + * chrt.c - chrt + * Command-line utility for manipulating a task's real-time attributes + * + * Robert Love <rml@tech9.net> + * 27-Apr-2002: initial version + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, v2, as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Copyright (C) 2004 Robert Love + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <sched.h> +#include <unistd.h> +#include <getopt.h> +#include <errno.h> + +static void show_usage(const char *cmd) +{ + fprintf(stderr, "chrt version " VERSION "\n"); + fprintf(stderr, "usage: %s [options] [prio] [pid | cmd [args...]]\n", + cmd); + fprintf(stderr, "manipulate real-time attributes of a process\n"); + fprintf(stderr, " -f, --fifo " + "set policy to SCHED_FF\n"); + fprintf(stderr, " -p, --pid " + "operate on existing given pid\n"); + fprintf(stderr, " -m, --max " + "show min and max valid priorities\n"); + fprintf(stderr, " -o, --other " + "set policy to SCHED_OTHER\n"); + fprintf(stderr, " -r, --rr " + "set policy to SCHED_RR (default)\n"); + fprintf(stderr, " -h, --help " + "display this help\n"); + fprintf(stderr, " -v, --verbose " + "display status information\n"); + fprintf(stderr, " -V, --version " + "output version information\n\n"); + fprintf(stderr, "You must give a priority if changing policy.\n\n"); + fprintf(stderr, "Report bugs and send patches to <rml@tech9.net>\n"); +} + +static void show_rt_info(const char *what, pid_t pid) +{ + struct sched_param sp; + int policy; + + /* don't display "pid 0" as that is confusing */ + if (!pid) + pid = getpid(); + + policy = sched_getscheduler(pid); + if (policy == -1) { + perror("sched_getscheduler"); + fprintf(stderr, "failed to get pid %d's policy\n", pid); + exit(1); + } + + printf("pid %d's %s scheduling policy: ", pid, what); + switch (policy) { + case SCHED_OTHER: + printf("SCHED_OTHER\n"); + break; + case SCHED_FIFO: + printf("SCHED_FIFO\n"); + break; + case SCHED_RR: + printf("SCHED_RR\n"); + break; + default: + printf("unknown\n"); + } + + if (sched_getparam(pid, &sp)) { + perror("sched_getparam"); + fprintf(stderr, "failed to get pid %d's attributes\n", pid); + exit(1); + } + + printf("pid %d's %s scheduling priority: %d\n", + pid, what, sp.sched_priority); +} + +static void show_min_max(void) +{ + int max, min; + + max = sched_get_priority_max(SCHED_FIFO); + min = sched_get_priority_min(SCHED_FIFO); + if (max >= 0 && min >= 0) + printf("SCHED_FIFO min/max priority\t: %d/%d\n", min, max); + else + printf("SCHED_FIFO not supported?\n"); + + max = sched_get_priority_max(SCHED_RR); + min = sched_get_priority_min(SCHED_RR); + if (max >= 0 && min >= 0) + printf("SCHED_RR min/max priority\t: %d/%d\n", min, max); + else + printf("SCHED_RR not supported?\n"); + + max = sched_get_priority_max(SCHED_OTHER); + min = sched_get_priority_min(SCHED_OTHER); + if (max >= 0 && min >= 0) + printf("SCHED_OTHER min/max priority\t: %d/%d\n", min, max); + else + printf("SCHED_OTHER not supported?\n"); +} + +int main(int argc, char *argv[]) +{ + int i, policy = SCHED_RR, priority = 0, verbose = 0; + struct sched_param sp; + pid_t pid = 0; + + struct option longopts[] = { + { "fifo", 0, NULL, 'f' }, + { "pid", 0, NULL, 'p' }, + { "help", 0, NULL, 'h' }, + { "max", 0, NULL, 'm' }, + { "other", 0, NULL, 'o' }, + { "rr", 0, NULL, 'r' }, + { "verbose", 0, NULL, 'v' }, + { "version", 0, NULL, 'V' }, + { NULL, 0, NULL, 0 } + }; + + while((i = getopt_long(argc, argv, "+fphmorvV", longopts, NULL)) != -1) + { + int ret = 1; + + switch (i) { + case 'f': + policy = SCHED_FIFO; + break; + case 'm': + show_min_max(); + return 0; + case 'o': + policy = SCHED_OTHER; + break; + case 'p': + errno = 0; + pid = strtol(argv[argc - 1], NULL, 10); + if (errno) { + perror("strtol"); + fprintf(stderr, "failed to parse pid!\n"); + return 1; + } + break; + case 'r': + policy = SCHED_RR; + break; + case 'v': + verbose = 1; + break; + case 'V': + printf("chrt version " VERSION "\n"); + return 0; + case 'h': + ret = 0; + default: + show_usage(argv[0]); + return ret; + } + + } + + if ((pid && argc - optind < 1) || (!pid && argc - optind < 2)) { + show_usage(argv[0]); + return 1; + } + + if (pid && (verbose || argc - optind == 1)) { + show_rt_info("current", pid); + if (argc - optind == 1) + return 0; + } + + errno = 0; + priority = strtol(argv[optind], NULL, 10); + if (errno) { + perror("strtol"); + fprintf(stderr, "failed to parse priority!\n"); + return 1; + } + + sp.sched_priority = priority; + if (sched_setscheduler(pid, policy, &sp) == -1) { + perror("sched_setscheduler"); + fprintf(stderr, "failed to set pid %d's policy\n", pid); + return 1; + } + + if (verbose) + show_rt_info("new", pid); + + if (!pid) { + argv += optind + 1; + execvp(argv[0], argv); + perror("execvp"); + fprintf(stderr, "failed to execute %s\n", argv[0]); + return 1; + } + + return 0; +} diff --git a/schedutils/ionice.1 b/schedutils/ionice.1 new file mode 100644 index 00000000..b0c68c93 --- /dev/null +++ b/schedutils/ionice.1 @@ -0,0 +1,71 @@ +.TH ionice "1" "August 2005" ionice +.SH NAME +ionice \- get/set program io scheduling class and priority +.SH SYNOPSIS +.B ionice +[\fI-c\fR] \fI[-n\fR] [\fI-p\fR] [COMMAND [ARG...]] + +.SH DESCRIPTION +This program sets the io scheduling class and priority for a program. As of +this writing, Linux supports 3 scheduling classes: + +\fBIdle\fR. +A program running with idle io priority will only get disk time when no other +program has asked for disk io for a defined grace period. The impact of idle +io processes on normal system activity should be zero. This scheduling +class does not take a priority argument. + +\fBBest effort\fR. +This is the default scheduling class for any process that hasn't asked for +a specific io priority. Programs inherit the CPU nice setting for io +priorities. This class takes a priority argument from \fI0-7\fR, with lower +number being higher priority. Programs running at the same best effort +priority are served in a round-robin fashion. + +\fBReal time\fR. +The RT scheduling class is given first access to the disk, regardless of +what else is going on in the system. Thus the RT class needs to be used with +some care, as it can starve other processes. As with the best effort class, +8 priority levels are defined denoting how big a time slice a given process +will receive on each scheduling window. + +If no arguments or just \fI-p\fR is given, \fIionice\fR will query the +current io scheduling class and priority for that process. + +.SH OPTIONS +.LP +.TP 7 +\fB-c\fP +The scheduling class. 1 for real time, 2 for best-effort, 3 for idle. +.TP 7 +\fB-n\fP +The scheduling class data. This defines the class data, if the class +accepts an argument. For real time and best-effort, \fI0-7\fR is valid +data. +.TP 7 +\fB-p\fP +Pass in a process pid to change an already running process. If this argument +is not given, \fBionice\fP will run the listed program with the given +parameters. + +.SH EXAMPLES +.LP +.TP 7 +# \fBionice\fP -c3 -p89 +.TP 7 +Sets process with PID 89 as an idle io process. +.TP 7 +# \fBionice\fP -c2 -n0 bash +.TP 7 +Runs 'bash' as a best-effort program with highest priority. +.TP 7 +# \fBionice\fP -p89 +.TP 7 +Returns the class and priority of the process with PID 89. + +.SH NOTES +Linux supports io scheduling priorities and classes since 2.6.13 with the CFQ +io scheduler. + +.SH AUTHORS +Jens Axboe <axboe@suse.de> diff --git a/schedutils/ionice.c b/schedutils/ionice.c new file mode 100644 index 00000000..b3b3383a --- /dev/null +++ b/schedutils/ionice.c @@ -0,0 +1,143 @@ +/* + * ionice: set or get process io scheduling class and priority + * + * Copyright (C) 2005 Jens Axboe <axboe@suse.de> SUSE Labs + * + * Released under the terms of the GNU General Public License version 2 + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <getopt.h> +#include <unistd.h> +#include <sys/ptrace.h> +#include <sys/syscall.h> +#include <asm/unistd.h> + +#if defined(__i386__) +#define __NR_ioprio_set 289 +#define __NR_ioprio_get 290 +#elif defined(__powerpc__) || defined(__powerpc64__) +#define __NR_ioprio_set 273 +#define __NR_ioprio_get 274 +#elif defined(__x86_64__) +#define __NR_ioprio_set 251 +#define __NR_ioprio_get 252 +#elif defined(__ia64__) +#define __NR_ioprio_set 1274 +#define __NR_ioprio_get 1275 +#elif defined(__alpha__) +#define __NR_ioprio_set 442 +#define __NR_ioprio_get 443 +#elif defined(__s390x__) || defined(__s390__) +#define __NR_ioprio_set 282 +#define __NR_ioprio_get 283 +#else +#error "Unsupported arch" +#endif + +static inline int ioprio_set(int which, int who, int ioprio) +{ + return syscall(__NR_ioprio_set, which, who, ioprio); +} + +static inline int ioprio_get(int which, int who) +{ + return syscall(__NR_ioprio_get, which, who); +} + +enum { + IOPRIO_CLASS_NONE, + IOPRIO_CLASS_RT, + IOPRIO_CLASS_BE, + IOPRIO_CLASS_IDLE, +}; + +enum { + IOPRIO_WHO_PROCESS = 1, + IOPRIO_WHO_PGRP, + IOPRIO_WHO_USER, +}; + +#define IOPRIO_CLASS_SHIFT 13 + +const char *to_prio[] = { "none", "realtime", "best-effort", "idle", }; + +static void usage(void) +{ + printf("Usage: ionice [OPTIONS] [COMMAND [ARG]...]\n"); + printf("Sets or gets process io scheduling class and priority.\n"); + printf("\n\t-n\tClass data (typically 0-7, lower being higher prio)\n"); + printf("\t-c\tScheduling class\n"); + printf("\t\t\t1: realtime, 2: best-effort, 3: idle\n"); + printf("\t-p\tProcess pid\n"); + printf("\t-h\tThis help page\n"); + printf("\nJens Axboe <axboe@suse.de> (C) 2005\n"); +} + +int main(int argc, char *argv[]) +{ + int ioprio = 4, set = 0, ioprio_class = IOPRIO_CLASS_BE; + int c, pid = 0; + + while ((c = getopt(argc, argv, "+n:c:p:h")) != EOF) { + switch (c) { + case 'n': + ioprio = strtol(optarg, NULL, 10); + set = 1; + break; + case 'c': + ioprio_class = strtol(optarg, NULL, 10); + set = 1; + break; + case 'p': + pid = strtol(optarg, NULL, 10); + break; + case 'h': + default: + usage(); + exit(0); + } + } + + switch (ioprio_class) { + case IOPRIO_CLASS_NONE: + ioprio_class = IOPRIO_CLASS_BE; + break; + case IOPRIO_CLASS_RT: + case IOPRIO_CLASS_BE: + break; + case IOPRIO_CLASS_IDLE: + ioprio = 7; + break; + default: + printf("bad prio class %d\n", ioprio_class); + return 1; + } + + if (!set) { + if (!pid && argv[optind]) + pid = strtol(argv[optind], NULL, 10); + + ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); + + if (ioprio == -1) + perror("ioprio_get"); + else { + ioprio_class = ioprio >> IOPRIO_CLASS_SHIFT; + ioprio = ioprio & 0xff; + printf("%s: prio %d\n", to_prio[ioprio_class], ioprio); + } + } else { + if (ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio | ioprio_class << IOPRIO_CLASS_SHIFT) == -1) { + perror("ioprio_set"); + return 1; + } + + if (argv[optind]) + execvp(argv[optind], &argv[optind]); + } + + return 0; +} diff --git a/schedutils/taskset.1 b/schedutils/taskset.1 new file mode 100644 index 00000000..5847a189 --- /dev/null +++ b/schedutils/taskset.1 @@ -0,0 +1,115 @@ +.\" taskset(1) manpage +.\" +.\" Copyright (C) 2004 Robert Love +.\" +.\" This is free documentation; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2 of +.\" the License. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with this manual; if not, write to the Free +.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, +.\" USA. +.\" +.\" 2002-05-11 Robert Love <rml@tech9.net> +.\" Initial version +.\" +.TH TASKSET "1" "Apr 2003" "schedutils" "Linux User's Manual" +.SH NAME +taskset \- retrieve or set a processes's CPU affinity +.SH SYNOPSIS +.B taskset +[\fIoptions\fR] [\fImask\fR | \fIlist\fI ] [\fIpid\fR | \fIcommand\fR [\fIarg\fR]...] +.SH DESCRIPTION +.PP +.BR taskset +is used to set or retrieve the CPU affinity of a running process given its PID +or to launch a new COMMAND with a given CPU affinity. CPU affinity is a +scheduler property that "bonds" a process to a given set of CPUs on the system. +The Linux scheduler will honor the given CPU affinity and the process will not +run on any other CPUs. Note that the Linux scheduler also supports natural +CPU affinity: the scheduler attempts to keep processes on the same CPU as long +as practical for performance reasons. Therefore, forcing a specific CPU +affinity is useful only in certain applications. +.sp +The CPU affinity is represented as a bitmask, with the lowest order bit +corresponding to the first logical CPU and the highest order bit corresponding +to the last logical CPU. Not all CPUs may exist on a given system but a mask +may specify more CPUs than are present. A retrieved mask will reflect only the +bits that correspond to CPUs physically on the system. If an invalid mask is +given (i.e., one that corresponds to no valid CPUs on the current system) an +error is returned. The masks are typically given in hexadecimal. For example, +.TP +.BR 0x00000001 +is processor #0 +.TP +.BR 0x00000003 +is processors #0 and #1 +.TP +.BR 0xFFFFFFFF +is all processors (#0 through #31) +.PP +When +.BR taskset +returns, it is guaranteed that the given program has been scheduled to a legal +CPU. +.SH OPTIONS +.TP +.B -p, --pid +operate on an existing PID and not launch a new task +.TP +.B -c, --cpu-list +specifiy a numerical list of processors instead of a bitmask. The list may +contain multiple items, separated by comma, and ranges. For example, +.BR 0,5,7,9-11 . +.TP +.B -h, --help +display usage information and exit +.TP +.B -V, --version +output version information and exit +.SH USAGE +.TP +The default behavior is to run a new command with a given affinity mask: +taskset [mask] -- [command] [arguments] +.TP +You can also retrieve the CPU affinity of an existing task: +taskset -p [pid] +.TP +Or set it: +taskset -p [mask] [pid] +.SH PERMISSIONS +A user must possess +.BR CAP_SYS_NICE +to change the CPU affinity of a process. Any user can retrieve the affinity +mask. +.SH AUTHOR +Written by Robert M. Love. +.SH "REPORTING BUGS" +Report bugs to <rml@tech9.net>. +.SH COPYRIGHT +Copyright \(co 2004 Robert M. Love +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +.SH "SEE ALSO" +.BR chrt (1), +.BR nice (1), +.BR renice (1), +.BR sched_setaffinity (2), +.BR sched_getaffinity (2) +.sp +See +.BR sched_setscheduler (2) +for a description of the Linux scheduling scheme. diff --git a/schedutils/taskset.c b/schedutils/taskset.c new file mode 100644 index 00000000..5932620e --- /dev/null +++ b/schedutils/taskset.c @@ -0,0 +1,334 @@ +/* + * taskset.c - taskset + * Command-line utility for setting and retrieving a task's CPU affinity + * + * Robert Love <rml@tech9.net> 25 April 2002 + * + * Linux kernels as of 2.5.8 provide the needed syscalls for + * working with a task's cpu affinity. Currently 2.4 does not + * support these syscalls, but patches are available at: + * + * http://www.kernel.org/pub/linux/kernel/people/rml/cpu-affinity/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, v2, as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Copyright (C) 2004 Robert Love + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <getopt.h> +#include <sched.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> + +static void show_usage(const char *cmd) +{ + fprintf(stderr, "taskset version " VERSION "\n"); + fprintf(stderr, "usage: %s [options] [mask | cpu-list] [pid |"\ + " cmd [args...]]\n", cmd); + fprintf(stderr, "set or get the affinity of a process\n\n"); + fprintf(stderr, " -p, --pid " + "operate on existing given pid\n"); + fprintf(stderr, " -c, --cpu-list "\ + "display and specify cpus in list format\n"); + fprintf(stderr, " -h, --help display this help\n"); + fprintf(stderr, " -v, --version "\ + "output version information\n\n"); + fprintf(stderr, "The default behavior is to run a new command:\n"); + fprintf(stderr, " %s 03 sshd -b 1024\n", cmd); + fprintf(stderr, "You can retrieve the mask of an existing task:\n"); + fprintf(stderr, " %s -p 700\n", cmd); + fprintf(stderr, "Or set it:\n"); + fprintf(stderr, " %s -p 03 700\n", cmd); + fprintf(stderr, "List format uses a comma-separated list instead"\ + " of a mask:\n"); + fprintf(stderr, " %s -pc 0,3,7-11 700\n", cmd); + fprintf(stderr, "Ranges in list format can take a stride argument:\n"); + fprintf(stderr, " e.g. 0-31:2 is equivalent to mask 0x55555555\n\n"); +} + +static inline int val_to_char(int v) +{ + if (v >= 0 && v < 10) + return '0' + v; + else if (v >= 10 && v < 16) + return ('a' - 10) + v; + else + return -1; +} + +static char * cpuset_to_str(cpu_set_t *mask, char *str) +{ + int base; + char *ptr = str; + char *ret = 0; + + for (base = CPU_SETSIZE - 4; base >= 0; base -= 4) { + char val = 0; + if (CPU_ISSET(base, mask)) + val |= 1; + if (CPU_ISSET(base + 1, mask)) + val |= 2; + if (CPU_ISSET(base + 2, mask)) + val |= 4; + if (CPU_ISSET(base + 3, mask)) + val |= 8; + if (!ret && val) + ret = ptr; + *ptr++ = val_to_char(val); + } + *ptr = 0; + return ret ? ret : ptr - 1; +} + +static char * cpuset_to_cstr(cpu_set_t *mask, char *str) +{ + int i; + char *ptr = str; + int entry_made = 0; + + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, mask)) { + int j; + int run = 0; + entry_made = 1; + for (j = i + 1; j < CPU_SETSIZE; j++) { + if (CPU_ISSET(j, mask)) + run++; + else + break; + } + if (!run) + sprintf(ptr, "%d,", i); + else if (run == 1) { + sprintf(ptr, "%d,%d,", i, i + 1); + i++; + } else { + sprintf(ptr, "%d-%d,", i, i + run); + i += run; + } + while (*ptr != 0) + ptr++; + } + } + ptr -= entry_made; + *ptr = 0; + + return str; +} + +static inline int char_to_val(int c) +{ + int cl; + + cl = tolower(c); + if (c >= '0' && c <= '9') + return c - '0'; + else if (cl >= 'a' && cl <= 'f') + return cl + (10 - 'a'); + else + return -1; +} + +static int str_to_cpuset(cpu_set_t *mask, const char* str) +{ + int len = strlen(str); + const char *ptr = str + len - 1; + int base = 0; + + /* skip 0x, it's all hex anyway */ + if (len > 1 && !memcmp(str, "0x", 2L)) + str += 2; + + CPU_ZERO(mask); + while (ptr >= str) { + char val = char_to_val(*ptr); + if (val == (char) -1) + return -1; + if (val & 1) + CPU_SET(base, mask); + if (val & 2) + CPU_SET(base + 1, mask); + if (val & 4) + CPU_SET(base + 2, mask); + if (val & 8) + CPU_SET(base + 3, mask); + len--; + ptr--; + base += 4; + } + + return 0; +} + +static const char *nexttoken(const char *q, int sep) +{ + if (q) + q = strchr(q, sep); + if (q) + q++; + return q; +} + +static int cstr_to_cpuset(cpu_set_t *mask, const char* str) +{ + const char *p, *q; + q = str; + CPU_ZERO(mask); + + while (p = q, q = nexttoken(q, ','), p) { + unsigned int a; /* beginning of range */ + unsigned int b; /* end of range */ + unsigned int s; /* stride */ + const char *c1, *c2; + + if (sscanf(p, "%u", &a) < 1) + return 1; + b = a; + s = 1; + + c1 = nexttoken(p, '-'); + c2 = nexttoken(p, ','); + if (c1 != NULL && (c2 == NULL || c1 < c2)) { + if (sscanf(c1, "%u", &b) < 1) + return 1; + c1 = nexttoken(c1, ':'); + if (c1 != NULL && (c2 == NULL || c1 < c2)) + if (sscanf(c1, "%u", &s) < 1) { + return 1; + } + } + + if (!(a <= b)) + return 1; + while (a <= b) { + CPU_SET(a, mask); + a += s; + } + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + cpu_set_t new_mask, cur_mask; + pid_t pid = 0; + int opt, err; + char mstr[1 + CPU_SETSIZE / 4]; + char cstr[7 * CPU_SETSIZE]; + int c_opt = 0; + + struct option longopts[] = { + { "pid", 0, NULL, 'p' }, + { "cpu-list", 0, NULL, 'c' }, + { "help", 0, NULL, 'h' }, + { "version", 0, NULL, 'V' }, + { NULL, 0, NULL, 0 } + }; + + while ((opt = getopt_long(argc, argv, "+pchV", longopts, NULL)) != -1) { + int ret = 1; + + switch (opt) { + case 'p': + pid = atoi(argv[argc - 1]); + break; + case 'c': + c_opt = 1; + break; + case 'V': + printf("taskset version " VERSION "\n"); + return 0; + case 'h': + ret = 0; + default: + show_usage(argv[0]); + return ret; + } + } + + if ((!pid && argc - optind < 2) + || (pid && (argc - optind < 1 || argc - optind > 2))) { + show_usage(argv[0]); + return 1; + } + + if (pid) { + if (sched_getaffinity(pid, sizeof (cur_mask), &cur_mask) < 0) { + perror("sched_getaffinity"); + fprintf(stderr, "failed to get pid %d's affinity\n", + pid); + return 1; + } + if (c_opt) + printf("pid %d's current affinity list: %s\n", pid, + cpuset_to_cstr(&cur_mask, cstr)); + else + printf("pid %d's current affinity mask: %s\n", pid, + cpuset_to_str(&cur_mask, mstr)); + + if (argc - optind == 1) + return 0; + } + + if (c_opt) + err = cstr_to_cpuset(&new_mask, argv[optind]); + else + err = str_to_cpuset(&new_mask, argv[optind]); + + if (err) { + if (c_opt) + fprintf(stderr, "failed to parse CPU list %s\n", + argv[optind]); + else + fprintf(stderr, "failed to parse CPU mask %s\n", + argv[optind]); + return 1; + } + + if (sched_setaffinity(pid, sizeof (new_mask), &new_mask)) { + perror("sched_setaffinity"); + fprintf(stderr, "failed to set pid %d's affinity.\n", pid); + return 1; + } + + if (sched_getaffinity(pid, sizeof (cur_mask), &cur_mask) < 0) { + perror("sched_getaffinity"); + fprintf(stderr, "failed to get pid %d's affinity.\n", pid); + return 1; + } + + if (pid) { + if (c_opt) + printf("pid %d's new affinity list: %s\n", pid, + cpuset_to_cstr(&cur_mask, cstr)); + else + printf("pid %d's new affinity mask: %s\n", pid, + cpuset_to_str(&cur_mask, mstr)); + } else { + argv += optind + 1; + execvp(argv[0], argv); + perror("execvp"); + fprintf(stderr, "failed to execute %s\n", argv[0]); + return 1; + } + + return 0; +} |