Resources, garbage-collection and the π-calculus David Teller

advertisement
Resources, garbage-collection and the π-calculus
David Teller?
D.O.Teller@sussex.ac.uk
University of Sussex
Abstract. Techniques such as mobility and distribution are often used
to overcome limitations of resources such as the amount of memory or
the necessity for specialised devices. Indeed, questions related to such
limitations are crucial in matters of security, compilation and quality of
service. However, few attempts have been made at formalising this notion
of resource limitation in presence of mobility, distribution or concurrency.
In this paper, we present a formalisation of resource usage, resource
limitations and garbage-collection, using as a support a variant of the
π-calculus, the controlled π-calculus. We use this calculus to study formally the notion of garbage-collection and to produce an effective proof
system for respect of resource bounds, aware of resource transfer between
processes and resource reuse thanks to finalisation. We also present an
example of transformation of a protocol for compliance with such limitations and we confront informally our definitions with commonly-used
garbage-collectors such as those of OCaml, Java and C#.
1
Introduction
In modern computer technologies, aspects of mobility, concurrency and distribution are nearly omnipresent. Software deployed on a system has often been built
on a different system and channelled to the end-user through possibly unsafe
means, just as consumer electronics is expected to start taking advantage of Cell
chips to provide mostly transparent distribution of tasks among dynamically assembled arrays of processors. While these techniques are often used for the sake
of convenience, as they correspond to the intuitive way of thinking about some
problems, they are also often necessary to overcome limitations on resources.
For instance, analysing large sets of data typically require amounts of memory
or CPU power not found on individual computers, while many organisations
gather printers around print servers, providing printing resources to printer-less
PCs.
Several attempts have been made at modelling aspects of the usage of resources for mobility, but do not take into account the fact that many resources
are limited, used concurrently, and may be reused once deallocated [6, 7]. In this
paper, we attempt to go further. We present the controlled π-calculus, or cπ,
?
Many thanks to Martin Berger, Matthew Hennessy, Tom Hirschowitz, Karl Krukow
and Julian Rathke for their time and their numerous and insightful suggestions.
a process algebra based on the π-calculus, augmented with semantic constructions to represent resources, resource usage and limitations, garbage-collection
and resource reuse. This calculus is intended as a step towards the design of a
domain-specific programming language for safe, provable resource manipulation.
Some of the ideas presented in this paper build on ideas previously expressed in
the first incarnation of cπ [10], Controlled Ambients [12] and BoCa [3].
The foremost concept of cπ is that of resource. Resources are abstract representations of notions such as memory space, file access rights or printers. Resources may be allocated to variables, file handlers or print requests or other
depositaries, all of them represented by names in the π-calculus. To mirror this,
we enrich the π-calculus with notions of resource allocation (i.e. name creation),
usage (i.e. name existence) and deallocation (i.e. name destruction). To illustrate
this point, let us consider the following transitions in cπ :
new a : Ram in j −→ (νa : Ram)j
(νa : Ram)j 0 −→ j 0
(1)
(2)
Transition (1) represents the allocation of a resource Ram from the system,
for use in j. The depositary for this resource is a – in an applied implementation
of cπ, a would probably be associated to some value stored in memory. Hence,
this transition may not take place if there are not enough resources available for
the creation of a. Conversely, that depositary may be destroyed by a transition
such as (2), hence releasing of Ram and possibly triggering transitions which
were blocked by the lack of resources.
Deciding when to destroy a name is a complex problem without one single
best solution. While some languages use more or less complete algorithms for
automatic garbage-collection, others rely on manual operations of deallocation
(as in C) or reallocation (as in Camelot [6]). The question is no less complex in
the π-calculus or cπ. For instance,
(νa : Ram)a?(x).j
represents a process expecting some input on a name a. Since that name is
private and known by no other process, the communication will never take place.
Therefore, a is useless and that resource Ram could be deallocated by some wellchosen garbage-collection scheme. More complete algorithms may also be aware
of deadlocks or useless live processes. In cπ, rather than choosing a specific
deallocation strategy, we rely on a parametric relation GC to determine when a
channel may be removed. As we will see, well-chosen relations may mimic either
automatic or manual garbage-collection, as well as channel or system failures,
preemption of resources or exceptions.
In Section 2, we introduce cπ, which we illustrate in Section 3 with the example of a manager for bounded resources. We then discuss in Section 4 properties
of the language and a classification of garbage-collectors. Section 5 contains a
type system for guarantees on resource usage. We conclude this paper by a review of related works and on-going developments. Full proofs may be found in
a companion report [11].
2
The language
The syntax of cπ is defined by the following grammar:
Processes P, Q ::= (νa : r)P | P |Q | i
Instructions i, j ::= 0 | new a : r in i | spawn i and j | a?(b).i
| a!hbi.i | ∗ i | if a = b then i else j
We differentiate currently executed processes (P , Q. . . ) from instructions
waiting to be executed (i, j. . . ). Resources (r, s . . . ) are members of a set
of resources S, parameter of the language. Names (a, b. . . ) are elements of an
infinite set N which also contains }, or “null”, the name of deallocated channels,
which cannot be bound and on which it is thus impossible to communicate. All
terms are supposed finite.
Process (νa : r)P holds resource r for its private name a and behaves as P ,
while process i executes the instructions i. Instruction new a : r in i allocates
resource r to name a and proceeds as i, while spawn i and j produces two
concurrent threads running i and j. Other constructions are identical to their
π-calculus counterpart. Free and bound names are defined as in the π-calculus.
The main difference between (ν) and new in as well as between | and
spawn and is that the first construct of each pair describes a running process,
while the second describes an instantiation instruction. An implementation of
cπ might introduce constructors for new in – representing different methods
of collecting resources to create a name – and for spawn and – representing
different natures and locations of instantiated processes.
Definition 1 (Resources). A set (S, ⊕, ⊥, , >) is a set of resources if ⊕ (the
composition of two resources) is a binary operator on S, defined everywhere
and commutative, with neutral element ⊥, if (the inclusion of a resource in
another) is a preorder on S with a minimal element ⊥ and a maximal element
> and for all x, y, z, whenever x y holds, x ⊕ z y ⊕ z also holds.
A process P is said to hold resource res(P ), where res is defined by
res((νa : r)P ) = res(P ) ⊕ r
res(P |Q)
= res(P ) ⊕ res(Q)
res(i)
=⊥
Typical sets of resources are integers (used to represent memory and spacelike resources) powersets with union (used to represent keys and non-conflicting
distribution) and powersets with disjoint union and “undefined” as a maximal
value (used to represent devices and conflicting distribution).
Structural equivalence is defined as the smallest equivalence ≡ compatible
with the axioms of Figure 1 and with α-conversion of bound names – in contrast
with the traditional π-calculus, we do not have (νa : r)0 ≡ 0, as these processes
do not use the same amount of resources. Resource-unaware semantics is defined
τ
as the smallest relation −→pre compatible with the axioms of Figure 1.
(νa : r)(νb : s)P ≡ (νb : s)(νa : r)P
∗i ≡ i| ∗ i
(a 6= b)
a∈
/ f n(Q)
P ≡Q
P ≡Q
((νa : r)P )|Q ≡ (νa : r)(P |Q)
P |R ≡ Q|R
(νa : r)P ≡ (νa : r)Q
a?(b)
α
P −→pre P 0
R-Par
P −→ pre P 0
R-Comm
α
P |Q −→pre P 0 |Q
τ
P |Q −→pre P 0 |Q0
τ
P −→pre P 0
R-Hide
P ≡ P0
τ
(νa : r)P −→pre (νa : r)P 0
P 0 −→pre Q0
α
P −→pre Q
τ
spawn i and j −→pre i|j
R-Alloc
new a : r in i −→pre (νa : r)i
a?c
R-Receive
a 6= }
α
Q0 ≡ Q
R-Equiv
τ
R-Spawn
a!hbi
Q −→ pre Q0
a!c
a?(b).i −→pre i{b ← c}
R-Send
a!hci.i −→pre i
τ
R-Then
if a = a then i else j −→pre i
τ
R-Else
if a = b then i else j −→pre j
(a 6= b)
a : r GC P
Gc-Deallocate
τ
τ
Clean-Send
τ
(νa : r)P −→pre P {a ← }}
}!hxii −→pre 0
Clean-Receive
}?(x)i −→pre 0
τ
Clean-RReceive
∗}?(x)i −→pre 0
τ
Clean-RSend
Fig. 1. Resource-unaware semantics of cπ.
∗}!hxii −→pre 0
Rule R-Spawn executes the spawning of a new thread, while rule R-Alloc
executes the creation of a new channel, hence consuming resources. Rule RComm differs from its π-calculus counterparts insofar as no communication is allowed on a destroyed channel. The destruction of a channel – and the corresponding release of resources held by the process – is handled by Gc-Deallocate.
This rule depends on an oracle GC . By opposition to the π-calculus this relation may implement manual destruction, reference-counting, as well as more
complex operations from error-handling to deadlock-detection. Rules Clean-*
complete the task of cleaning-up processes by removing processes attempting
to communicate on destroyed channels. This mechanism of garbage-collection
of processes themselves may be compared to the Segmentation Fault of modern
operating systems. Also note that it is possible to compare any two names. In
particular, if x = } then i else j will reduce to i if x has been destroyed
and to j otherwise. In this respect, channel names behave as weak references
in many programming languages. This definition permits the implementation of
finalisation and exception-like mechanisms.
Definition 2 (Resource-aware Labelled Transition Semantics).
The resource-aware LTS of an instance of cπ on the set of resources S with a
• GC
garbage-collector GC is defined by the relation 7−→
where,
α
P −→pre Q
α;r GC
P 7−→
res(Q) r
Q
Note that, under some circumstances, numerous otherwise identical reductions may be expressed with an infinite number of different resource labels.
Definition 3 (Resource-aware semantics). The resource-aware semantics
of an instance of cπ on the set of resources S with a resource limit of r ∈ S and
where
with a garbage-collector GC is defined by the relation −→GC
r
τ ;r GC
P 7−→
P
−→GC
r
Q
Q
Resource-aware semantics take into account the fact that a system has limited resources. When a resource is not available for a transition, that transition
does not take place. Note that r represents a limit on the total level of resource
used – for instance, the physical amount of memory on the computer running the
program, or the authorisations acquired – and does not change during the reduction. On the other hand, the number of resources currently used, materialised by
res(P ), varies with time, increasing as a consequence of allocations and decreasing as a consequence of deallocations. In Section 3, we will see a garbage-collector
providing a form of error-handling mechanisms in case of resource exhaustion.
3
Example: A print spooler
In this section, we present a model for a simple print spooler – most of the techniques we expose here would be equally useful in the case of a system memory
manager or any resource broker. This spooler maintains a pool of available printers, receives requests from clients and returns a handler to any non-busy printer.
Whenever the caller has finished with the printer, this resource is returned to
the pool. If some requests had been put on hold, one of them is then unblocked
and fulfilled.
For the sake of brevity, we assume the existence of macros P ush and P op,
used respectively to add or remove printers from a pool, itself containing initially
n printers, and we extend the syntax to allow polyadic communications.
The following process is an example of a possible client:
∆
Client = new a in .request!hai.a?(printer, destructor).Print.destructor!hi. · · ·
It sends a request on the predefined channel request, waits for the printer and
its destructor, uses printer as necessary, then deallocates by calling destructor
and proceeds without using printer anymore.
Straightforward model Numerous strategies are possible for the ”implementation” of the print spooler. We may, for instance, give the client full access and
return a printer to the pool without any check, once the destructor is called:
BRM Driver1 = ∗request?(x).new destructor in .P op (y).
(x!hy, destructori | ∗ destructor?().P ush y)
In turn, intermediate channels may be removed by a simple scheme 1 once
/ f n(P ).
they are not referenced anymore: ∀x, ∀P, x : 1 P ⇐⇒ x ∈
This printer re-pooling strategy is clearly unsafe, as a malicious or ill-written
client may never call destructor, may call it several times or may continue to
use the printer afterwards – this technique is therefore similar to free() in C.
The garbage-collection scheme, similar to that of the traditional π-calculus, can
prove insufficient if the client, for some reason, syntactically continues to reference destructor even though it does not use it anymore. Such a mechanism is
commonly found in programming languages, implemented as a reference-counter,
and is often considered a simpler alternative to full-scale garbage-collectors, although it cannot handle complex scenarios, such as cycles of references.
Complex model This model, as most of our experiments, uses the mechanism of
finalisation. While finalisation is commonly used by developers to permit safe
interaction between components implemented with different memory models, we
take advantage of this mechanism to permit safe reuse of deallocated resources:
F inalise h.i = (νlock : ⊥)lock!hi | ∗ lock?().if h = } then i else lock!hi
This macro waits until h has been destroyed then triggers i. Since i is triggered after the destruction of h, it may safely reuse the resources formerly allocated to h. Among other things, finalisation or finalisation-like mechanisms may
be used to transform resource-unaware loops or services into resource-bounded
loops or services. We demonstrate this on figure 2.
For this second driver, we suppose the existence of three resources Limit
(some limit on resource usage), Handler and Res (both of which are used by
the garbage-collector to identify under which circumstances some depositaries
may or must be removed).
Whereas the previous spooler gave full access to printers, this one generates
and communicates handlers handler, which a client may use to send documents
to one printer. The destruction of a handler may be triggered either by a call to
destructor by the client, automatically by the garbage-collector, or as a consequence of the destruction of sigres. In either case, its finalisation pushes back
the printer onto the pool.
The behaviour of names delete and sigres is determined by the garbagecollection scheme we use for this example. This relation is defined by several
rules: it permits automatically deallocating non-referenced names (1), as well as
names only referenced in receptions (2, 3) or finalisations (4). Any name may
also be manually destroyed by emitting it on channel delete (5). Deallocation of
names may also be used to react to a specific state of the system – here, lack
of memory: if the resource usage of the process exceeds a given limit Limit,
an agreed-upon name sigres is deallocated (6). As we have seen, this triggers
destruction of all handlers, and some error-management routine (presumably
warning the administrator).
BRM Driver2 = ∗request?(x).P op (y).new destructor in
new handler : Handler in new sigres : Res in
spawn ∗ handler?(z).y!hzi
and x!hhandler, destructori
and ∗ destructor?().delete!hhandleri
and F inalise handler.P ush y
and F inalise sigres.(spawn delete!hhandleri and Handle error)
The Garbage-Collection relation is the smallest err verifying
(1)
∀x, ∀P, x ∈
/ f n(P ) ⇒ x err P
(2)
∀x, ∀P, i, x err P ⇒ x err P | x?(y).i
(3)
∀x, ∀P, i, x err P ⇒ x err P | ∗ x?(y).i
(4)
∀x, ∀P, i, x err P ⇒ x err P | F inalise x.i
(5)
∀x, ∀P, i, a : Handler err delete!hai.i | P
(6)
res(P ) Limit ⇒ sigres : Res err P
Fig. 2. A print spooler with error-handling and without dangling pointers
The re-pooling itself is safe, insofar as a printer may only be returned once
to the pool and can only be used again by the client if the client requests a
new printer and receives a new handler. The technique used here may be seen
as a combination of usage of manual and automatic garbage-collection and fi-
nalisation, as well as a manner of concurrent exception-handling, in which the
destruction of handler serves as throwing, and its finalisation as catching.
Note that, as in our previous works [10], and by opposition to most garbagecollected programming languages (including Java, C# and OCaml), finalisation
is safe, insofar as resurrection of an entity [2] is impossible. Also note that
operations delete and F inalise are not limited to this example and may be used
to provide simple models of more complex features such as channel failure or
preemption of a resource. In Section 5, we will discuss how a type system may
take advantage of finalisation to provide guarantees on reuse of resources.
4
Properties
Due to space constraints, full proofs and more detailed propositions are omitted
and may be found in the companion technical report [11]. Proofs are generally
unsurprising.
Proposition 1 (cπ can contain π).
There is an encoding of the π-calculus to an instance of cπ which preserves
distribution, reduction, termination, structure, structural equivalence and barbs.
Proposition 2 (More resources give more freedom).
If S is a set of resources and if r and s are elements of S such that r s then,
GC
for any garbage-collection scheme GC, −→GC
r ⊆−→s . If r ≺ s, we further have
GC
GC
−→r (−→s .
The inclusion derives directly from the definition of −→GC
r . The non-equality
can be proved by examining process (νa : s)(a?(x) | a!h}i), as this process has
no reduction in −→GC
and one step of reduction in −→GC
r
s .
Definition 4 (Sound, complete).
If is a relation between processes (typically, a simulation), a garbage-collection
scheme GC is sound with respect to if and only if, for any a, r and P such
that a GC P , we have (νa : r)P P {a ← }}.
A garbage-collection scheme GC is complete w.r.t. if and only if it contains
all garbage-collection schemes sound w.r.t .
A sound garbage-collector may trigger behaviours (typically by freeing resources or finalising names) but not remove any. A complete garbage-collector
will remove every useless name and might also remove useful names.
Proposition 3 (Perfect garbage-collection).
If is a relation such that, for any a and P such that a ∈
/ f n(P ), P (νa :
⊥)P , there exists a decidable sound and complete garbage-collection relation with
respect to if and only if is decidable.
To prove the “only if” part, we may suppose the existence of a sound and com∆
plete garbage-collector SC, examine process P = (νa : ⊥)if a = } then i else j
and prove that a SC P if and only if j i.
Formally, we define (bi)simulations as in the π-calculus. By opposition to
their π-calculus counterparts, however, cπ (bi)simulations permit observation of
resources.
Definition 5 (Simulation).
For a resource-aware instance of cπ on the set of resources S and with garbagecollection relation GC, a relation R is a simulation if, whenever (P, Q) ∈ R, if
α;r GC
α;r GC
P 7−→
P 0 then there is some Q0 such that Q 7−→
Q0 and (P 0 , Q0 ) ∈ R. We
then write P ≤GC
Q,
and
we
say
that
Q
simulates
P
.
S
Note that simulation is contextual in presence of the empty garbage-collector
but that it is easy to find garbage-collectors for which simulation is not contextual. This contextuality may be used as an additional manner of classifying
garbage-collectors.
We now apply these definitions to a few examples.
Proposition 4 (Spooler garbage-collectors).
With respect to their respective simulations, garbage-collector 1 , as defined in
Section 3, is sound but incomplete, while garbage-collector err , as defined on
figure 2, is neither sound nor complete.
The incompleteness of both schemes may be proved by examining process
(νa)a!hxi, as a is removed by neither garbage-collector, although it clearly could.
We prove soundness of 1 by induction on the structure of processes, taking
advantage of Proposition 2. We prove the unsoundness of err by examining
(νa : Handler)delete!hai | if a = } then 0 else b!hi.
Proposition 5 (GC Interaction).
Informally, garbage-collector with unbridled finalisation is unsound.
Both the formalisation and the proof of this proposition are too long for
this paper. More interesting is the fact that we can experience this result in a
number of programming languages1 . This seems to indicate that, unrestricted,
the mechanism of finalisation is too powerful for this usage of resource-bounded
computation.
5
A type system for resource guarantees
In this section, we present a type system designed to produce proofs of resourceboundedness of protocols. As the language itself, this type system is parametrised
by the set of resources. The two main contributions of this type system are two
patterns which we incorporated after meeting them during our experiments on
reworking protocols to make them resource-bounded.
1
We have reproduced the result with type-safe subsets of OCaml, Java, C#, several
garbage-collected variants of C++, Python, variants of JavaScript. . .
The first pattern is the use of finalisation, as introduced in Section 3, to per∆
mit safe reuse of resources: in a process such as P = F inalise a.i | F inalise a.j,
both i and j are triggered only after the deallocation of resources allocated to
a. Process (i | j){a ← }} may therefore allocate more resources than P . The
resources allocated to a must, however, be shared between i and j or, from a
static point of view, between F inalise a.i and F inalise a.j. In the rest of this
type system, this sharing will be expressed as the value λ(a) of function λ.
The second pattern is that of runtime resource transmission: to execute a
∆
process such as Q = a?(x).new b : r in x!hbi, resource r seems necessary and
sufficient. It is, however, not realistic to expect requiring resource ∞·r to execute
∗Q, as the number of actual communications on a is probably finite. Therefore,
we may also consider that Q requires no resource, but that each call a!hyi.i
transmits resource r for the creation of b. In the rest of this type system, this
form of transfer will be expressed as parameters g and d of channel types.
Type judgements are expressed with the following grammar:
T ::= Bound(r, λ) r ∈ S, λ : N −→ S
N ::= N ame(C, r) e ∈ S
C ::= Chan(N, g, d) g, d ∈ S
| Ssh
Judgement Γ ` P : Bound(r, λ) states that, under environment Γ , P can
be evaluated as a process which may be executed without starvation using only
resource r and may have reused resources of external depositaries as specified
by λ. Judgement Γ ` a : N ame(C, r) states that, according to Γ , a is the
name of an entity using resource r, with role C. If C is Chan(N, g, d), a is a
communication channel, which can be used to communicate names of type N ,
to transfer resource g from the sender to the receiver, d of which can be reused
by the receiver after deallocation. Conversely, if C is Ssh, a is not a channel and
cannot be used for communication.
Figure 3 presents the type system. Two rules have been omitted due to space
constraints: T-Let and T-Spawn, for handling instructions new . . . in and
spawn . . . and , functionally identical to their process counterparts T-New and
T-Par. For the sake of readability, we slightly alter the syntax to allow writing
new a : N in · · · and (νa : N ). When necessary, we write a 7→ r for the function
defined on N whose value is r for a and ⊥ for everything else, λ\{x} for the
function defined on N whose value on x is ⊥ and identical to that of λ everywhere
else, and ⊥N for the function defined on N whose value is ⊥ everywhere. We
also extend and ⊕ to functions. Note that this type system can also be applied
to a traditional π-calculus with type annotations.
The following lemmas and theorems are standard and use standard proofs.
Lemma 1 (Weakening).
If Γ ` P : Bound(t, λ), if t0 t and λ0 λ, then Γ ` P : Bound(t0 , λ0 ).
Theorem 1 (Subject Reduction).
If Γ ` P : Bound(r, ⊥N ) and P −→GC∗
P 0 then Γ ` P 0 : Bound(r, ⊥N ).
>
Γ ` i : Bound(⊥, ⊥N )
T-Nil
Γ `0:T
λ(a) ra
T-New
T-Repl
λ0 λ\{a}
Γ ` ∗i : T
t0 ra ⊕ tP
Γ ` P : Bound(tP , λ)
Γ ` (νa : N ame( , ra ))P : Bound(t0 , λ0 )
t 0 tP ⊕ t Q
Γ ` P : Bound(tP , λP )
T-Par
λ0 λP ⊕ λQ
Γ ` Q : Bound(tQ , λQ )
Γ ` P |Q : Bound(t0 , λ0 )
t0 ⊕ r t
λ0 λ\{b}
d λ(b)
Γ ` a : N ame(Chan(N, r, d), )
Γ, b : N ` i : Bound(t, λ)
T-Receive
Γ ` a?(b).i : Bound(t0 , λ0 )
t0 t ⊕ r
λ0 λ ⊕ b 7→ d
b 6= }
Γ ` a : N ame(Chan(N, r, d), )
Γ ` i : Bound(t, λ)
T-Send
T-IfName
0
Γ `b:N
0
Γ ` a!hbi.i : Bound(t , λ )
a 6= }
b 6= }
Γ `a:N
Γ `b:N
Γ `j:T
Γ ` if a = b then i else j : Bound(t, λ)
a 6= }
λ0 λi ⊕ a 7→ s
λ0 λj
Γ `a:N
Γ ` i : Bound(ti , λi )
T-IfNull
Γ `i:T
t0 tj
t0 ⊕ s ti
Γ ` j : Bound(tj , λj )
Γ ` if a = } then i else j : Bound(t0 , λ0 )
Γ ` i : Bound(ti , λi )
T-IfAlwaysNull
Γ ` if } = } then i else j : Bound(ti , λi )
Fig. 3. Type system for resource guarantees.
Theorem 2 (Well-typed terms behave).
P 0.
P 0 then we also have P −→GC∗
If Γ ` P : Bound(r, ⊥N ) and P −→GC∗
r
>
In other words there is no starvation on resource acquisition.
Theorem 3 (Inference).
For any set of resources S such that (constructive) satisfiability of sets of linear
inequations is decidable, type inference is decidable.
This may be proved by induction on the structure of a term, by building a set
of systems of linear inequations on resources such that the term may be typed
if and only if one of the systems has a solution. Types of the term may then be
deduced from the solutions of the system.
An interesting property of the type system is that, as expected, the reallocation of deallocated resources through finalisation behaves as intended.
Proposition 6 (Finalization). For any s, we can always derive
Γ ` i : Bound(r, λ)
x 6= }
Γ ` F inalise x.i : Bound(r0 , λ ⊕ (x 7→ s))
r0 ⊕ s r
Proposition 7 (Spooler). Typing the print spooler permits us to determine
that it uses at most n printers, that each incoming call causes the allocation of
at most one handler, that there can be at most n handlers running at any time,
that the spooler allocates handlers only on demand and that the spooler sends
messages to the printer only when requested to do so by a client.
To prove these properties, we use the set of resources N4 where Γ ` P :
Bound((p, h, k, m), λ) means that P uses resources to allocate at most p printers,
h handlers using client’s resources, k handlers using the spooler’s resources and m
messages. In particular, most of these properties take advantage of the resource
transfer during communications. The proof itself is straightforward.
6
Conclusions
We have presented the new controlled π-calculus, a π-calculus with resource
allocation, usage and garbage-collection and with resource-bounded execution.
We have shown how to use this calculus to represent a complex bounded resources manager – in this case, a print spooler – with both manual and automatic garbage-collection and several forms of error-handling, including reaction
to the lack of some resources. We believe that the transformations applied to
make the print spooler resource-bounded may be performed automatically at
compile-time. Furthermore, we have developed a rich type system to guarantee properties of resource management in this controlled π-calculus, including a
novel manner of statically typing exchange of resources. Applying this type system to the bounded resources manager, we have managed to extract properties
of resource-boundedness and static transfer of authorisations.
This work builds on our previous experiences [9, 10] with resource control for
concurrent and distributed systems, as well as the BoCa [3] variant of Mobile
Ambients with resources. In relation to these developments, we provide more
polished semantic mechanisms, a more generic definition of resources, a much
finer study of garbage-collection, and more powerful proof techniques.
Comparable concepts have also been studied in the Camelot [6] functional
language, in the λ-calculus [7], in the Vault [5] imperative language and in
SCCS [1]. None of these attemps, however, combines a notion deallocation of
resources, a notion of resource bounds and concurrency.
Future developments Using cπ, we have built simple models of garbage-collection
by exploration of memory, as present in OCaml or Java, or by manual reallocation, as present in Camelot or numerous real-time programs. We have obtained
preliminary formal results on their safety, which we intend to explore further. We
are also currently progressing with the design of Teπc, a family of domain-specific
languages based on cπ. To cπ, Teπc adds notions of resource constructors and
depositaries values, expressed in parametric languages. Currently, our main difficulties are the development of a generic-enough dependent type system extending
our proof techniques to wider sets of properties, and the study of equivalence of
resources. We also intend to study mechanisms of garbage-collection adapted to
these languages and to our definitions, possibly by integrating existing works for
garbage-collection of names or processes [8, 4].
References
1. A calculus and logic of resources and processes. Technical Report HPL-2004-170R1,
Hewlett-Packard Labs, 2005.
2. K. Arnold and J. Gosling. The Java Programming Language. Addison-Wesley,
1998.
3. F. Barbanera, M. Bugliesi, M. Dezani, and V. Sassone. A calculus of bounded
capacities. In Proceedings of Advances in Computing Science, 9th Asian Computing
Science Conference, ASIAN’03, volume 2896 of Lecture Notes in Computer Science.
Springer, 2003.
4. S. Dal Zilio and A. D. Gordon. Region analysis and a π-calculus with groups. In
Proceedings of the 25th International Symposium on Mathematical Foundations of
Computer Science, volume 1893 of Lecture Notes in Computer Science. Springer,
Aug. 2000.
5. R. DeLine and M. Fahndrich. Enforcing high-level protocols in low-level software.
In SIGPLAN Conference on Programming Language Design and Implementation,
2001.
6. M. Hofmann. A type system for bounded space and functional in-place update–
extended abstract. Nordic Journal of Computing, 7(4), Autumn 2000. An earlier
version appeared in ESOP2000.
7. A. Igarashi and N. Kobayashi. Resource usage analysis. In Proceedings of the 29th
ACM SIGPLAN-SIGACT symposium on Principles of programming languages.
ACM Press, 2002.
8. N. Kobayashi. Useless code elimination and program slicing for the pi-calculus. In
Proceedings of APLAS’03, LNCS, 2003.
9. D. Teller. Formalisms for mobile resource control. In Proceedings of FGC’03,
volume 85 of ENCS. Elsevier, 2003.
10. D. Teller. Resource recovery in the π-calculus. In Proceedings of the 3rd IFIP
International Conference on Theoretical Computer Science, 2004.
11. D. Teller.
A pi-calculus with limited resources, garbage-collection
and guarantees.
Technical Report 4/2005, University of Sussex, 2005.
http://www.informatics.sussex.ac.uk/users/dot20/publications/cpi2rr.pdf.
12. D. Teller, P. Zimmer, and D. Hirschkoff. Using Ambients to Control Resources. In
Proceedings of the 13th International Conference on Concurrency Theory, volume
2421 of Lecture Notes in Computer Science. Springer-Verlag, 2002.
Download