diff --git a/doc/sgpem2dman.texi b/doc/sgpem2dman.texi index 0e8a801..6235e16 100644 --- a/doc/sgpem2dman.texi +++ b/doc/sgpem2dman.texi @@ -17,7 +17,7 @@ This is SGPEMv2 Developer Manual (version @value{VERSION}, @value{UPDATED}). -Copyright @copyright{} 2005 University of Padova, dept. of Pure +Copyright @copyright{} 2005-2006 University of Padova, dept. of Pure and Applied Mathematics Permission is granted to copy, distribute and/or modify this document diff --git a/doc/sgpem2uman.texi b/doc/sgpem2uman.texi index a6a5d6e..0b3bd1e 100644 --- a/doc/sgpem2uman.texi +++ b/doc/sgpem2uman.texi @@ -17,7 +17,7 @@ This is SGPEMv2 User Manual (version @value{VERSION}, @value{UPDATED}). -Copyright @copyright{} 2005 University of Padova, dept. of Pure +Copyright @copyright{} 2005-2006 University of Padova, dept. of Pure and Applied Mathematics Permission is granted to copy, distribute and/or modify this document @@ -67,7 +67,7 @@ Free Documentation License''. * Overview of SGPEM:: Description and objectives of SGPEM v2. * Installation:: Here we explain how to install SGPEM v2, - as well as providing some advice for + as well as providing some advice for believed-to-be useful compilation options. * Basics:: Things you should know before starting. @@ -89,6 +89,10 @@ Free Documentation License''. @unnumbered History @table @strong +@item 2006, September 8th @r{-- Matteo Settenvini} +Update chapters about building and installation. Rewrite some of the +chapter about extending SGPEMv2 with custom CPU policies, and add a +more complex example. @item 2006, September 7th @r{--- Luca Vezzaro} First attempt at expanding the manual structure with the stuff we'll need in the forthcoming beta testing @@ -130,11 +134,14 @@ First draft of this document. @cindex description SGPEM is an Italian acronym, standing for ``@emph{Simulatore della Gestione dei Processi -in un Elaboratore Multiprogrammato}'' (in English, ``@emph{Multitasking Computer Process -Management Simulator}''). +in un Elaboratore Multiprogrammato}'' (in English, ``@emph{Process +Management Simulator for a Multitasking Computer}''). It was initially developed for use inside the ``Operating Systems'' teaching, part of the Computer Science course of the University of Padova, Italy. -The aim of SGPEM is to provide an for simulating policies applied to sort processes, and for assigning resources in a multitasking computer. SGPEMv2 is a didactic software, and it can help students to understand better the functionality of Operating Systems. +The aim of SGPEM is to provide an easy-to-use environment for +simulating process scheduling policies, and for assigning resources in +a multitasking computer. SGPEMv2 is an educational software, and it can +help students to better understand the functionality of operating systems. @c % -------------------------------------------------- @@ -143,8 +150,8 @@ The aim of SGPEM is to provide an for simulating policies applied to sort proce @section How to read this manual? @cindex manual -We recommend that you read the manual following the the structure that we imposed for it. -You will be guided trough the Installation, Configuration and Usage process of SGPEM v2. +We recommend that you read the manual following the the structure that +we layed out for it. You will be gently led trough Installation, Configuration and Usage of SGPEMv2. If you find yourself in trouble reading the manual, please don't hesitate to contact us at @email{swe@@thgnet.it}. @@ -156,7 +163,7 @@ If you find yourself in trouble reading the manual, please don't hesitate to con @cindex reporting We welcome bug reports and suggestions for any aspect of the SGPEM v2 system, program in general, -documentation, installation, anything.Please email us at @email{swe@@thgnet.it}. +documentation, installation... anything. Please email us at @email{swe@@thgnet.it}. For bug reporters, include enough information for us to reproduce the problem. In general: @itemize @item @@ -193,14 +200,13 @@ You can use the program from your own shell, or if you prefer you can use the mi @item The output of the simulation is textual, and you can see it on the main GUI window or on your Terminal window. @item -The policy in use if First Come First Served. +The policy in use is First Come First Served. @item You can write your own policies. For more information see @ref{Writing new policies}. @end itemize - @c % -------------------------------------------------- @node Installation, Basics, Overview of SGPEM, Top @@ -211,7 +217,7 @@ For more information see @ref{Writing new policies}. * Prerequisites:: Programs and libraries needed to compile and run SGPEM -* Building:: Help for compiling SGPEM on +* Building:: Help for compiling SGPEM on your platform. @end menu @@ -232,32 +238,22 @@ And if you find this section misses something / it lists the wrong version of a program, please let us know! @c % ---- new subsection -@subsection Developers +@subsection Runtime dependencies -Other than the tools needed by users building from sources, -you'll need: +To run SGPEMv2, you require: @table @emph -@item GCC with C++ support -as well as the other standard GNU binutils and tools: make, sed, ld... -GCC version >=3.4 is highly recommended. Please don't report -compiling-related problems with any previous version. -@item Automake >= 1.9 -We use a single @file{Makefile.am} to avoid -recursive make. Older versions of automake didn't play right -with it. See @url{http://aegis.sourceforge.net/auug97.pdf} for -the motivations that led to this choice. +@item Gtkmm >= 2.8 with Cairo support +The popular C++ jacket for the even-more popular GIMP +ToolKit. We use Cairo to draw our custom widgets. -@item Autoconf, libtool, autopoint @dots{} -The standard autotool family. +@item Python >= 2.3 +We use Python to let the user write her own policies +in a simple and complete language. -@item Subversion >= 1.2 -If you need to update the sources from our repository, or commit -your changes, you'll need Subversion built with SSL support. - -@item Dejagnu >= 1.4 -The testsuite framework we use as a platform for running tests. +@item libXML2 >= 2.6.10 +An XML library we use to save and load files to/from disk. @end table @@ -275,23 +271,36 @@ Python can use, starting from a simple interface specification. @end table @c % ---- new subsection -@subsection Runtime dependencies +@subsection Developers -To run SGPEMv2, you require: +Other than the tools needed by users building from sources, +you'll need: @table @emph +@item GCC with C++ support +as well as the other standard GNU binutils and tools: make, sed, ld... +GCC version >=3.4 is highly recommended. Please don't report +compiling-related problems with any previous version. There are some +known issues with certain versions of GCC 4.0. @xref{Building}. -@item Gtkmm >= 2.8 with Cairo support -The popular C++ jacket for the even-more popular GIMP -ToolKit. We use Cairo to draw our custom widgets. +@item Automake >= 1.9 +We use a single @file{Makefile.am} to avoid +recursive make. Older versions of automake didn't play right +with it. See @url{http://aegis.sourceforge.net/@/auug97.pdf} for +the motivations that led to this choice. -@item Python >= 2.3 -We use Python to let the user write her own policies -in a simple and complete language. +@item Autoconf, libtool, autopoint @dots{} +The standard autotool family. + +@item Subversion >= 1.2 +If you need to update the sources from our repository, or commit +your changes, you'll need Subversion built with SSL support. + +@item Dejagnu >= 1.4 +The testsuite framework we use as a platform for running tests. @end table - @c % -------------------------------------------------- @node Building, (none), Prerequisites, Installation @@ -300,49 +309,70 @@ in a simple and complete language. @noindent To ensure a clean build, follow these steps: +@sp 1 @example -@code{cd } +@code{cd } @code{mkdir =build} @code{cd =build} @code{CXXFLAGS="what you want" ../configure --prefix=/usr/local} @end example -@sp 2 +@sp 1 @noindent This will check you have all the needed software installed. -@noindent Choosing good @env{CXXFLAGS} to optimize your build. +@noindent Choose good @env{CXXFLAGS} to optimize your build. For example, on my machine, I would use: + +@sp 1 @example @code{CXXFLAGS="-O3 -pipe -march=pentium4" ../configure --prefix=/usr/local} @end example -@sp 2 +@sp 1 -@noindent Being a developer, though, if I had to debug SGPEM, I would type: +@noindent Being a developer, though, if I had to debug SGPEM, I would +type: + +@sp 1 @example -@code{CXXFLAGS="-O0 -g -ggdb -pg" ../configure \} -@code{ --prefix=`pwd`/_inst} +@code{../configure --prefix=`pwd`/../=inst --enable-debug} @end example -@sp 2 +@sp 1 + +@noindent Please note that those around ``pwd'' are backticks, and not +normal apostrophes. @strong{Warning}: at the moment, we are aware that passing @option{--disable-shared} to configure doesn't work. We'll look into it sooner or later, but in the meantime just build shared libraries. @noindent Once succesfully configured SGPEMv2, just type: + +@sp 1 @example @command{make} @end example -@sp 2 +@sp 1 -@noindent And upon a succesful build, you can install it just by: +@noindent Some versions of GCC 4, usually those before the 4.1 series, +present some problems with the newly-added visibility support for DSO +object symbols. For example, OpenSuSE 10.0 is known to have such +issues. If you encounter problems during building and in linking stage +about unresolved symbols in libraries, please re-run +@command{configure} with the @option{--disable-visibility-support} +option. You'll then have to run @command{make clean && make}. + + +@noindent Upon a succesful build, you can install SGPEMv2 just by hitting: + +@sp 1 @example @code{su -c "make install"} @end example -@sp 2 +@sp 1 @noindent Root password will be required (of course, if you're installing it with a prefix placed inside your home directory, -you won't need administrative rights, and just ``@samp{make install}'' +you won't need administrative rights, and just ``@command{make install}'' will sufficit). See the ``@file{INSTALL}'' file in this folder for an overview of other @@ -353,10 +383,11 @@ See the ``@file{INSTALL}'' file in this folder for an overview of other We added Doxygen support to the project. If you've installed it, you can simply run @command{make apidox} from the package top source directory. The documentation will be outputted into -the @samp{$@{BUILD_DIR@}/docs/API/} directory. +the @samp{$@{BUILD_DIR@}/docs/API/} dir. If you'd like to generate nicier inheritance graphs, you've just to -install @command{dot}, part of the @emph{Graphviz} package. +install @command{dot}, part of the @emph{Graphviz} package. If you +didn't have it previously installed, you may need to re-run @command{configure}. @c % -------------------------------------------------- @@ -548,8 +579,6 @@ Each schedulable entity is represented by its name followed by its priority encl @c % ------------------------------------------------ -@c % ------------------------------------------------- - @node Extending SGPEM, License, Using SGPEM, Top @chapter Extending SGPEM @cindex extending @@ -561,16 +590,30 @@ Each schedulable entity is represented by its name followed by its priority encl @end menu +@c % ------------------------------------------------- + @node Writing new policies, Writing plugins, Extending SGPEM, Extending SGPEM @section Writing new policies @cindex writing policies -All policies are implemented in Python, but don't worry (be happy!). You don't have to be a Python expert to write a new policy. -We'll explain you how to write a new policy on an simple example of FCFS policy. Now let's start, all you have to do is change the few bold-ed lines, of the following example. -@sp 1 +All built-in policies are implemented in Python, but don't worry: you +don't have to be a Python expert to write a new policy. We'll explain +you how to write a new policy on an simple example of FCFS +policy. Then a more complex example will follow: a Round Robin policy +that uses pre-emption by priority. + +Now let's get started, all you have to do to create your own policy is +to change the few bold lines of the following example. Also remember +that the name of the class have to be the same of the name of the file +(minus the @code{.py} file extension, of course). + + + +@c % --------- new subsection +@subsection A beginner example: First Come First Served @example -01 from Policy import Policy +01 from CPUPolicy import CPUPolicy 02 class fcfs(Policy) : 03 def __init__(self): 04 pass; @@ -586,48 +629,220 @@ We'll explain you how to write a new policy on an simple example of FCFS policy. 11 def sort_queue(self, event, queue): @strong{12 cmpf = lambda a, b: \ - a.get_schedulable().get_arrival_time() < \ + a.get_schedulable().get_arrival_time() <= \ b.get_schedulable().get_arrival_time() 13 self.sort(queue,cmpf)} @end example @sp 2 -@itemize -@item body of @code{def configure(self):} line 06 - Configure policy to initial values. -This is called just before a simulation starts, and is responsible to define +@table @asis +@item body of @code{def configure(self)}: line 06 + +Configure policy to initial values. This is called just before a +simulation starts, and it is responsible to define the parameters the policy wants to expose to the user. For example, it may make -the return value of is_preemptive configurable, or register an integer value for -a the time slice duration. -@sp 1 -@item body of @code{def is_preemptive(self):} line 08 - It says whether the policy wants to be preemptive, other than by normal time slice termination. +the return value returned by @code{is_preemptive()} configurable, or +to register an integer value for a the time slice duration. + +@item body of @code{def is_preemptive(self):} line 08 + +It says whether the policy wants to be preemptive, other than by +normal time slice termination (if a positive time slice has been provided). The possible return values are: - @enumerate -@item True -If the policy declares it wants the running process to be released if a process at higher priority is put at the beginning of the ready processes queue +@enumerate + +@item +@code{True}: If the policy returns True, it declares that it wants the running +thread to be released if a thread at higher priority is put at the +beginning of the ready threads queue. + +This is achieved by putting the current running thread, if there is +one, onto the ready queue. It is up to you, into the +@code{sort_queue()} method, to manage this special case. + +@item +@code{False}: The policy always waits the end of the time slice (or a thread +blocking/termination) before selecting a new running thread, even if it +has greater priority than the current one. + +There will never be a running thread in the ready queue passed to +@code{sort_queue()}. -@item False -If the policy always waits the end of the time slice (or a process blocking/termination, of course) before selecting a new running process, even if it has greater priority than the current one. @end enumerate -Please note how the word ``priority'' here has a general meaning: it indicates every process than +Please note how the word ``priority'' here has a general meaning: it indicates every thread than can bubble up the sorted ready queue and come before another. So it's up to Policy.sort_queue() to give it a precise meaning. @sp 1 -@item body of @code{def get_time_slice(self):} line 10 - Returns how long is a time-slice for this policy. -A time sliced policy should return a positive integer value, a policy which doesn't use slices should instead -return -1. You're encouraged to use a user-configurable parameter via Policy.configure() if the policy is +@item body of @code{def get_time_slice(self):} line 10 + +Returns how long is a time-slice for this policy. +A time sliced policy should return a positive integer value, a policy +which doesn't use slices should instead +return @code{-1}. You're encouraged to use a user-configurable +parameter via @code{Policy.configure()} if the policy is time-sliced, to ensure greater flexibility. + @sp 1 -@item body of -@code{ def sort_queue(self, event, queue):} -line 12,13 - Sort ready processes queue. -This method is called by the scheduler at each step of the simulation to sort the ready processes queue. +@item body of @code{ def sort_queue(self, event, queue):} line 12,13 -@end itemize +Sort the queue of ready threads. This method is called by the +scheduler at each step of the simulation to sort the ready threads +queue. It is the core of your policy: when scheduler has to select +a new thread it will always try to take the first of the queue. If it +cannot run for some reason (for example, it immediately blocks), the +second is selected and so on, until the end of the queue. +Remember that if @code{is_preemptible()} returns True, you may have +a running thread in the queue. See the following example for some tips +about how to manage this case. + +Pay attention to the fact that we used the @code{<=} relation at line @samp{12}, and +not a simple @code{<}. This is because @code{queue.sort()} uses a +in-place implementation of quicksort, which is stable only when +employed with a minor-or-equal relation. Otherwise the queue would be +sorted, but two adjacent threads that have the same value for a given +priority would be swapped. If your policy behaves strangely, this may +be the cause. + +@end table + +@c % --------- new subsection +@subsection Exposed interface: what you can use + +@anchor{Configuring parameters} +@subsubsection Configuring parameters + +TODO: list and describe all methods exposed from PolicyParameters. + +@subsubsection Methods for manipulating the ready queue + +TODO: list and describe all methods exposed from ReadyQueue. + +@subsubsection Properties of schedulable entities + +TODO: list and describe all methods exposed from Schedulable, +Thread and Process + + +@c % --------- new subsection +@subsection A more complete example: Round Robin with priority + +Now, let's see a more interesting (and a little more complex) example: +a Round Robin by priority policy that can optionally also work with +pre-emption by priority. + +@sp 2 +@example +00 from CPUPolicy import CPUPolicy +01 +02 class rr_priority(CPUPolicy) : +03 """Round Robin scheduling policy that takes priority in account. +04 +05 No lower priority thread can run if a higher +06 priority thread exists. If pre-emptive by priority, a +07 higher-priority thread becoming ready even in the middle +08 of a time slice will pre-empt the running thread. Else, +09 the time slice will have to end before the former can run.""" +10 +11 def __init__(self): +12 pass; +13 +14 def configure(self): +15 param = self.get_parameters() +16 param.register_int("Time slice", 1, 10000, True, 2) +17 param.register_int("Is preemptive?", 0, 1, True, 1) +18 +19 def is_preemptive(self): +20 value = self.get_parameters().get_int("Is preemptive?") +21 if value == 0: +22 return False +23 else: +24 return True +25 +26 def get_time_slice(self): +27 return self.get_parameters().get_int("Time slice") +28 +29 def sort_queue(self, queue): +30 by_ltime = lambda a, b: \ +31 a.get_last_acquisition() <= \ +32 b.get_last_acquisition() +33 by_prio = lambda a, b: \ +34 a.get_current_priority() <= \ +35 b.get_current_priority() +36 +37 self.sort(queue,by_ltime) +38 self.sort(queue,by_prio) +39 +40 # manage preemption: see if we've a running thread +41 # in the ready queue, and if it can still run +42 if self.is_preemptive() == True: +43 higher_prio = queue.get_item_at(0).get_current_priority() +44 i = 0 +45 while i < queue.size(): +46 sched = queue.get_item_at(i) +47 priority = sched.get_current_priority() +48 if(priority != higher_prio): +49 break +50 if sched.get_state() == "running": +51 queue.bubble_to_front(i) +52 i += 1 +@end example + +We've also added a description of the class immediately +following the class declaration (lines @samp{03-09}). This is what is +returned as the policy description in the frontend. You may want to +document your policies in the same way too. + +Now, let's see the most complex parts together: + +@table @code +@item configure() + +There are three types of parameters you can register in the value +returned by @code{self.get_parameters()}, and they are integer +parameters, float parameters and strings. Usually boolean values can +be simulated by registering a integer parameter limited in the +interval [0, 1]. @xref{Configuring parameters} for the exposed interface. + +@item is_preemptive() + +TODO: write me + +@item sort_queue() + +Here there are quite a lot of things going on, so let's tackle them +one by one. + +At line @samp{30} we create a lambda-function that says to sort the queue +by last aquisition time, so that threads that have been aquired +recently end up at the back of the queue (which is exactly what a +Round Robin policy should do). + +Then, at line @samp{33}, we create another lambda-function, this time +because we want to sort the queue by priority, too. + +Done this, we let quicksort do the hard job at lines @samp{37-38}. + +Since we may have pre-emption enabled, we may have a running thread on +the ready queue (if one exists at the current instant). But what +happens if the running thread was put in the queue, and we just sorted it? + +Unfortunately, having the greatest last aquisition time, the running thread would end +at the back of the queue, thus never being selected to run for more +than a single time unit if the queue is non-empty and there are other +threads with the same priority! + +The solution is to check if there is a thread with state ``running'' +at the beginning of the queue, between those that have the same +priority. If there's one, we make it bubble to the top of the queue. + +This is the explanation for lines @samp{42-52}. + +@end table @c % ------------------------------------------------- @@ -636,6 +851,7 @@ This method is called by the scheduler at each step of the simulation to sort th @section Writing plugins @cindex plugins +TODO: write me @c % ------------------------------------------------- @c include license text