schedtool-1.3.0.orig/0000755000175000001440000000000011063463473014030 5ustar varenetusersschedtool-1.3.0.orig/error.h0000644000175000001440000000117711063463473015340 0ustar varenetusers/* Schedtool (c) by Freek This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. 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. Please see the file LICENSE for details. */ /* include it here, to let the main also use errno */ #include void decode_error(char *, ...); schedtool-1.3.0.orig/TUNING0000644000175000001440000000200711063463473014756 0ustar varenetusersFIRST AND FOREMOST ------------------ - be sure to set all your IDE disks to use DMA transfers: hdparm -d1 /dev/hda or even hdparm -A1 -X66 -c1 -d1 /dev/hda Please see the man-page for hdparm for explanation of the other options. Can also be applied to CDROMs. - run your own optimized kernel (kernel building IS fun) MPLAYER ------- - use -vo xvidix or -vo xv to offload work to your gfx-card - use a natively (especially for your CPU) compiled mplayer (again, this is fun and you will learn) - use hdparm -u1 -A1 -a 160 - nicing to -5 or -10 already helps, but requires root-privileges XMMS ---- - really should never skip, even at considerable background-compiling load go and compile it with CPU-optimizations for your CPU - set the output-buffer to a higher value ( Preferences -> Output Plugin -> configure -> Buffering -> Buffer size(ms) Enter something like 2500 oder 3000 ) - use a decent soundcards that actually does things in hardware Switching from ISA- to PCI-cards helps a lot schedtool-1.3.0.orig/LICENSE0000644000175000001440000004333511063463473015045 0ustar varenetusersThe following is the original GNU GPL v2 under which schedtool is released. schedtool is (c) by Freek, 2004, 2005, 2006, 2007 -- -- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; 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, or (at your option) any later version. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. schedtool-1.3.0.orig/TODO0000644000175000001440000000041211063463473014515 0ustar varenetusers-add raw number mode for sched policies DONE -add variable parsing of affinity (0x3 == "0,1" etc) DONE -add probing for available features DONE -be more dynamic (spacing in output, ...) PARTIAL -use (*f)() instead of if(mode_set(this, ...))) - core engine rewrite schedtool-1.3.0.orig/INSTALL0000644000175000001440000000344211063463473015064 0ustar varenetusersPREREQUISITES: -------------- This package is released under the terms of the GPL2; you can read it in the file LICENSE. Use at your own risk. SCHED_NORMAL, SCHED_FIFO and SCHED_RR are the supported out of the box by every linux-kernel. If you want to use special scheduling policies, get the according patches listed below. o SCHED_BATCH: Kernel 2.4.18+ with Ingo Molnar's O(1)-sched-patch [ http://www.kernel.org/pub/linux/kernel/people/mingo ] Kernel 2.6.16+ now have support for SCHED_BATCH. Con Kolivas also maintains patches for 2.6. [ http://ck.kolivas.org/patches/2.6 ] o SCHED_ISO and SCHED_IDLEPRIO: 2.6.X and special patches by Con Kolivas [ http://ck.kolivas.org/patches/2.6 ] o CPU-AFFINITY: kernel 2.5.8 or later RedHat9 does contain a patched kernel that supports CPU-affinity for 2.4.X the -aa series also contain support for CPU-affinity [ http://www.kernel.org/pub/linux/kernel/people/andrea ] INSTALLING: ----------- If you want to build WITH CPU-affinity support, do #> make If that gives you errors about affinity or sched_setaffinity, you don't have your system ready for affinity - likely you have a too old glibc without that support. To install, type: #> make install The default prefix is /usr/local, so the binary will be put into /usr/local/bin, the man-page into /usr/local/man/man8; additional docs are put into $PREFIX/share/doc/schedtool. You may change the destination in the Makefile. You can define DEBUG (either by adding -DDEBUG to CFLAGS in the Makefile or specifying them to make) to get additional output. - -- - -- - -- - For the curious, look into: /usr/src/linux/include/linux/sched.h and locate the following: /* * Scheduling policies */ #define SCHED_OTHER 0 #define SCHED_FIFO 1 #define SCHED_RR 2 schedtool-1.3.0.orig/CHANGES0000644000175000001440000001604511063463473015031 0ustar varenetusersTue Aug 6 14:42:36 CEST 2002 v0.3 -added SCHED_FIFO, SCHED_RR, static priorities -updated documentation -included some scheduler overview (sched-design.txt) -misc typo-fixes -added Makefile for fast compiling / installing -fixed logical errors in CHECK_RANGE_PRIO, CHECK_RANGE_POLICY (must've been quite late ;-) Sat Aug 10 16:26:19 CEST 2002 v0.5 -man-page is ready and also installed via make install -README restructured -Wondering about the fast version-progress? The whole package is now roughly half of what I've been dreaming of. Still missing are e.g. some numbers. Fri Aug 30 16:52:27 CEST 2002 v0.6 (only for me) -minor source (-h / -v switches), README and Makefile (target: zipman, unzipman) fixes Wed Sep 4 10:22:31 CEST 2002 v0.7 -huge README updates with some numbers, improvements -return-value updates: return values represent the number of failed sched_setscheduler()-calls with 0 being everything okay. Sun Sep 22 00:18:09 CEST 2002 v0.8 -some code work, #define SCHED_*, replace 0 with SCHED_NORMAL and such minor stuff -clarified the meaning of "higher" in README -asked for util-linux inclusion Mon Nov 11 17:26:45 CET 2002 v0.8b -minor cleanups Tue Aug 26 19:53:41 CEST 2003 v0.9 -implement better error handling to return exactly (well I tried at my best knowledge) what went wrong during the sched_setscheduler()-call -set_process() no longer automatically calls print_process() -minor README/man-page updates regarding kernel versions 2.5 and 2.6 Sun Aug 31 16:14:35 CEST 2003 v0.95 -add support for CPU-affinity -simplify error-handling in code -overhaul the man-page Tue Dec 24 21:31:59 CET 2003 (Tue Jan 6 13:37:32 CET 2004) v0.96 -it is bad practice to have the "prerequisites" containing technical stuff before the "about / info"-section explaing what the hell this even is. README changed accordingly. -moved installing into file INSTALL -Con made a suggestion for using schedtool as a wrapper to start processes with adjusted scheduling-params. Here you go, Con (option -e for (e)xec)! -added parenthesis for safety in print_process in the big if( ... || ... || ... ) --now--> if( (...) || (...) || (...) ) -fixed an argument-BUG ("prio >= prio_min" instead of "p >= ...") in #define CHECK_RANGE_PRIO which did not change behaviour, but was wrong. -made my debug-printing accessible via -DDEBUG_ME -merry christmas Thu Jan 15 14:41:06 CET 2004 v0.97 -changed -e(xecute) semantics from fork() to in-place exec() much like RML's tools do it. This means that the schedtool-process will be overwritten by the specified command. -added padding for better readable output; may change to dynamic spacing in future versions Wed Jan 21 15:44:59 CET 2004 v0.98 -there, people, you have it: your changed cmdline parsing, no need for quoting multi-argument-commands, just plain #> schedtool -3 -e cpu-hog -x1 -l2 THIS MEANS ALSO THAT YOU NO LONGER CAN MIX ARGS AND OPTIONS LIKE: #> schedtool 1 2 3 4 -3 5 6 -restructured the help-output to be more "comprehendable" ... as an admin I get serious pain reading it now -and, hooray, schedtool is now silent "as that is standard unix behaviour" unless you specify -v, which will print for each setting PID and so on, which is indeed what I prefer to have. Now that you have it all like you wanted, send me money or even better, hot chicks. Wed Jan 28 13:51:05 CET 2004 v0.99 -build schedtool with affinity is now the default -changed Makefile a bit; new target no_affinity -included support for SCHED_ISO (patch by Con Kolivas) -update docs to reflect changes Sun Apr 4 10:38:17 CEST 2004 v0.99.1 -support nice operations; schedtool is now capable of setting ALL scheduling attributes! -minor change in engine (move execute into the loop to eliminate duplicate code; the code is slowly getting a mess with all these checks here and there) -documentation /man-page update; man-page now lists SCHED_* -Makefile: new target install-doc, installs some docs into $PREFIX/share/doc/schedtool Tue Apr 20 11:45:19 CEST 2004 v1.0 -released 1.0; more documentation updates and clarifications Wed Jun 30 20:27:29 CEST 2004 v1.1.0 -added "NO WARRANTY" to help output -add raw mode for the kernel hackers; allows direct input of the numerical policy value and changed docs accordingly. Mon Jul 5 14:12:35 CEST 2004 v1.1.1 -added a list mode for affinity, additional to the bitmask mode -identified 2 FIXMEs Sun Aug 1 14:00:58 CEST 2004 -fixed one fixme: check affinity input for isdigit() -changed the CHECK_RANGE_PRIO macro a bit for code cleanup -moved affinity setting to the end of the loop, because may fail with ENOSYS Sun Sep 19 19:50:09 CEST 2004 v1.1.2 -added missing padding for NICE in output -changed custom "policy not implemented" error to "value out of range / policy not implemented" to indicate wrong values when setting affinity or such Tue Sep 28 20:59:42 CEST 2004 v1.2 -finally try to not break affinity-compiled binaries on non-affinity kernels (2nd FIXME fixed) -use getpid() instead of PID 0 (== current process) when in execute mode Sun Oct 3 18:14:46 CEST 2004 v1.2.1 -REALLY DO NOT break affinity stuff; sched_getaffinity() suddenly returns 4 on success instead of 0 as declared in the man-page on at least kernels 2.6.8+ -pad nice-levels correctly; they can be negative, as such we need %3d in printf() Tue Oct 12 13:04:53 CEST 2004 v1.2.2 -adjust copyright -correct typo in man-page -correctly figure out affinity; I was missing an #include Sun Oct 17 00:41:43 CEST 2004 v1.2.3 -get the affinity-ifdef-stuff right. Oh my. -really up version to 1.2.3 (I'm getting old) -remove superfluous break in schedtool.c::engine(), execute part -correct another typo in man-page Sat Nov 27 00:27:23 CET 2004 v1.2.4 -add a "probe" mode (-r), similar to sched-utils; lists prio_min/max -add helper-functions get_prio_min_max() and print_prio_min_max() Sat Feb 5 19:59:44 CET 2005 v1.2.5 -fix NULL pointer printing when policy is out-of-range of TAB[] ; instead, print numeric value + -behave more nicely with SCHED_ISO and newer -ck kernels (inspired by cr7) Tue Jan 17 18:50:04 CET 2006 v1.2.6 -add support for SCHED_IDLEPRIO in 2.6.16-ck kernels -update documentation accordingly; remove old stuff about SCHED_BATCH which is in mainline 2.6 now Mon Sep 30 22:29:48 CEST 2006 v1.2.7 -update man-page: get section(8) right again, mention affinity list mode Tue Nov 14 21:22:18 CET 2006 v1.2.8 -try to initialize aff_mask in a more portable way -minor man-page update -change SCHED_IDLE to SCHED_IDLEPRIO everywhere -change MANPATH to $PREFIX/share/man Sun Nov 26 15:27:12 CET 2006 v1.2.9 -spelling fixes for README; thanks to Sven Hartrumpf -Makefile fix for installing man-page (wrong path); thanks to Adam Sampson Fri Jul 20 20:24:24 CEST 2007 v1.2.10 -fix incorrect use of $DISTDIR in Makefile for RPM-bulding thanks to Adel Gadllah -fix version to 1.2.10 (forgot for 1.2.9) Mon Sep 15 15:35:29 CEST 2008 v1.3.0 -bring schedtool to new glibc affinity api (cpu_set_t) & make it work under new glibcs again -bug-fix behaviour when 1 wrong PID was given - all other (valid) PIDs would run into error schedtool-1.3.0.orig/PACKAGERS0000644000175000001440000000026711063463473015260 0ustar varenetusersPlease remove ALL references to my email-adress in your package/info-page. Instead, write: Please use the "contact author"-form on http://freshmeat.net/projects/schedtool Thank you. schedtool-1.3.0.orig/schedtool.80000644000175000001440000001576111063463473016117 0ustar varenetusers.\" Text automatically generated by txt2man-1.4.5 .TH "SCHEDTOOL" 8 "1 November 2006" "" "System Manager's Manual" .SH "NAME" \fBschedtool \fP\- query and set CPU scheduling parameters .SH "SYNOPSIS" .nf .fam C .TP \fBschedtool\fP [\fB\-0\fP|\fB\-N\fP] [\fB\-1\fP|\fB\-F\fP] [\fB\-2\fP|\fB\-R\fP] [\fB\-3\fP|\fB\-B\fP] [\fB\-4\fP|\fB\-I\fP] [\fB\-5\fP|\fB\-D\fP] [\fB\-M\fP \fIpolicy\fP] [\fB\-a\fP \fIaffinity\fP] [\fB\-p\fP \fIprio\fP] [\fB\-n\fP \fInice_level\fP] [\fB\-e\fP \fIcommand [arg ...]\fP] [\fB\-r\fP] [\fB\-v\fP] [\fB\-h\fP] [LIST OF \fIPIDs\fP] .fam T .fi .SH "DESCRIPTION" \fBschedtool\fP can set all CPU scheduling parameters Linux is capable of or display information for given processes. .P Long\-running, non\-interactive tasks may benefit from SCHED_BATCH as timeslices are longer, less system\-time is wasted by computing the next runnable process and the caches stay stable. .P Audio/video or other near\-realtime applications may run with less skipping if set to SCHED_RR. Use the static priority\-switch \fB\-p\fP to designate inter\-process\-hierarchies. .TP \fBschedtool\fP now supports setting the CPU\-affinity introduced in linux 2.5.8. .SH "OPTIONS" .TP .B \fB\-N\fP or \fB\-0\fP set all \fIPIDs\fP to SCHED_NORMAL/OTHER .TP .B \fB\-F\fP or \fB\-1\fP to SCHED_FIFO root\-credentials required .TP .B \fB\-R\fP or \fB\-2\fP to SCHED_RR root\-credentials required .TP .B \fB\-B\fP or \fB\-3\fP to SCHED_BATCH .TP .B \fB\-I\fP or \fB\-4\fP to SCHED_ISO .TP .B \fB\-D\fP or \fB\-5\fP to SCHED_IDLEPRIO .TP .B \fB\-M\fP \fIpolicy\fP for manual/raw mode; policy is the number of the scheduling policy (see above for 0-4). This option is mostly for kernel guys that want to test their new implementations. .TP .B \fB\-p\fP \fIprio\fP specify static priority \fBrequired\fP for SCHED_FIFO and SCHED_RR. Usually ranged from 1\-99. .TP .B \fB\-a\fP \fIaffinity\fP set the PID's \fIaffinity\fP to this bitmask (hexadecimal); alternatively, a list mode is supported. .TP .B \fB\-n\fP \fInice_level\fP set the PID's nice level; see \fBnice(2), nice(1)\fP. .TP .B \fB\-e\fP \fIcommand [arg ...]\fP execute \fIcommand\fP with given scheduling parameters (overwrites schedtool's process image). See EXAMPLES. .TP .B \fB\-r\fP display min and max priority for each policy. .TP .B \fB\-v\fP be verbose. .TP .B \fB\-h\fP help .SH "EXAMPLES" To query the $SHELL's policies: .PP .nf .fam C #> schedtool $$ To query some \fIPIDs\fP, namely 1 2 and 3: .PP .nf .fam C #> schedtool 1 2 3 .fam T .fi To \fBexecute\fP mplayer in \fBSCHED_RR\fP with priority 20. The priority arg is needed for both SCHED_RR and SCHED_FIFO. .PP .nf .fam C #> schedtool \-R \-p 20 \-e mplayer -quiet some_file.avi .fam T .fi To set current shell to \fBSCHED_BATCH\fP, which all programs the shell starts will inherit: .PP .nf .fam C #> schedtool \-3 $$ .fam T .fi To set all processes with the name 'cpu_hog' to SCHED_BATCH: .PP .nf .fam C #> schedtool \-3 `pidof cpu_hog` .fam T .fi To set a process' \fIaffinity\fP to only the first CPU (CPU0): .PP .nf .fam C #> schedtool \-a 0x1 .fam T Using the list mode and affinty of CPU0 and CPU3: .PP .nf .fam C #> schedtool -a 0,3 .fam T .fi A combination of an \fIaffinity\fP and a \fIpolicy\fP\-argument is \- of course \- always possible. .PP .nf .fam C #> schedtool \-B \-a 0x1 .fam T .fi .SH "AFFINITY MASK" The \fIaffinity\fP\-argument determines on which CPUs a process is allowed to run. It consists of a simple bitmask represented in hexadecimal. CPU0 is denoted by the least\-significant bit, CPU1 by the second least\-significant and so on, thus giving: .PP \fB0x1\fP \-> only run on CPU0 .PP \fB0x2\fP \-> only run on CPU1 .PP \fB0x4\fP \-> only run on CPU2 .PP \fB0x8\fP \-> only run on CPU3 ... and so on. .PP Multi\-target CPUs may be specified using bitwise OR of the values: .PP \fB0x7\fP \-> run on CPUs 0, 1, 2 but \fBNOT\fP on 4 .PP \fB0x3\fP \-> run only on CPUs 0 and 1 .PP The default is to run a process on all CPUs, giving a mask of .PP \fB0xf\fP for all 4 CPUs .PP \fB0xff\fP for all 8 CPUs .SH "AFFINITY MASK - LIST MODE" Alternatively a list mode is supported where you can specify the CPUs delimited by ",". The following runs on CPU0 and CPU1 (equivalent to \fB0x3\fP): .PP .nf .fam C #> schedtool \-a \fB0,1\fP .SH "POLICY OVERVIEW" \fBSCHED_NORMAL / SCHED_OTHER\fP This is the default policy and for the average program with some interaction. Does preemption of other processes. .PP \fBSCHED_FIFO\fP First-In, First Out Scheduler, used only for real-time contraints. Processes in this class are usually not preempted by others, they need to free themselves from the CPU via sched_yield() and as such you need special designed applications. \fBUse with extreme care.\fP \fBROOT-credentials required.\fP .PP \fBSCHED_RR\fP Round-Robin Scheduler, also used for real-time constraints. CPU-time is assigned in an round-robin fashion with a much smaller timeslice than with SCHED_NORMAL and processes in this group are favoured over SCHED_NORMAL. Usable for audio/video applications near peak rate of the system. \fBROOT-credentials required.\fP .PP \fBSCHED_BATCH\fP [ since 2.6.16 in mainline ] SCHED_BATCH was designed for non-interactive, CPU-bound applications. It uses longer timeslices (to better exploit the cache), but can be interrupted anytime by other processes in other classes to guaratee interaction of the system. Processes in this class are selected last but may result in a considerable speed-up (up to 300%). No interactive boosting is done. .PP \fBSCHED_ISO\fP [ patch needed ] SCHED_ISO was designed to give users a SCHED_RR-similar class. To quote Con Kolivas: "This is a non-expiring scheduler policy designed to guarantee a timeslice within a reasonable latency while preventing starvation. Good for gaming, video at the limits of hardware, video capture etc." .PP \fBSCHED_IDLEPRIO\fP [ patch needed ] SCHED_IDLEPRIO is similar to SCHED_BATCH, but was explicitely designed to consume only the time the CPU is idle. No interactive boosting is done. If you used SCHED_BATCH in the -ck kernels this is what you want since 2.6.16 .SH "HINTS" PID 0 means "current process", in our case, schedtool. May occur when using the \-e switch. .PP Be careful with SCHED_FIFO! You may lock out other processes from the CPU, including your shell. .PP For SCHED_BATCH you \fIcertainly\fP need the a recent 2.6 kernel. .PP A short overview is given in SCHED_DESIGN and the \fBREADME\fP contains thourough discussion. The \fBINSTALL\fP file also lists all prerequisites and where you can get patches. .PP Affinity 0x0 should never be used. .SH "SEE ALSO" \fBsched_setscheduler\fP(2), \fBsched_setaffinity\fP(2), \fBnice\fP(2), \fBnice\fP(1), \fBrenice\fP(3). .SH "BUGS" You need some knowledge about the kernel and scheduling. The author is a grumpy little elitist. .SH "AUTHOR" Freek .P Please contact me via freshmeat.net's "contact author"\-feature (http://freshmeat.net/projects/schedtool). schedtool-1.3.0.orig/schedtool.c0000644000175000001440000004046211063463473016166 0ustar varenetusers/* schedtool Copyright (C) 2002-2006 by Freek Please contact me via freshmeat.net Release under GPL, version 2 Use at your own risk. Inspired by setbatch (C) 2002 Ingo Molnar 01/2006: included support for SCHED_IDLEPRIO for ck kernels 01/2004: included SCHED_ISO patch by Con Kolivas 11/2004: add probing for some features (priority) 09/2008: change affinity calls to new cpu_set_t API Born in the need of querying and setting SCHED_* policies. All output, even errors, go to STDOUT to ease piping. Content: main code cmd-line parsing the engine set_/print_process usage */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "util.h" /* various operation modes: print/set/affinity/fork */ #define MODE_NOTHING 0x0 #define MODE_PRINT 0x1 #define MODE_SETPOLICY 0x2 #define MODE_AFFINITY 0x4 #define MODE_EXEC 0x8 #define MODE_NICE 0x10 #define VERSION "1.3.0" /* constants are from the O(1)-sched kernel's include/sched.h I don't want to include kernel-headers. Included those defines for improved readability. */ #undef SCHED_NORMAL #undef SCHED_FIFO #undef SCHED_RR #undef SCHED_BATCH #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 #define SCHED_BATCH 3 #define SCHED_ISO 4 #define SCHED_IDLEPRIO 5 /* for loops */ #define SCHED_MIN SCHED_NORMAL #define SCHED_MAX SCHED_IDLEPRIO #define CHECK_RANGE_POLICY(p) (p <= SCHED_MAX && p >= SCHED_MIN) #define CHECK_RANGE_NICE(n) (n <= 20 && n >= -20) /* 4 bits of CPU_SETSIZE will naturally reduce to 1 char, so we'd only need [CPU_SETSIZE / 4 + 1] to be sure leave a bit of room and only do CPU_SETSIZE / 2 */ #define CPUSET_HEXSTRING(name) char name[CPU_SETSIZE / 2] char *TAB[] = { "N: SCHED_NORMAL", "F: SCHED_FIFO", "R: SCHED_RR", "B: SCHED_BATCH", "I: SCHED_ISO", "D: SCHED_IDLEPRIO", 0 }; /* call it engine_s in lack of a better name */ struct engine_s { int mode; int policy; int prio; int nice; cpu_set_t aff_mask; /* # of args when going in PID-mode */ int n; char **args; }; int engine(struct engine_s *e); int set_process(pid_t pid, int policy, int prio); static inline int val_to_char(int v); static char * cpuset_to_str(cpu_set_t *mask, char *str); static inline int char_to_val(int c); static int str_to_cpuset(cpu_set_t *mask, const char* str); int parse_affinity(cpu_set_t *, char *arg); int set_affinity(pid_t pid, cpu_set_t *mask); int set_niceness(pid_t pid, int nice); void probe_sched_features(); void get_prio_min_max(int policy, int *min, int *max); void print_prio_min_max(int policy); void print_process(pid_t pid); void usage(void); extern char *optarg; extern int optind, opterr, optopt; extern int errno; int main(int ac, char **dc) { /* policy: -1, to indicate it was not set; nice: 10, as nice/renice have as default; prio: 0 per default mode: MODE_NOTHING, no options set */ int policy=-1, nice=10, prio=0, mode=MODE_NOTHING; /* aff_mask: zero it out */ cpu_set_t aff_mask; CPU_ZERO(&aff_mask); /* for getopt() */ int c; if (ac < 2) { usage(); return(0); } while((c=getopt(ac, dc, "+NFRBID012345M:a:p:n:ervh")) != -1) { switch(c) { case '0': case 'N': policy=SCHED_NORMAL; mode |= MODE_SETPOLICY; break; case '1': case 'F': policy=SCHED_FIFO; mode |= MODE_SETPOLICY; break; case '2': case 'R': policy=SCHED_RR; mode |= MODE_SETPOLICY; break; case '3': case 'B': policy=SCHED_BATCH; mode |= MODE_SETPOLICY; break; case '4': case 'I': policy=SCHED_ISO; mode |= MODE_SETPOLICY; break; case '5': case 'D': policy=SCHED_IDLEPRIO; mode |= MODE_SETPOLICY; break; case 'M': /* manual setting */ policy=atoi(optarg); mode |= MODE_SETPOLICY; break; case 'a': mode |= MODE_AFFINITY; parse_affinity(&aff_mask, optarg); break; case 'n': mode |= MODE_NICE; nice=atoi(optarg); break; case 'e': mode |= MODE_EXEC; break; case 'p': prio=atoi(optarg); break; case 'r': probe_sched_features(); break; case 'v': /* the user wants feedback for each process */ mode |= MODE_PRINT; break; case 'V': case 'h': usage(); return(0); default: //printf("ERROR: unknown switch\n"); usage(); return(1); } } /* DAMN FUCKING parameter checking ARGH! */ /* for _BATCH and _NORMAL, prio is ignored and must be 0*/ if((policy==SCHED_NORMAL || policy==SCHED_BATCH) && prio) { decode_error("%s call may fail as static PRIO must be 0 or omitted", TAB[policy] ); /* _FIFO and _RR MUST have prio set */ } else if((policy==SCHED_FIFO || policy==SCHED_RR || policy==SCHED_ISO)) { #define CHECK_RANGE_PRIO(p, p_low, p_high) (p <= (p_high) && p >= (p_low)) /* FIFO and RR - check min/max priority */ int prio_min, prio_max; get_prio_min_max(policy, &prio_min, &prio_max); //int prio_max=sched_get_priority_max(policy); //int prio_min=sched_get_priority_min(policy); if(! CHECK_RANGE_PRIO(prio, prio_min, prio_max)) { // this could be problematic on very special custom kernels if(prio == 0) { decode_error("missing priority; specify static priority via -p"); } else { decode_error("PRIO %d is out of range %d-%d for %s", prio, prio_min, prio_max, TAB[policy] ); } /* treat as all calls have failed */ return(ac-optind); } #undef CHECK_RANGE_PRIO } /* no mode -> do querying */ if(! mode) { mode |= MODE_PRINT; } if( mode_set(mode, MODE_EXEC) && ! ( mode_set(mode, MODE_SETPOLICY) || mode_set(mode, MODE_AFFINITY) || mode_set(mode, MODE_NICE) ) ) { /* we have nothing to do */ decode_error("Option -e needs scheduling-parameters, not given - exiting"); return(-1); } if(! CHECK_RANGE_NICE(nice)) { decode_error("NICE %d is out of range -20 to 20", nice); return(-1); } #undef CHECK_RANGE_NICE /* and: ignition */ { struct engine_s stuff; /* now fill struct */ stuff.mode=mode; stuff.policy=policy; stuff.prio=prio; stuff.aff_mask=aff_mask; stuff.nice=nice; /* we have this much real args/PIDs to process */ stuff.n=ac-optind; /* this is the first real arg */ stuff.args=dc+optind; /* now go on and do what we were told */ return(engine(&stuff)); } } int engine(struct engine_s *e) { int ret=0; int i; #ifdef DEBUG do { CPUSET_HEXSTRING(tmpaff); printf("Dumping mode: 0x%x\n", e->mode); printf("Dumping affinity: 0x%s\n", cpuset_to_str(&(e->aff_mask), tmpaff)); printf("We have %d args to do\n", e->n); for(i=0;i < e->n; i++) { printf("Dump arg %d: %s\n", i, e->args[i]); } } while(0); #endif /* handle normal query/set operation: set/query all given PIDs */ for(i=0; i < e->n; i++) { int pid, tmpret=0; cpu_set_t affi; CPU_ZERO(&affi); CPU_SET(0, &affi); /* if in MODE_EXEC skip check for PIDs */ if(mode_set(e->mode, MODE_EXEC)) { pid=getpid(); goto exec_mode_special; } if(! (isdigit( *(e->args[i])) ) ) { decode_error("Ignoring arg %s: is not a PID", e->args[i]); continue; } pid=atoi(e->args[i]); exec_mode_special: if(mode_set(e->mode, MODE_SETPOLICY)) { /* accumulate possible errors the return value of main will indicate how much set-calls went wrong set_process returns -1 upon failure */ tmpret=set_process(pid,e->policy,e->prio); ret += tmpret; /* don't proceed as something went wrong already */ if(tmpret) { continue; } } if(mode_set(e->mode, MODE_NICE)) { tmpret=set_niceness(pid, e->nice); ret += tmpret; if(tmpret) { continue; } } if(mode_set(e->mode, MODE_AFFINITY)) { tmpret=set_affinity(pid, &(e->aff_mask)); ret += tmpret; if(tmpret) { continue; } } /* and print process info when set, too */ if(mode_set(e->mode, MODE_PRINT)) { print_process(pid); } /* EXECUTE: at the end */ if(mode_set(e->mode, MODE_EXEC)) { char **new_argv=e->args; ret=execvp(*new_argv, new_argv); /* only reached on error */ decode_error("schedtool: Could not exec %s", *new_argv); return(ret); } } /* indicate how many errors we got; as ret is accumulated negative, convert to positive */ return(abs(ret)); } int set_process(pid_t pid, int policy, int prio) { struct sched_param p; int ret; char *msg1="could not set PID %d to %s"; char *msg2="could not set PID %d to raw policy #%d"; p.sched_priority=prio; /* anything other than 0 indicates error */ if((ret=sched_setscheduler(pid, policy, &p))) { /* la la pointer mismatch .. lala */ decode_error((CHECK_RANGE_POLICY(policy) ? msg1 : msg2), pid, (CHECK_RANGE_POLICY(policy) ? TAB[policy] : policy) ); return(ret); } return(0); } /* the following functions have been taken from taskset of util-linux (C) 2004 by Robert Love */ 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; } /* str seems to need to hold [CPU_SETSIZE * 7] chars, as in used in taskset however, 4 bits of CPU_SETSIZE will naturally reduce to 1 char (bits "1111" -> char "f") so CPU_SETSIZE / 4 + 1 should be sufficient will pad with zeroes to the start, so print the string starting at the returned char * */ 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 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 && str[0] == '0' && str[1] == 'x') { 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; } /* end of functions taken */ /* mhm - we need something clever for all that CPU_SET() and CPU_ISSET() stuff */ int parse_affinity(cpu_set_t *mask, char *arg) { cpu_set_t tmp_aff; char *tmp_arg; size_t valid_len; CPU_ZERO(&tmp_aff); if(*arg == '0' && *(arg+1) == 'x') { /* we're in standard hex mode */ str_to_cpuset(&tmp_aff, arg); } else if( (valid_len=strspn(arg, "0123456789,.")) ) { /* new list mode: schedtool -a 0,2 -> run on CPU0 and CPU2 */ /* split on ',' and '.', because '.' is near ',' :) */ while((tmp_arg=strsep(&arg, ",."))) { int tmp_cpu; if(isdigit((int)*tmp_arg)) { tmp_cpu=atoi(tmp_arg); CPU_SET(tmp_cpu, &tmp_aff); #ifdef DEBUG printf("tmp_arg: %s -> tmp_cpu: %d\n", tmp_arg, tmp_cpu); #endif } } } else { decode_error("affinity %s is not parseable", arg); exit(1); } *mask=tmp_aff; return 0; } int set_affinity(pid_t pid, cpu_set_t *mask) { int ret; CPUSET_HEXSTRING(aff_hex); if((ret=sched_setaffinity(pid, sizeof(cpu_set_t), mask)) == -1) { decode_error("could not set PID %d to affinity 0x%s", pid, cpuset_to_str(mask, aff_hex) ); return(ret); } return(0); } int set_niceness(pid_t pid, int nice) { int ret; if((ret=setpriority(PRIO_PROCESS, pid, nice))) { decode_error("could not set PID %d to nice %d", pid, nice ); return(ret); } return(0); } /* probe some features; just basic right now */ void probe_sched_features() { int i; for(i=SCHED_MIN; i <= SCHED_MAX; i++) { print_prio_min_max(i); } } /* get the min/max static priorites of a given policy. Max only work for SCHED_FIFO / SCHED_RR */ void get_prio_min_max(int policy, int *min, int *max) { *min=sched_get_priority_min(policy); *max=sched_get_priority_max(policy); } /* print the min and max priority of a given policy, like chrt does */ void print_prio_min_max(int policy) { int min, max; get_prio_min_max(policy, &min, &max); switch(min|max) { case -1: printf("%-17s: policy not implemented\n", TAB[policy]); break; default: printf("%-17s: prio_min %d, prio_max %d\n", TAB[policy], min, max); break; } } /* Be more careful with at least the affinity call; someone may use an affinity-compiled version on a non-affinity kernel. This is getting more and more fu-gly. */ void print_process(pid_t pid) { int policy, nice; struct sched_param p; cpu_set_t aff_mask; CPUSET_HEXSTRING(aff_mask_hex); CPU_ZERO(&aff_mask); /* strict error checking not needed - it works or not. */ errno=0; if( ((policy=sched_getscheduler(pid)) < 0) || (sched_getparam(pid, &p) < 0) /* getpriority may successfully return negative values, so errno needs to be checked */ || ((nice=getpriority(PRIO_PROCESS, pid)) && errno) ) { decode_error("could not get scheduling-information for PID %d", pid); } else { /* do custom output for unknown policy */ if(! CHECK_RANGE_POLICY(policy)) { printf("PID %5d: PRIO %3d, POLICY %-5d , NICE %3d", pid, p.sched_priority, policy, nice ); } else { printf("PID %5d: PRIO %3d, POLICY %-17s, NICE %3d", pid, p.sched_priority, TAB[policy], nice ); } /* sched_getaffinity() seems to also return (int)4 on 2.6.8+ on x86 when successful. this goes against the documentation */ if(sched_getaffinity(pid, sizeof(aff_mask), &aff_mask) == -1) { /* error or -ENOSYS simply ignore and reset errno! */ errno=0; } else { printf(", AFFINITY 0x%s", cpuset_to_str(&aff_mask, aff_mask_hex)); } printf("\n"); } } void usage(void) { printf( "get/set scheduling policies - v" VERSION ", GPL'd, NO WARRANTY\n" \ "USAGE: schedtool PIDS - query PIDS\n" \ " schedtool [OPTIONS] PIDS - set PIDS\n" \ " schedtool [OPTIONS] -e COMMAND - exec COMMAND\n" \ "\n" \ "set scheduling policies:\n" \ " -N for SCHED_NORMAL\n" \ " -F -p PRIO for SCHED_FIFO only as root\n" \ " -R -p PRIO for SCHED_RR only as root\n" \ " -B for SCHED_BATCH\n" \ " -I -p PRIO for SCHED_ISO\n" \ " -D for SCHED_IDLEPRIO\n" \ "\n" \ " -M POLICY for manual mode; raw number for POLICY\n" \ " -p STATIC_PRIORITY usually 1-99; only for FIFO or RR\n" \ " higher numbers means higher priority\n" \ " -n NICE_LEVEL set niceness to NICE_LEVEL\n" \ " -a AFFINITY_MASK set CPU-affinity to bitmask or list\n\n" \ " -e COMMAND [ARGS] start COMMAND with specified policy/priority\n" \ " -r display priority min/max for each policy\n" \ " -v be verbose\n" \ "\n" \ ); /* printf("Parent "); print_process(getppid()); */ } schedtool-1.3.0.orig/Makefile0000644000175000001440000000260011063463473015466 0ustar varenetusers# go on and adjust here if you don't like those flags CFLAGS=-Os -fomit-frame-pointer -s -pipe #CFLAGS=-Wall -Os -fomit-frame-pointer -s -pipe -DDEBUG CC=gcc # likewise, if you want to change the destination prefix DESTDIR= DESTPREFIX=/usr/local MANDIR=$(DESTPREFIX)/share/man/man8 GZIP=gzip -9 TARGET=schedtool DOCS=LICENSE README INSTALL SCHED_DESIGN RELEASE=$(shell basename `pwd`) all: $(TARGET) clean: rm -f *.o $(TARGET) distclean: clean unzipman rm -f *~ *.s install: all install-doc zipman install -d $(DESTDIR)$(DESTPREFIX)/bin install -p -c $(TARGET) $(DESTDIR)$(DESTPREFIX)/bin install -d $(DESTDIR)$(MANDIR) install -p -c schedtool.8.gz $(DESTDIR)$(MANDIR) install-doc: install -d $(DESTDIR)$(DESTPREFIX)/share/doc/$(RELEASE) install -p -c $(DOCS) $(DESTDIR)$(DESTPREFIX)/share/doc/$(RELEASE) zipman: test -f schedtool.8 && $(GZIP) schedtool.8 || exit 0 unzipman: test -f schedtool.8.gz && $(GZIP) -d schedtool.8.gz || exit 0 affinity_hack: clean $(MAKE) CFLAGS="$(CFLAGS) -DHAVE_AFFINITY_HACK" $(TARGET) release: distclean release_gz release_bz2 @echo --- $(RELEASE) released --- release_gz: distclean @echo Building tar.gz ( cd .. ; tar czf $(RELEASE).tar.gz $(RELEASE) ) release_bz2: distclean @echo Building tar.bz2 ( cd .. ; tar cjf $(RELEASE).tar.bz2 $(RELEASE) ) schedtool: schedtool.o error.o schedtool.o: schedtool.c error.h util.h error.o: error.c error.h schedtool-1.3.0.orig/SCHED_DESIGN0000644000175000001440000002004611063463473015634 0ustar varenetusers Goals, Design and Implementation of the new ultra-scalable O(1) scheduler This is an edited version of an email Ingo Molnar sent to lkml on 4 Jan 2002. It describes the goals, design, and implementation of Ingo's new ultra-scalable O(1) scheduler. Edits by Robert Love, 18 April 2002, to add corrections and account for changes to the scheduler since its debut. Goal ==== The main goal of the new scheduler is to keep all the good things we know and love about the current Linux scheduler: - good interactive performance even during high load: if the user types or clicks then the system must react instantly and must execute the user tasks smoothly, even during considerable background load. - good scheduling/wakeup performance with 1-2 runnable processes. - fairness: no process should stay without any timeslice for any unreasonable amount of time. No process should get an unjustly high amount of CPU time. - priorities: less important tasks can be started with lower priority, more important tasks with higher priority. - SMP efficiency: no CPU should stay idle if there is work to do. - SMP affinity: processes which run on one CPU should stay affine to that CPU. Processes should not bounce between CPUs too frequently. - plus additional scheduler features: RT scheduling, CPU binding. and the goal is also to add a few new things: - fully O(1) scheduling. Are you tired of the recalculation loop blowing the L1 cache away every now and then? Do you think the goodness loop is taking a bit too long to finish if there are lots of runnable processes? This new scheduler takes no prisoners: wakeup(), schedule(), the timer interrupt are all O(1) algorithms. There is no recalculation loop. There is no goodness loop either. - 'perfect' SMP scalability. With the new scheduler there is no 'big' runqueue_lock anymore - it's all per-CPU runqueues and locks - two tasks on two separate CPUs can wake up, schedule and context-switch completely in parallel, without any interlocking. All scheduling-relevant data is structured for maximum scalability. - better SMP affinity. The old scheduler has a particular weakness that causes the random bouncing of tasks between CPUs if/when higher priority/interactive tasks, this was observed and reported by many people. The reason is that the timeslice recalculation loop first needs every currently running task to consume its timeslice. But when this happens on eg. an 8-way system, then this property starves an increasing number of CPUs from executing any process. Once the last task that has a timeslice left has finished using up that timeslice, the recalculation loop is triggered and other CPUs can start executing tasks again - after having idled around for a number of timer ticks. The more CPUs, the worse this effect. Furthermore, this same effect causes the bouncing effect as well: whenever there is such a 'timeslice squeeze' of the global runqueue, idle processors start executing tasks which are not affine to that CPU. (because the affine tasks have finished off their timeslices already.) The new scheduler solves this problem by distributing timeslices on a per-CPU basis, without having any global synchronization or recalculation. - batch scheduling. A significant proportion of computing-intensive tasks benefit from batch-scheduling, where timeslices are long and processes are roundrobin scheduled. [ I don't know if the following is still true; to enter BATCH-mode please use schedtool. SCHED_BATCH processes, are, however, interruptible by SCHED_NORMAL processes anytime to garantee interactiveness. -Freek ] The new scheduler does such batch-scheduling of the lowest priority tasks - so nice +19 jobs will get 'batch-scheduled' automatically. With this scheduler, nice +19 jobs are in essence SCHED_IDLE, from an interactiveness point of view. - handle extreme loads more smoothly, without breakdown and scheduling storms. - O(1) RT scheduling. For those RT folks who are paranoid about the O(nr_running) property of the goodness loop and the recalculation loop. - run fork()ed children before the parent. Andrea has pointed out the advantages of this a few months ago, but patches for this feature do not work with the old scheduler as well as they should, because idle processes often steal the new child before the fork()ing CPU gets to execute it. Design ====== the core of the new scheduler are the following mechanizms: - *two*, priority-ordered 'priority arrays' per CPU. There is an 'active' array and an 'expired' array. The active array contains all tasks that are affine to this CPU and have timeslices left. The expired array contains all tasks which have used up their timeslices - but this array is kept sorted as well. The active and expired array is not accessed directly, it's accessed through two pointers in the per-CPU runqueue structure. If all active tasks are used up then we 'switch' the two pointers and from now on the ready-to-go (former-) expired array is the active array - and the empty active array serves as the new collector for expired tasks. - there is a 64-bit bitmap cache for array indices. Finding the highest priority task is thus a matter of two x86 BSFL bit-search instructions. the split-array solution enables us to have an arbitrary number of active and expired tasks, and the recalculation of timeslices can be done immediately when the timeslice expires. Because the arrays are always access through the pointers in the runqueue, switching the two arrays can be done very quickly. this is a hybride priority-list approach coupled with roundrobin scheduling and the array-switch method of distributing timeslices. - there is a per-task 'load estimator'. one of the toughest things to get right is good interactive feel during heavy system load. While playing with various scheduler variants i found that the best interactive feel is achieved not by 'boosting' interactive tasks, but by 'punishing' tasks that want to use more CPU time than there is available. This method is also much easier to do in an O(1) fashion. to establish the actual 'load' the task contributes to the system, a complex-looking but pretty accurate method is used: there is a 4-entry 'history' ringbuffer of the task's activities during the last 4 seconds. This ringbuffer is operated without much overhead. The entries tell the scheduler a pretty accurate load-history of the task: has it used up more CPU time or less during the past N seconds. [the size '4' and the interval of 4x 1 seconds was found by lots of experimentation - this part is flexible and can be changed in both directions.] the penalty a task gets for generating more load than the CPU can handle is a priority decrease - there is a maximum amount to this penalty relative to their static priority, so even fully CPU-bound tasks will observe each other's priorities, and will share the CPU accordingly. the SMP load-balancer can be extended/switched with additional parallel computing and cache hierarchy concepts: NUMA scheduling, multi-core CPUs can be supported easily by changing the load-balancer. Right now it's tuned for my SMP systems. i skipped the prev->mm == next->mm advantage - no workload i know of shows any sensitivity to this. It can be added back by sacrificing O(1) schedule() [the current and one-lower priority list can be searched for a that->mm == current->mm condition], but costs a fair number of cycles during a number of important workloads, so i wanted to avoid this as much as possible. - the SMP idle-task startup code was still racy and the new scheduler triggered this. So i streamlined the idle-setup code a bit. We do not call into schedule() before all processors have started up fully and all idle threads are in place. - the patch also cleans up a number of aspects of sched.c - moves code into other areas of the kernel where it's appropriate, and simplifies certain code paths and data constructs. As a result, the new scheduler's code is smaller than the old one. Ingo schedtool-1.3.0.orig/util.h0000644000175000001440000000117511063463473015162 0ustar varenetusers/* Schedtool (c) by Freek This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. 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. Please see the file LICENSE for details. */ /* contains bit-fiddeling */ inline static int mode_set(int x, int try) { return((x & try) == try); } schedtool-1.3.0.orig/syscall_magic.h0000644000175000001440000000147711063463473017024 0ustar varenetusers/* this sticks around for documentation issues only and will be removed in the next release - it documents the direct syscalls for affinity, without going thru glibc */ #if 0 /* I don't know where this was exactly taken from, but I think I found it in glibc. */ #include #define __NR_sched_setaffinity 241 #define __NR_sched_getaffinity 242 /* a nice macro to define the following: it's a syscall with 3 args, it returns int, it's named sched_...., the next arg is of type pid_t, has the local name pid, next is unsigned int, with name len, then an unsigned long *, named user_mask_ptr */ _syscall3 (int, sched_setaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr) _syscall3 (int, sched_getaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr) #endif schedtool-1.3.0.orig/README0000644000175000001440000002763611063463473014726 0ustar varenetusersschedtool Copyright (C) 2002-2006 Freek Release under GPL, version 2 (see LICENSE) Use at your own risk. Inspired by setbatch (C) 2002 Ingo Molnar Suggestions are welcome. CONTENT: -------- -About -Usage / description of schedtool -A complex example -Static Priority -Policies reviewed -Thanks -Appendix A: A course into Multi-Level-Feedback-Queue-scheduling ABOUT: ------ schedtool was born, because there was no tool to change or query all CPU-scheduling policies under Linux, in one handy command. Support for CPU-affinity has also been added and most recently (re-)nicing of processes. Thus, schedtool is the definitive interface to Linux's scheduler. It can be used to avoid skipping for A/V-applications, to lock processes onto certain CPUs on SMP/NUMA systems, which may be beneficial for networking or benchmarks, or to adjust nice-levels of lesser important jobs to maintain a high amount of interactive responsiveness under high load. All output, even errors, go to STDOUT to ease piping. If you don't know about scheduling policies, you probably don't want to use this program - or learn and read "man sched_setscheduler". Certain modes (as of this writing: SCHED_IDLEPRIO and SCHED_ISO) need a patched kernel. See INSTALL for details. USAGE: ------ There are 3 operation modes: query, set and execute new process. QUERY PROCESS(ES): #> schedtool This will print all information it can obtain for the processes with . SET PROCESS(ES): I) scheduling policy (detailed discussion in "POLICY OVERVIEW") #> schedtool - where is one of: N or 0: for SCHED_NORMAL F or 1: for SCHED_FIFO R or 2: for SCHED_RR B or 3: for SCHED_BATCH I or 4: for SCHED_ISO example: #> schedtool -B II) static priority .. is mandatory for SCHED_FIFO and SCHED_RR STATIC_PRIO is a number from 1-99; higher values mean higher priority in that scheduling class (relative to other processes in the same class). example: #> schedtool -R -p 20 III) CPU-affinity example: #> schedtool -a 0x3 IV) nice-level example #> schedtool -n 10 Of course you can combine policy with affinity and nice in one call. EXECUTE A NEW PROCESS: example: #> schedtool [SCHED_PARAMETERS_LIKE_ABOVE] -e command -arg1 -arg2 file This will execute "command -arg1 -arg2 file" like typing exactly this on the prompt would. CPU-affinity: To give PIDs/a command a certain CPU-affinity, use the -a switch. The value is used as a simple bitmask, the bit set to 1 denoting the PID may run on that CPU, the bit unset (0) denoting it MUST NOT. The following picture uses only 16 bits for example purpose. The resulting value is the bitwise OR of the single values for each CPU. CPU0 (the first CPU in your system) is denoted by the least significant bit (here, the one on the right side). CPU 0-----------, CPU 1-----------,| ... || mask VV means value == dec -------------------------------------------------------------------------- 0000 0000 0000 0001 -> run only on CPU0 -> 0x1 == 1 0000 0000 0000 1001 -> run on CPU0 AND CPU3 -> 0x9 == 9 0000 0000 0000 1111 -> run on CPU0-CPU4 -> 0xF == 15 1111 1111 1111 1111 -> run on CPU0-CPU15 -> 0xFFFF ==2^16-1 To set back to the default (PID may run on all CPUs), use the mask 0xFFFFFFFF (the kernel will automatically reduce it to the max # of cpus) As a short mnemonic rule, each 'F' denotes a set of 4 CPUs (0xF: all 4 CPUs, 0xFF: all 8 CPUs, and so on ...) Since version 1.1.1 a new list mode is supported, allowing you to specify the target-CPUs without doing bitjuggling. To separate the different CPUs, use a ',': Run on CPU0 and CPU1: #> schedtool -a 0,1 A COMPLEX EXAMPLE: ------------------ #> schedtool -R -p 50 -a 0x2 -e mplayer file.avi Execute mplayer file.avi with -SCHED_RR, -static priority 50, -affinity 0x2 (run only on CPU1). ABOUT STATIC PRIORITY: ---------------------- Static priority is something completely different than the nice-level; the nice-level is added to the dynamic priority, and the higher it gets, the more the process is "punished"([2]), whereas the static priority is used to find the next process to run in the current scheduling class and the higher it is the more preferred >in general< the process is over others, e.g. when it's becoming ready after a blocking action. It will/may also preempt another, lower-prioritized process. STATIC_PRIO can't be assigned to SCHED_NORMAL or SCHED_BATCH. The code won't prevent this (a warning is printed - think UNIX), you maybe get an error later at the setting-call. v1.2.4+ support a probe mode like sched-utils; it will display each policy's min and max priority, when given the -r parameter. #> schedtool -r N: SCHED_NORMAL : prio_min 0, prio_max 0 F: SCHED_FIFO : prio_min 1, prio_max 99 R: SCHED_RR : prio_min 1, prio_max 99 B: SCHED_BATCH : prio_min 0, prio_max 0 I: SCHED_ISO : policy not implemented D: SCHED_IDLEPRIO: policy not implemented POLICY OVERVIEW + WHERE TO USE: ------------------------------- SCHED_NORMAL is the standard scheduling policy and good for the average job with reasonable interaction. SCHED_FF and SCHED_RR are for real-time constraints. Don't use them for normal stuff, because they've got extremely short time-slices increasing the context-switching overhead and they won't let other processes run until they get blocked by a system-call like read() or actively free themselves from the CPU via the system-call sched_yield(2). SCHED_BATCH is encuraged for long-running and non-interactive processes; the timeslice is considerably longer (1.5s I think) - these processes, though, are interrupted almost anytime by other ones to guarantee interactiveness. Processes won't get any interactive boosts. Users are encouraged to set their computing jobs to SCHED_BATCH. Or, as admin of a compute-server, you could set their shells to SCHED_BATCH via the login-script. SCHED_BATCH has been included in 2.6.16+ kernels. SCHED_ISO [patch needed, see INSTALL] is a new mode, currently only in Con's patches, to mimick the real-time class for non-root users. To quote Con: "Any task trying to start as real time that doesn't have authority to do so will be set to SCHED_ISO. This is a non-expiring scheduler policy designed to guarantee a timeslice within a reasonable latency while preventing starvation. Good for gaming, video at the limits of hardware, video capture etc. It is best set using the schedtool by a normal user trying to start something as SCHED_RR." [ http://kerneltrap.org/node/view/2159 ] SCHED_ISO is now somewhat deprecated; SCHED_RR is now possible for normal users, albeit to a limited amount only. See newer kernels. SCHED_IDLEPRIO [patch needed, see INSTALL] SCHED_IDLEPRIO was formerly called SCHED_BATCH in the -ck patchset; the -ck SCHED_BATCH has nothing to do with the mainline SCHED_BATCH! It is a policy where the process does not get any interactive boost (through sleeping etc) and also only the idle CPU time. For more information you can read the file SCHED_DESIGN as a good overview, but be warned, that *some* things may be outdated by the new O(1)-patches. Then proceed to the man-page for sched_setscheduler(2) - it gives a very good overview and is _highly_ recommended. FINAL WORDS / CONTACT: ---------------------- If you feel you are able to make this software better or you can report some numbers with the different scheduling policies, please contact me. Feedback is appreciated. Please use freshmeat.net's "contact author"-feature to do so. THANKS: ------- Thanks fly out to (in no particular order) o Ingo Molnar o Con Kolivas for suggesting the -e switch, submitting patch for SCHED_ISO o Samuli Kärkkäinen, the quality-verification-engineer o my girlfriend and supporting friends - -- - -- - [2]: A bit simplified - it's not all that easy :-) Go on to Appendix A for an example on how scheduling is performed in Solaris. [3]: (see also [4]) Nice level and dynamic priority are somewhat "strange": sometimes, higher values mean higher priority (to be put on CPU when process ready); sometimes, lower values mean higher priority. At the moment, I confirm my system being the following: - The nice-level is SUBSTRACTED from the dynamic priority, thus giving a Process nice -10 means INCREASING it's priority (valuewise) by 10 points. - In the end, higher values mean higher priority. Use "ps -eO pri,nice" and look for yourself. APPENDIX A: INTRODUCTION TO MULTI-LEVEL-QUEUE-FEEDBACK-SCHEDULING ----------------------------------------------------------------- This appendix uses information originating from the "System Programming I"-course at my university; the examples are using Solaris 2.X, but I think, Linux is doing it in a >similar< (albeit not that overcomplicated) way. Solaris has 60 wait queues for the class TS (TimeSharing); there are other classes as system and RealTime as well. A TS-queue looks like this (which is basically a set of rules): Level ts_quantum ts_tqexp ts_maxwait ts_lwait ts_slpret 0 200 0 0 50 50 . . . . . . . . . . . . . . . . . . 44 40 34 0 55 55 45 40 35 0 56 56 . . . . . . . . . . . . . . . . . . 59 20 49 32000 59 59 You can display all these numbers on a Solaris-box using # dispadmin -c TS -g Level: just a queue ID. ts_quantum: the maximum timeslice - the maximum time, the process is allowed to run continuously until it's interrupted and another process is physically put on the CPU. ts_tqexp: if the process uses it's timeslice entirely, it's put into that queue [cf. Level]. ts_maxwait: maximum time to wait for the process in that queue without being run, in seconds. ts_lwait: if one process stays too long in the current queue, it's put into that queue. ts_slpret: queue to put the process in after it was blocked, e.g. in a syscall. Let's start an imaginary process and look what's happening: Start -> -> queue 59, ts_quantum 20ms -> queue 49, ts_quantum 40ms -> queue 39, ts_quantum 80ms -> queue 29, ts_quantum 120ms -> queue 19, ts_quantum 160ms -> queue 9, ts_quantum 200ms You see how this only number-crunching process is put into queues that allow him to use the CPU for more and more time. Now let's do the process a blocking action: queue 0, ts_quantum 200ms, after e.g. 100ms blocking call! --> queue 50, ts_quantum 40ms, after e.g. 20ms blocking call! --> queue 58, ts_quantum 40ms Now you see how this process is "punished", or from another point of view, the scheduler thinks, this is an interactive process computing a bit and then outputting data, so it's put into a queue that has averagely the same computing time until a this output occurs. So the schedulers knows pretty much about the current state of the machine and can plan accordingly. The dynamic priority is something like an age - the higher[4] it is the more likely you get a seat :) (the CPU). There are 4 rules: -if a process is not run, it ages - the dynamic priority rises. -if a process is running, the dynamic priority is lowered. -the process with the (at the moment) highest priority is put onto the CPU. -processes with lower priority are/can be interrupted by processes with higher priority. This guarantees that no process is running for too long and others are waiting for too long. -End Of Documentation - -- - [4]: higher (priority) in means of more important to run in the near future; higher does not automatically mean a higher value in it's PCB[5] [5]: Process Control Block, some structure where important accounting and other useful information are stored, usually only used by the kernel. schedtool-1.3.0.orig/error.c0000644000175000001440000000236611063463473015334 0ustar varenetusers/* Schedtool (c) by Freek This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. 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. Please see the file LICENSE for details. */ /* Content: This includes a nice error-function */ #include #include #include #include "error.h" /* print ERROR: + given message + errormsg received via errno */ void decode_error(char *fmt, ...) { va_list args; char *msg=NULL; int tmp_errno=errno; printf("ERROR: "); va_start(args, fmt); vprintf(fmt, args); va_end(args); if(errno) { /* do our own errors */ if (errno == EINVAL) { msg="value out of range / policy not implemented"; goto bail; } /* hu, can this be unsave ? */ msg=(char *)strerror(errno); /* the strerror()-call went wrong */ if(errno != tmp_errno) { msg="unknown error code, sorry"; } bail: printf(" - %s",msg); } printf("\n"); }