A facility is normally used to model
a resource (something a process requests
service from) in a simulated system.
For example, in a model of a computer
system, a CPU and a disk drive might
both be modeled by CSIM facilities.
A simple facility consists of a single
server and a single queue (for processes
waiting to gain access to the server).
Only one process at a time can be using
a server. A multiserver-server facility
contains a single queue and multiple
servers. All of the waiting processes
are placed in the queue until one of
the servers becomes available. A facility
set is an array of simple facilities;
in essence, a facility set consists
of multiple single server facilities,
each with its own queue.
Normally, processes are ordered in a
facility queue by their priority (a
higher priority process is ahead of
a lower priority process). In cases
of ties in priorities, the order is
first-come, first-served (fcfs). An
fcfs facility can be designated as a
synchronous facility. Each synchronous
facility has its own clock with a period
and a phase and all reserve operations
are delayed until the onset of the next
clock cycle. Service disciplines other
than priority order can be established
for a server. These are described in
section 4.11,
"Changing the Service Discipline
at a Facility".
A set of usage and queueing statistics
is automatically maintained for each
facility in a model. The statistics
for all facilities which have been used
are "printed" when either
a report (see
section 19.2, "CSIM Report
Output") or a report_facilities
is executed (see
section 4.4, "Producing Reports"
for details about the reports that are
generated). In addition, there is a
set of inspector functions that can
be used to extract individual statistics
for each facility.
First time users of facilities should
focus on the following four sections,
which explain how to set up facilities,
use (and reserve and release) facilities,
and produce reports. Subsequent sections
describe the more advanced features
of facilities.
A facility
is declared in a CSIM program using
the built-in type FACILITY.
Example:
FACILITY f;
Before a facility can be used, it must
be initialized by calling the facility
function.
Prototype:
FACILITY facility(char*
name)
Example:
f = facility("fac");
A newly created facility is created
with a single server which is "free".
The facility name is used only to identify
the facility in output reports and trace
messages.
Facilities should be declared with global
variables and initialized in the first
process (normally the process named
sim)
prior to the beginning of the simulation
part of the model. Unless changed by
a set_servicefunc
statement (see
section 4.11, "Changing the
Service Disciplines at a Facility"),
the scheduling policy of the facility
will be first-come, first-served (fcfs).
A process typically uses a server for
a specified interval of time.
Prototype:
void use(FACILITY
f, double service_time)
Example:
use(f, exponential(1.0));
If the server at this facility is free
(not being used by another process),
then the process gains exclusive use
of the server and the usage interval
starts immediately. At the end of the
usage interval, the process gives up
use of the server and departs this facility.
Execution continues at the statement
following the use
statement.
If the server at this facility is busy
(is being used by another process),
then the newly arriving process is placed
in a queue of waiting processes; this
queue is ordered by process priority,
with processes of equal priority being
ordered by time of arrival. As each
process completes its usage interval,
the process at the head of the queue
is assigned to the server and its usage
interval starts at that time.
The service discipline at a facility
specifies how processes are given access
to the server. One of several different
service disciplines can be specified
for a facility. Also, another form of
facility has multiple servers. In addition,
it is possible to have an array of facilities
(a facility set). The difference between
a multiserver facility and a facility
set is that a multiserver facility has
one queue for all of the waiting processes,
while a facility set has a separate
queue for each facility in the set.
In some cases, a process will acquire
a server, but will do something other
than enter the usage interval when it
gets the server. The statements for
doing this are reserve (to gain exclusive
use of a server) and release (to relinquish
use of the server acquired in a previous
reserve statement)
Prototypes:
long reserve(FACILITY
f)
void release(FACILITY f)
Examples:
reserve(f);
release(f);
When a process executes a reserve, it
either gets use of the server immediately
(if the server is not busy) or it is
suspended and placed in a queue of processes
waiting to get use of the server. When
it gains access to the server, it executes
the statement following the reserve
statement. The order of processes in
the queue is by process priority, with
processes of equal priority being ordered
by time of arrival. This process priority
service discipline is called fcfs in
CSIM; it (along with fcfs_sy,
see below) is the only service discipline
that can be specified for facilities
where processes do this reserve-release
style of access. If another service
discipline is in force, then the processes
must execute use
statements instead of reserve-release
pairs of statements.
The process releasing a server at a
facility must be the same process as
the one which reserved it. If this is
not the case, then the release_server
statement (see below) must be used.
When a process executes a release,
it gives up use of the server; if there
is at least one process waiting to start
using the server (i.e.,
there is at least one process in the
queue at this facility), the process
at the head of the queue is given access
to the server and that process is then
reactivated and will proceed by executing
the statement following its reserve
statement. No simulation time passes
during execution of a release statement.
Note:
Executing the sequence "reserve(f);
hold(t); release(f);" is equivalent
to executing the statement "use(f,
t);". However, if the usage interval
is specified by a random number function,
then there is a subtle difference between
these, as follows: the randomly derived
interval is determined after gaining
access to the server in the first sequence
and before gaining access to the server
with the use form; thus it is likely
that the intervals in these two examples
will be different. In other words, the
sequence "reserve(f); hold (exponential
(t)); release(f);" will not necessarily
display exactly the same behavior as
executing the statement "use(f,
exponential (t));".
Reports for facilities are most often
produced by calling the report function
which prints reports of all the CSIM
objects. Reports can be produced for
all existing facilities by calling the
report_facilities
function.
Prototype:
void report_facilities(void)
Example:
report_facilities();
The report for a facility, as illustrated
below, includes, for each facility,
the name of the facility, the service
discipline, the average service time,
the utilization, the throughput rate,
the average queue length, the average
response time and the number of completed
service requests.
In some cases, it is necessary to reset
the statistics counters for a specific
facility.
Prototype:
void reset_facility(FACILITY
f)
Example:
reset_facility(f);
Executing this statement does not affect
the state of the facility or its servers.
The "reset" and the reset_facilities
statements each call reset_facility()
for all facilities in the model.
Sometimes, it is necessary for one process
to reserve a facility and then for another
process to release the server obtained
by the first process. In this case,
the first process has to save the index
of the server it obtained, and then
give this server index to the second
process, so that it can specify that
index in the release_server
statement, as follows:
Example:
server_index
= reserve(f) ;
Prototype:
void release_server(FACILITY
f, long
server_index)
Example:
release_server(f,
server_index);
This operates in the same way as the
release statement except that the ownership
of the server is not checked; thus,
a process which did not reserve the
facility may release it by executing
the release_server
statement with a server index.
In some cases, a facility has multiple
servers, and each of these servers is
indistinguishable from the other servers.
A mutliserver facility is declared as
a normal (single server) facility.
Example:
FACILITY cpu;
However, a multiserver facility is initialized
in a different manner.
Prototype:
FACILITY facility_ms(char
*name, long
number_of_servers)
Example:
cpu =
facility_ms("dual cpu", 2);
A process can either execute a use
statement or the reserve-release
pair of statements at a multiserver
facility. In either case, the process
gains access to any server that is free;
a process is suspended and put in the
single queue at the facility only when
all of the servers are busy.
A facility set is an array of facilities.
Example:
FACILITY disk[10]
A facility set is initialized as follows:
Prototype:
void facility_set(FACILITY
f[],char *name,
long num_facilities);
Example:
facility_set(disk,
"disk", 10) ;
reserve(disk[0]);
In a facility set, each element of the
set is an independent, single server
facility, with its own queue. Each of
these facilities is given a constructed
name which shows its position in the
set. In the above example, the name
for the first element of the set is
"disk[0]". Facility sets are
used to model cases where each server
has its own queue of waiting processes.
Sometimes a process must not wait indefinitely
to gain access to a server. If a process
executes the timed_reserve
function, it will be suspended until
either it gains use of a server or the
specified time-out interval expires.
Prototype:
long timed_reserve(FACILITY
f, double timeout)
Example:
result = timed_reserve(f,
100.0);
if (result ! = TIMED_OUT) . . .
The process must check the functional
value, to determine whether or not it
obtained a server. If the value TIMED_OUT
is returned, the process did not obtain
a server. If this is not returned (EVENT_OCCURRED
will in fact be returned), then the
process did obtain a server and should
eventually release the server.
The name of a facility can be changed
at any time, as follows:
Prototype:
void set_name_facility(FACILITY f, char
*new_name)
Example:
set_name_facility(f,
"cpus");
Only the first ten characters of the
facility's name are stored.
The service discipline for a facility
determines the order in which processes
at the facility are given access to
that facility. If not otherwise specified,
the service discipline for a facility
is fcfs. When the priorities differ,
processes gain access to the server
in priority order (higher priority processes
before lower priority processes). When
processes have the same priority, the
processes gain access in the order of
their arrival at the facility (first
come, first served). This default service
discipline can be changed.
Prototype:
void set_servicefunc(FACILITY f,
void(*service_function)())
Example:
set_servicefunc(f,
pre_res);
Set_servicefunc()
refers to a service function which is
invoked when the use statement (described
above) references this facility. This
service function can be any of the following
pre-defined service discipline functions:
-
fcfs
- first come, first served
This is the default service discipline
and is described in the introduction
to this section. If the synchronous_facility
statement (see below) is used for
this facility, this will behave like
a fcfs_sy
(clock synchronized fcfs) facility.
In other words, there are two ways
for a facility to become synchronized:
specifying the service discipline
of fcfs_sy
or specifying (or defaulting) fcfs
for the service discipline and using
the synchronous_facility
statement.
-
fcfs_sy
- first come, first served, clock
synchronized
This is the same as fcfs except that
requests can be satisfied only at
the beginning of a clock cycle. If
not otherwise specified (via synchronous_facility
below), the clock phase (time to onset
of first clock cycle) will be 0.0,
and the period (length of a clock
cycle) will be 1.0.
-
inf_srv
- infinite servers
There is no queueing delay at all
since there is always a server available
at the facility.
-
lcfs_pr
- last come, first served, preempt
Arriving processes are always serviced
immediately, preempting a process
that is currently being served if
necessary. Priority is not a consideration
with this service discipline.
-
prc_shr
- processor sharing
This is load-dependent processor sharing.
Service times for each process are
determined based on the number of
processes at the facility. If not
otherwise specified (see set_loaddep
below), it will be assumed that the
rate that applies when there are n
processes at the facility is n
(in other words, if there are n
processes at the facility, the service
time will be multiplied by n).
The altered service times are recomputed
as tasks that arrive at and leave
the facility. There is no queueing
delay with processor sharing since
the assumption is that the server
works faster and faster as necessary
to service all processes that request
it.
There can be a maximum of 100 processes
sharing a prc_shr
facility.
-
pre_res
- preempt resume
Higher priority processes will preempt
lower priority processes, so that
the highest priority process at the
facility will always finish using
it first. Where the priorities are
the same, processes will be served
on a first come, first served basis.
Preempted processes will eventually
resume and complete their service
time intervals.
-
pre_rst
- preempt-restart
Higher priority processes will preempt
lower priority processes, so that
the highest priority process at the
facility will always finish using
it first. Where the priorities are
the same, processes will be served
on a first come, first served basis.
Preempted processes will eventually
resume and will restart their respective
service time intervals each time they
resume.
-
rnd_pri
- round robin with priority
Higher priority processes will be
served first. When there are multiple
processes with the same priority,
they will be serviced on a round robin
basis, with each getting the amount
of time specified in set_timeslice
(see below) before being preempted
by the next process of the same priority.
-
rnd_rob
- round robin
Processes will be serviced on a round
robin basis, with each getting the
amount of time specified in set_timeslice
(see below) before being preempted
by the next process requiring service.
Process priority is not a consideration
with this service discipline.
Caution:
The use statement (as opposed to the
reserve)
statement must be used for most of these
service disciplines to be effective.
Only fcfs
and fcfs_sy will operate properly with
reserve.
To set the clock information for the
fcfs_sy
service discipline:
Prototype:
void synchronous_facility(FACILITY
f, double
phase, double period)
Example:
synchronous_facility(f,
0.0, 1.0);
To set the load dependent service rate
for the prc_shr
(see above) service discipline:
Prototype:
void set_loaddep(FACILITY
f, double rate[],
long n)
Example:
set_loaddep(f,
rate, 10);
The "rate" array is an array
of length n,
where each element specifies the service
rate for the corresponding number of
processes using the server. Rate[i]
is the amount by which the service time
is multiplied when there are i
processes at the facility. If n
is less than the 100 (the maximum number
of processes allowed to share use of
a prc_shr
facility), then the value of the last
specified rate is replicated until 100
values are available. Also, if n
is greater than 99, only 100 values
will be used. It should be remembered
that the altered service times are recomputed
as tasks arrive at and leave the facility.
To set the time slice for the round
robin service disciplines, rnd_pri
and rnd_rob
(see above):
Prototype:
void set_timeslice(FACILITY
f, double
slice_length)
Example:
set_timeslice(f,
0.01);
To delete a facility:
Prototype:
void delete_facility(FACILITY
f)
Example:
delete_facility(f);
To delete a facility set:
Prototype:
void delete_facility_set(FACILITY
if_set[])
Example:
delete_facility_set(f_set);
Caution:
Deleting a facility or facility set
is an extreme action and should be done
only when necessary.
Information about usage of a facility
by processes belonging to different
process classes can be collected for
all facilities or for a specific facility.
To collect class-based usage information
for a specific facility:
Prototype:
void collect_class_facility(FACILITY
f)
Example:
collect_class_facility(f);
Usage of this facility by all process
classes (see
section 17, "Process Classes")
will be reported in the facilities report.
Also, it is an error to change the maximum
number of classes allowed after this
statement has been executed.
To collect usage information for all
facilities:
Prototype:
void collect_class_facility_all(void)
Example:
collect_class_facility_all();
This applies to all of the facilities
in existence when this statement is
executed Usage of the facilities by
all process classes (see
section 17, "Process Classes")
will be reported in the facilities report.
It is an error to change the maximum
number of classes allowed after this
statement has been executed.
All statistics and information maintained
by a facility can be retrieved during
execution of a model or upon its completion.
| Prototype: |
Functional
Value: |
| char* facility_name(FACILITY
f) |
pointer to name
of facility |
| long num_servers(FACILITY
f) |
number of servers
at facility |
| char* service_disp(FACILITY
f) |
pointer to name
of service
discipline at facility |
| double timeslice(FACILITY
f) |
time in each
time-slice for facility
(which has a round robin
service discipline) |
| long num_busy(FACILITY
f) |
number of servers
currently
busy at facility |
| long qlength(FACILITY
f) |
number of processes
currently
waiting at facility |
| long status(FACILITY
f) |
current status of facility
Busy if all servers are in use
FREE if at least one server is
not in use
|
long completions(FACILITY f) |
number of completions
at facility |
| long preempts(FACILITY
f) |
number of preempted
requests
at facility |
| double qlen(FACILITY
f) |
mean queue length
at facility |
| double resp(FACILITY
f) |
mean response
time at facility |
| double serv(FACILITY
f) |
mean service
time at facility |
| double tput(FACILITY
f) |
mean throughput
rate at facility |
| double util(FACILITY
f) |
utilization (%
of time busy) at
facility |
Additional data on servers and classes
can be obtained as follows:
long server_completions(FACILITY
f, long sn)
number of completions for server sn
at facility
double server_serv(FACILITY
f, long sn)
mean service time for server sn
at facility
double server_tput(FACILITY
f, long sn)
mean throughput rate for server sn
at facility
double server_util(FACILITY
f, long sn)
utilization for server sn
at facility
long class_qlength(FACILITY
f, CLASS c)
number of processes from class at
facility
long class_completions(FACILITY
f, CLASS c)
number of completions for class at
facility
double class_qlen(FACILITY
f, CLASS c)
mean queue length for class at facility
double class_resp(FACILITY
f, CLASS c)
mean response time for class at facility
double class_serv(FACILITY
f, CLASS c)
mean service time for class at facility
double class_tput(FACILITY
f, CLASS c)
mean throughput rate for class at
facility
double class_util(FACILITY
f, CLASS c)
utilization for class at facility
To obtain a report on the status of
all of the facilities in a model:
Prototype:
void status_facilities
(void)
Example:
status_facilities ();
This report lists each facility along
with the number of servers, the number
of servers which are busy, the number
of processes waiting. the name and id
of each process at a server, and the
name and id of each process in the queue.
|
|