Resource containers and LRP
Department of Computer Science
Rice University
This code implements Resource containers along with Lazy Receiver Processing
(LRP). Resource containers [2,3]
are an operating system abstraction for resource principals distinct from the
notion of a protection domain. They enable fine-grained resource management in
operating systems. LRP [2,4] is a
network subsystem architecture that integrates network processing with resource
management in an operating system. The resources spent in network processing
are correctly accounted to the resource principal on whose behalf this
processing is performed.
Both Resource containers and LRP were originally implemented in
Digital UNIX by Gaurav Banga in
the context of the ScalaServer project.
This code was developed from ground up for the FreeBSD operating system by the
author in context of a project
on resource management in cluster-based servers
[1] under the direction of
Prof. Peter
Druschel and Prof. Willy
Zwaenepoel at the Department of Computer Science, Rice University.
This document briefly describes the overall design and layout of the code as
well as how to compile, install and run it. It does not comprehensively
describe all the code details and is only intended to be a guide to help give a
quick start to a knowledgeable Systems person. Implementation details have to
be gathered by reading the code. This document further assumes that the reader
is familiar with the publications [2],
[3], [4] and
[5].
Resource containers replace processes in FreeBSD as the resource principals.
Consumption of resources is charged to Resource containers rather than
processes (FreeBSD does not support kernel threads). Similarly, scheduling of
resources happens between Resource containers rather than processes.
Resource containers are arranged hierarchically in a tree-like data structure
for the purpose of scheduling. Each node in this tree is a Resource container
and the tree is headed by a special root Resource container. Any
internal node in the tree is different from the leaf nodes in that each
internal node runs a scheduler for multiplexing resources to its children
Resource containers. Different scheduling algorithms might be used by distinct
internal nodes. Processes are associated (or resource bound ) only
to leaf containers and these containers only serve to pass the resources handed
to them by their parent containers to the associated processes.
To facilitate the development and debugging of the code, Resource
containers are implemented in a loadable kernel module. This module is
designed to replace the process-centric resource management in FreeBSD with
Resource containers once the module is loaded. Unloading the module restores
the FreeBSD resource management.
Once the Resource container kernel module is loaded, a set of system calls
(described in detail in [2]) become available to
applications for the purpose of using Resource containers. A brief description
of these system calls is provided later in this
document. However, the code is designed such that existing applications do not
have to be modified; that is, it is not necessary for an application to use the
system calls provided with Resource containers.
The Resource container code starts by resource binding every application
process in the system to a distinct leaf container that is made a child of
the root container. Therefore, upon immediately loading the module, the
scheduling algorithm at the root Resource container determines the
manner in which resources are multiplexed between processes. Application
processes can then use the Resource container system calls to add more
complexity to the hierarchy. The Resource containers are kept transparent
to existing applications by automatically managing the resource binding of
new processes so as to maintain the usual UNIX semantics. A newly created
process is resource bound to a new leaf container that becomes a sibling of the
leaf container associated to the process's parent.
In order to support event driven processes/threads that perform processing on
behalf of several Resource containers, the code also supports the concept of a
scheduler binding [3]. A process/thread can
scheduler bind itself to multiple Resource containers. The process/thread then
becomes eligible to receive resources allocated to any of these
containers. However, processing performed by the process/thread is accounted
towards the unique Resource container to which it is resource bound.
LRP is also implemented in a separate loadable kernel module and serves to
correctly account for network processing. As for processes, network sockets are
also resource bound to Resource containers (a network socket is bound to the
same leaf container as the process that created it). Early demultiplexing is
performed on network packets to identify the network sockets to which they
belong. The packets are then placed in socket specific queues and further
processing is performed according to the scheduling priority of the Resource
container that is associated with the network socket. All network processing
is actually performed by a special process that is started during LRP
initialization and remains kernel resident for as long as the LRP module is
loaded. When network processing is to be performed for some socket, this
special process first resource binds itself to the socket's associated
container and then performs network processing for that socket. Due to its
resource binding, the resource usage is charged to the correct container.
To facilitate debugging, the LRP module implements a complete network stack
rather than requiring obtrusive changes to the default FreeBSD-4.0 network
stack. This is described in more detail in the next section.
The philosophy behind the design of both the Resource container as well as the
LRP modules was to minimize the changes to the FreeBSD-4.0 kernel and to
implement most of the code in the modules themselves. However, since LRP alters
the network stack, the LRP loadable module installs an additional network stack
in the operating system rather than modifying the existing one. In other
words, once the LRP module is loaded, the operating system runs with two
network stacks. The original stack is used for regular networking services
like telnet, rlogin etc. Any bugs (unless they cause memory violations) in the
new stack thus still keep regular system services running. All it takes to fix
these bugs is to unload the module, recompile the fixed code and load the
module back.
The network stack implemented by the loadable module was derived from the
original FreeBSD-4.0 stack itself. The trick to installing additional network
stacks is to install them as a different protocol family. Application programs
(such as web servers) choose the network stack they want to use by specifying
the protocol family as the first argument to the socket() system call. In
FreeBSD, the protocol family for the regular TCP/IP stack is 2 (specified
with macro PF_INET or AF_INET). For the alternate stack implemented in the
loadable module, this protocol family is chosen to be 21. Therefore, in order
to use a conventional web server (e.g., Apache) with this loadable module,
the first argument of any socket() calls made in the server code should be
changed to 21. (In Apache-1.3.3 source this required a change in the file
src/main/http_main.c).
Once the kernel operates with both the stacks loaded, the next question that
arises is which stack should service an IP packet that is received at a network
interface. The solution to this is of necessity ad hoc, as both network
stacks are equally capable of handling all IP packets. The packet is first
presented to the stack in the loadable module. This stack quickly makes a
decision on whether it wants the packet or not - if not, then the packet is
sent up the original stack. Under this implementation, all packets containing a
source IP address of the form 192.x.x.x and arriving on any of the fxp0-fxp4
interfaces are accepted by the stack in the loadable module. However, packets
from source 192.168.2.75 and packets from all other sources are sent up the
original stack (192.168.2.75 was the IP address of our development machine and
we wanted to use the regular stack for this address for ftp'ing the compiled
code over to the experimental machine). This part of the code is implemented in
LRP/netsys.c and should be modified as necessary.
This section provides a brief description of most of the files and
directories included in this release.
- build/: The code is compiled in this
directory. After compilation, this directory contains the files that
should be copied over to the experimental machine on which the code
is to be run. These are a Makefile, the Resource container
loadable module object file rc_mod.o, the LRP loadable module
object file netsys_mod.o, and an executable
LRP_startup that starts the special process in the context of
which all network processing is performed in LRP.
- kpatch/sys/: This directory contains a set of
modified files in the FreeBSD-4.0 kernel code. These files
are necessary for the loadable kernel modules to interact with the
kernel. If the kernel source is present in /sys, then file
kpatch/sys/X/Y should replace file /sys/X/Y in the
kernel code. To quickly update the kernel source in /sys, the
command ' cp -r kpatch/sys /' can be used. Some of the
files relative to this directory are described next. Others contain
minor changes for supporting the code in the loadable kernel modules.
All the files relative to this directory are derived from
corresponding files in the FreeBSD-4.0 kernel source.
- i386/conf/LUZERN: The kernel configuration file using
which we compiled our kernel. This should be modified as necessary
to suit a different hardware configuration than that on which this
code was tested.
- i386/i386/swtch.s: Modified to do CPU scheduling based on
Resource containers if the corresponding module is loaded.
- i386/i386/vm_machdep.c: Modified to report termination
of processes to the Resource container code.
Resource containers if the corresponding module is loaded.
- net/if_ethersubr.c, net/if_loop.c: Modified to add hooks
in the kernel to enable the use of the alternate network stack in the
LRP loadable module.
- kern/kern_switch.c: Modified to report a process that
becomes runnable to the Resource container code.
- kern/kern_synch.c: Modified to report blocked processes
to the Resource container code. Also contains the basic code
executed by the special process that does LRP network processing.
Finally, adds an optimization that makes context switches to happen
on every hardclock interrupt rather than every 100ms
(see Caveats).
- kern/kern_timeout.c: Modified to raise the flag that
indicates the end of a quantum at high priority. Otherwise, LRP
processing for some Resource container might incorrectly continue
well past its quantum.
- kern/uipc_socket.c: Modifies socket initialization and
termination code to support Resource containers and LRP.
- kern/uipc_socket2.c: Modified to associate a new socket
after an accept system call to the same Resource container as the
corresponding listen socket.
- sys/proc.h: Modified to extend the proc data
structure to support additional fields needed by Resource container
and LRP code. Extending the proc data structure needs recompilation
of some Unix utilities like top and ps that
operate by reading the proc data structure from kernel memory (see
Caveats).
- sys/socketvar.h: Modified to extend the socket data
structure to support additional fields needed by Resource container
and LRP code. Also adds an optimization that increases the maximum
length of socket buffers from 256 KB to 512 KB.
- kopt/sys/: This directory contains another set of
modified files in the FreeBSD-4.0 kernel code. These files only
optimize the kernel for better performance and are not necessary
for supporting the Resource container and the LRP implementations.
As for the files in the kpatch directory, the kernel source in /sys
can be quickly updated with these optimizations using the command
' cp -r kopt/sys /'. Many of these optimizations have been
posted by the author on the FreeBSD mailing list on networking
issues.
- RC/: This directory contains the source for loadable kernel
module that implements Resource containers. The files in this
directory are briefly described next.
- ownsyscall.c: Contains the boiler-plate code for the
Resource container loadable kernel module.
- rc.c, rc.h : The principal files that implement the
Resource container code.
- leaf_sched.c : Implements the code for a leaf container
in the Resource container hierarchy.
- lottery_sched.c : Implements the
lottery scheduling algorithm for CPU scheduling within an
internal node in the Resource container hierarchy.
- hash.c, hash.h : Implement a generic hash function
from the Compiler book by Aho, Ullman, Sethi.
- utils.c : Implements some routines for debugging
the Resource container implementation.
- LRP/: This directory contains the source for the loadable
kernel module that implements LRP. Most of this source was derived
from the source for the network stack found in a regular
FreeBSD-4.0 kernel in the directory /sys/netinet. The files
in this directory are briefly described next.
- netsys.c, netsys.h : Contain (1) boiler-plate code
for the LRP loadable kernel module, (2) code to initialize
a new protocol family in the kernel when module is loaded,
(3) the function sched_softintr() in netsys.c that inspects
every IP packet received on any network interface to decide
whether it is to be sent up the original network stack or
the stack in the loadable module, and (4) support for early
demultiplexing of network packets for LRP.
- Most other files are copies of the corresponding files from the
kernel source in /sys/netinet. Most are unchanged or slightly
changed to either incorporate them in the alternate network
stack or to support LRP.
- test/: This directory contains the source for some simple
test programs that use Resource containers. These programs are
briefly described now.
- auxprog1.c : Creates an internal Resource container,
names it RC1, makes it a child of the root container, and then
goes to sleep. The purpose of this program is mainly to hold
a reference to container RC1 (see Caveats
). This program also takes an argument that specifies
the CPU reservation for RC1. If no argument is given,
a default reservation of 40% is made.
- prog1.c : This program makes the leaf container for
the current process a child of RC1 created by auxprog1.c.
In addition, a reservation is made on the leaf container
as specified by an argument to prog1. By default a value of
10% is assumed.
- prog2.c : This program assigns a reservation
to the leaf container associated with the current process.
An argument specifies this reservation (default is 10%).
As prog2 is forked by the shell, the parent of its leaf
container shall be the root container.
Handles to Resource containers are made available to user-applications
in their file descriptor space (same as for sockets). Therefore, all the
FreeBSD system calls that can be used on descriptors for files and sockets
can also be used for descriptors for Resource containers. However, most of
these will return an error when applied to a Resource container descriptor
with the errno set to EINVAL. In addition, a set of new system calls have
been provided for Resource containers. Any application that uses these system
calls must include the file RC/rc.h before compilation. We now briefly
describe the set of system calls that can used on Resource container
descriptors. Unless otherwise mentioned, all calls return a 0 on success and
a -1 on failure.
- int rc_create(int sched_type) : Creates a new Resource container
in the kernel and returns a descriptor to it. The argument sched_type
can be SCHED_LEAF for creating a leaf container, or
SCHED_LOTTERY for creating an internal container that uses
lottery scheduling for multiplexing resources. The container created
by this system call is not attached in the Resource container hierarchy.
- int get_root_rc() : Returns a descriptor associated with the
root container in the the Resource container hierarchy.
- int set_rc_parent(int rcd1, int rcd2) : Makes the container
corresponding to rcd2 the parent of the container corresponding
to rcd1.
- int get_rc() : Returns a descriptor corresponding to the container
to which the current process is resource bound to.
- int set_fd_rc(int sockfd, int rcd) : Resource binds the socket
corresponding to descriptor sockfd to the Resource container
corresponding to descriptor rcd . Network processing
performed for the socket shall henceforth be charged to the
container corresponding to rcd . Sockets should only be
resource bound to leaf containers.
- int rc_attach_name(int rcd, char *name, int len) : Associates
a name specified by argument name with the container
corresponding to descriptor rcd. The argument len
gives the number of characters in name.
- int get_rc_byname(char *name, int len) : Returns a descriptor
corresponding to an existing Resource container that has a name attached
to it given by argument name . The argument len
gives the number of characters in name.
- int set_res_binding(int rcd) : Resource binds the current process
to the container corresponding to the descriptor rcd .
Processes should only be resource bound to leaf containers.
- int add_to_sched_binding(int rcd) : Adds the current process to
the scheduler binding of the Resource container corresponding to
descriptor rcd .
- int delete_from_sched_binding(int rcd) : Removes the current
process from the scheduler binding of the Resource container corresponding
to descriptor rcd .
- int get_rc_opt(int rcd, struct rcopt *rco) : Resource containers
support attributes that can be queried and set using the get_rc_opt() and
set_rc_opt() system calls. The get_rc_opt() system call gets the value
of the attributes specified by argument rco for the container
corresponding to rcd . The type definition for rcopt
data structure is defined in RC/rc.h and contains two fields (1)
attr_type (2) attr_val. The attribute to be
fetched is specified using attr_type while the variable
attr_val contains the value of the attribute after
the system call returns. For example, all Resource containers maintain
an attribute RCOPT_PCTCPU that
maintains the percentage CPU utilization for that container. This value
is maintained as a scaled integer. The actual percentage value can be
obtained by multiplying the value with the fraction 100/2048
(actually 100/FSCALE).
- int set_rc_opt(int rcd, struct rcopt *rco) : Sets the value
given in rco->attr_val for the attribute specified by
rco->attr_type belonging to the Resource container corresponding
to the descriptor rcd . Resources can be reserved for a
Resource container with an attribute RCOPT_SCHED_CPU_RESERVE
that specifies the proportional CPU reservation of this container with
respect to its siblings.
- int close(int rcd) : Decrements the reference count on the
Resource container associated to the descriptor rcd. If the reference
count becomes zero, the corresponding data structure in the kernel is
freed.
Download the source from the URL given at the beginning of this document.
Unzip and untar the tarball.
- Kernel compilation and installation:
Let the kernel source be present in /sys. Replace files in
the kernel source with the corresponding files from
kpatch/sys (and optionally from kopt/sys). The file
/sys/i386/config/LUZERN will be the kernel configuration file. This
file might need to be modified to adapt to a different hardware
configuration than on which this code was tested.
Execute the following series of commands to compile the kernel:
- cd /sys/i386/conf
- config LUZERN
- cd /sys/compile/LUZERN
- Modify param.c to increase HZ from 100 to 1000 (see
Caveats).
- make depend
- make
This should prepare the kernel binary /sys/compile/LUZERN/kernel.
Install this as /kernel on the experimental machine. Upon rebooting
the machine, it should be running the compiled kernel.
- Compilation and installation of the loadable modules:
Change directory to the root of the directory where the source was
installed after downloading. Execute the following series of commands
to compile the module and related programs:
- cd build
- make build
The build directory should now contain the four files
that are to be copied over to the experimental machine that is
to run the code. These are: (1) Makefile (2) rc_mod.o (3)
netsys_mod.o (4) LRP_startup.
- Application compilation and installation :
As mentioned earlier, Resource containers are transparent to
existing FreeBSD applications. Most binary executables can therefore
be run unmodified. Some applications (like top and
ps ) need to be recompiled as they read the proc structure
from kernel's memory. Applications that need to take advantage of
the Resource container hierarchy can use the Resource container
system calls.
As LRP is implemented only for the network stack in the LRP loadable
module, applications that use networking must use that stack in order
to benefit from LRP. The source for such applications remains
unmodified with one exception. Since we want the application to use
the network stack in the loadable module, the first argument to any
socket() call in the source code for the application should be
changed to 21. Other than this, the compilation and installation on
the experimental machine should be done as per the instruction manual
for the application. An example application is the Apache webserver.
Follow the following steps for testing the system.
- Reboot experimental machine : Reboot the experimental
machine such that it runs the modified kernel from the
Compiling and Installing section.
- Load kernel modules : On the experimental machine, go to
directory where the four files from the build directory were
copied. Execute 'make load' in this directory with super-user
privileges. This loads the Resource container and LRP kernel
modules (installing the second network stack in the kernel).
In addition, it also starts LRP_startup. If only Resource container
support is desired, execute 'make RC' rather than 'make load'.
- Start applications : Start any applications. As mentioned
earlier, networking applications can only use LRP if they have been
compiled to use the network stack in the LRP loadable module.
For terminating the setup, execute the following step:
- Unload the modules by executing the command 'make unload'.
Running programs in test directory : Once the Resource containers and
LRP modules are loaded, the sample programs in the test directory can be run.
They can be compiled by executing the 'make' command in the test directory. The
executables should be copied over to the experimental machine. Here is an
example execution:
- auxprog1 40 &
Creates RC1, attaches it to root container, sets reservation of 40% on it
and goes to sleep.
- prog1 10 &
Makes leaf container of prog1 a child of RC1 and gives it a reservation of
10%. As prog1 is the only active process on CPU, the 'top' command will
show 100% of the CPU resources allocated to prog1.
- prog1 20 &
Attaches another prog1 container to RC1 but assigns a 20% reservation to
it. The two active prog1 processes would get CPU resources in the
proportion 1:2 now.
- prog2 40 &
Assigns reservation of 40% to leaf container of prog2 that is a child
of the root container. As a result, the root container will distribute
resources between RC1 and container of prog2 in the ration 1:1 (that is
prog2 shall get 50% CPU resources). The 50% resources of RC1 shall be
divided in the ratio 1:2 between the two active prog1
processes. Therefore, these will get 16% and 32% of the CPU resources.
- Note that it takes a while before the values of CPU utilizations
reported by 'top' stabilize to the above values.
This is because, the past CPU usage is decayed with a
factor of 0.95 in FreeBSD - this means that it takes about 45 seconds
to forget 90% of the past usage. For terminating the sample programs,
all instances of prog1 should be killed before auxprog1
(see Caveats).
- Although developed for that project, this code release does not
implement Cluster Reserves
[1] that support global resource
management in cluster-based servers.
- The Resource container module is independent of the LRP module.
Therefore, it is possible to only load the Resource container module
and not load the LRP module. This will still enable Resource
containers to be used for managing the system's resources. However,
without LRP, network processing would not be correctly accounted to
the correct Resource container.
- The LRP implementation assumes that Resource containers are used
in the operating system as resource principals. Therefore, the LRP
loadable kernel module should only be loaded after loading the
module implementing Resource containers. Similarly, it should be
unloaded before unloading the Resource containers module.
- The Resource containers implemented in this code only control the
accounting and allocation of the CPU resource. Other resources like
memory pages, disk/network bandwidth are handled as in the vanilla
FreeBSD-4.0 operating system.
- No security features are implemented for Resource containers in this
code. In other words, any user application can assign any CPU
reservation to any Resource container. Therefore, a malicious
process can potentially get a high CPU share by creating a
Resource container, assigning a large CPU proportion to it,
making it a child of the root Resource container, and making its own
container the child of this new container.
- This code frees Resource containers using a reference counting
scheme. A reference count is maintained with each Resource container
and equals the sum total of all the threads that resource bind to the
container and all the file descriptors to the container held by
threads [2,3]. Once this
reference count reaches zero, the container is destroyed.
There is a problem with this scheme in that the children containers
and sockets bound to a container do not contribute to this
reference count. Therefore, as soon as the reference count to a
container goes to zero, any children containers and threads/sockets
that are resource
bound to them are left dangling in the system. This is specially
disruptive for TCP sockets that usually keep alive in the
TIME_WAIT state even after a process handling the corresponding
network connection dies (destroying its container in doing so).
Therefore, the following care should be taken while using this code:
- A file descriptor for a non-leaf container (other than the root
container) should be kept open in at least one process until
all its children containers and their associated sockets have
been freed.
- Any process should only be stopped at least one minute
(TIME_WAIT period) after it has closed all its TCP
connections.
- This code provides only the lottery scheduling algorithm [5] for multiplexing CPU resources. Therefore, this
algorithm has to be used at each internal node in the Resouce
container hierarchy. However, other scheduling algorithms can also be
implemented. We suggest using the file RC/lottery_scheduling.c
as a starting point for this purpose as it contains much of the
boiler-plate code.
- FreeBSD uses a priority-based scheme for scheduling processes.
Important processing in the kernel is assigned high priority (lower
in value that a macro PUSER) while user processes usually are
assigned low priority (higher in value than PUSER). It is important
to respect the high priorities for correct execution. To support
this, whenever a process becomes runnable, or has a change in its
priority (as assigned by FreeBSD), this is communicated to its
associated leaf container and the ancestors higher up on the
Resource container hierarchy. This enables the scheduling algorithms
at the internal nodes in the hierarchy to schedule based on
FreeBSD kernel priorities. The lottery scheduling implementation
only does lottery scheduling if none of the child containers have
a priority less than PUSER in value; otherwise scheduling is done
based on a strict priority based scheme.
- Lottery scheduling works by assigning resources in proportion to the
number of tickets held by a principal. Due to the probabilistic
nature of lottery scheduling, desired proportions are only realized
over large number of CPU quantums. By default, FreeBSD uses 100ms
quantums that can result in long times before the desired
proportional allocation is observed. To fix this problem, the code
in kpatch/sys/kern/kern_sync.c has been modified to force context
switches on every hardclock interrupt, rather than every 100ms.
It is further recommended to increase the hardclock interrupt
frequency from 100 Hz to 1000 Hz. This can be done by defining
the variable HZ appropriately in the file param.c in the
directory where the kernel is compiled (this file is created after
configuring the kernel by running the config command).
- The lottery scheduling implementation distinguishes children
containers into two classes - reserved and best effort. Any
child whose attribute RCOPT_SCHED_CPU_RESERVE is set
with a positive value has a percentage CPU reservation of that
value. This percentage is specified relative to the total resources
allocated to its parent (rather than an absolute CPU reservation).
After all reserved resources have been allocated by the parent,
any residual resources allocated to the parent
are allocated equally between the best-effort
children ( RCOPT_SCHED_CPU_RESERVE is 0 for these).
If there are no best-effort children, or if the sum total of
all child reservations exceeds 100, resources are distributed
among children in proportion to their reservations (rather than
equal to their reservation).
- While most FreeBSD executables remain transparent to the modified
kernel and the code in the loadable modules, some applications
like top and ps need to be recompiled as they
read data structures from the kernel's memory. However, no source
code changes are required in these applications. Applications that
read kernel's memory use a library libkvm. This library
needs to be recompiled and relinked with applications such as
top and ps . The source for this library is
located in directory lib/libkvm relative to the full FreeBSD source
(usually located in /usr/src). After files in kpatch/sys have been
copied over to the kernel sources, executing a 'make' in
/usr/src/lib/libkvm shall recompile the library. top and
ps can be subsequently recompiled by executing a 'make'
in /usr/src/usr.bin/top and /usr/src/bin/ps respectively.
- The LRP code does not send any TCP RST packets in response to SYN
packets bound for ports on which no process is listening. The SYN
packets are simply discarded.
- Support for scheduler binding in the Resource container code has not
been thoroughly tested.
- This is an alpha release. The code might be unstable under various
experimental conditions and might result in system crashes.
-
"Cluster Reserves: A Mechanism for Resource Management
in Cluster-based Network Servers", Mohit Aron, Peter Druschel
and Willy Zwaenepoel. In Proceedings of the ACM
SIGMETRICS Conference on Measurement and Modeling of Computer
Systems , Santa Clara, CA, June 2000.
-
"Operating System Support for Server Applications" , Gaurav Banga,
PhD thesis, Computer Science, Rice University, May 1999.
-
"Resource containers: A new facility for resource management in
server systems" , Gaurav Banga, Jeffrey C. Mogul and Peter
Druschel. In Proceedings of the Third Symposium on Operating
Systems Design and Implementation (OSDI), New Orleans, LA,
February 1999.
-
"Lazy Receiver Processing (LRP): A Network Subsystem Architecture for
Server Systems" , Peter Druschel and Gaurav Banga.
In Proceedings of the Second Symposium on Operating
Systems Design and Implementation (OSDI), Seattle, WA,
October 1996.
-
"Lottery Scheduling: Flexible Proportional-Share Resource Management"
, Carl A. Waldspurger and William E. Weihl.
In Proceedings of the First Symposium on Operating
Systems Design and Implementation (OSDI), Monterey, CA,
November 1994.