Resource Usage Analysis for the Pi-Calculus

We propose a type-based resource usage analysis for theπ-calculus extended with resource creation/access primitives. The goal of the resource usage analysis is to statically check that a program accesses resources such as files and memory in a valid manner. Our type system is an extension of previous behavioral type systems for theπ-calculus, and can guarantee the safety property that no invalid access is performed, as well as the property that necessary accesses (such as the close operation for a file) are eventually performed unless the program diverges. A sound type inference algorithm for the type system is also developed to free the programmer from the burden of writing complex type annotations. Based on the algorithm, we have implemented a prototype resource usage analyzer for theπ-calculus. To the authors' knowledge, ours is the first type-based resource usage analysis that deals with an expressive concurrent language like the pi-calculus.


Introduction
Computer programs access many external resources, such as files, library functions, device drivers, etc.Such resources are often associated with certain access protocols; for example, an opened file should be eventually closed and after the file has been closed, no read/write access is allowed.The aim of resource usage analysis [11] is to statically check that programs conform to such access protocols.Although a number of approaches, including type systems and model checking, have been proposed so far for the resource usage analysis or similar analyses [5,6,7,11,1], most of them focused on analysis of sequential programs, and did not treat concurrent programs, especially those involving dynamic creation/passing of channels and resources.
In the present paper, we propose a type-based method of resource usage analysis for concurrent languages.Dealing with concurrency is especially important because concurrent 2 N. KOBAYASHI, K. SUENAGA, AND L. WISCHIK programs are hard to debug, and also because actual programs accessing resources are often concurrent.We use the π-calculus (extended with resource primitives) as a target language so that our analysis can be applied to a wide range of concurrency primitives (including those for dynamically creating and passing channels) in a uniform manner.
A main new difficulty in dealing with concurrent programs is that control structures are more complex in concurrent programs than in sequential programs.For example, consider the following process P 1 : (νc) (read(x).c| c( ).close(x)) Here, read(x).creads x and then sends a signal on channel c, and in parallel to that, c( ).close(x) waits for a signal on channel c and then closes x.Because of the synchronization through channel c, x is closed only after being read.To capture this kind of causal dependency between communications and resource access, we use CCS processes as extra type information (which are called behavioral types).For example, the above process is given the behavioral type (νc) (x R .c| c. x C ).
Using the behavioral types introduced above, we can construct a type system for resource usage analysis in a manner similar to previous behavioral type systems for the πcalculus [10,3].A type judgment is of the form Γ ⊲ P : A, where Γ is the usual type environment and A is a behavioral type approximating the behavior of P on the free channels and resources.For example, the above process P 1 is typed x : res⊲P 1 : (νc) (x R .c| c. x C ). Behavioral types are also used to augment channel types.The judgment for s(x).P 1 is given by: Γ ⊲ s(x).P 1 : s where Γ = s:chan (x:res)(νc) (x R .c| c. x C ) .Here, the behavioral type of s(x).P 1 is simply a single input command s: the characteristic feature of this kind of type system is that the behavior of the input continuation is accounted for at output, not at input.The channel s has argument type (x:res)(νc) (x R .c| c. x C ), which specifies that the resource sent along channel s will be read first and then closed.Using the same type environment, the output process s r is typed as: Γ, r:res ⊲ s r : s. (νc) (r R .c| c. r C ) Here the behavioral type is an output followed by a continuation.The continuation (νc) (r R .c| c. r C ) has been obtained by substituting r for x in the argument type of s.In this way, the types propagate information about how resources and channels passed thorough channels are accessed.
An important property of our type system is that types express abstract behavior of processes, so that certain properties of processes can be verified by verifying the corresponding properties of their types, using, for example, model checking techniques.The latter properties (of behavioral types) are more amenable to automatic verification techniques like model checking than the former ones, because the types do not have channel mobility and also because the types typically represent only the behavior of a part of the entire process.
The technical contributions of the present work are summarized as follows.
• Formalization of type systems for resource usage analysis for the π-calculus, and proof of their soundness.We have augmented previous behavioral types for the πcalculus with hiding and renaming constructors, and adapted them to the problem of resource usage analysis.CCS-like processes have been used as types also in previous work on type systems for the π-calculus [10,3].Igarashi and Kobayashi [10], however, used a fragment without hiding and renaming, and Chaki et al. [3] used a fragment without renaming, while the present paper uses both hiding and renaming.The inclusion of hiding and renaming is important both for accuracy and for automatic inference (see Remark 3.12).• Realization of fully automatic verification (while making the analysis more precise than [10]).Igarashi and Kobayashi [10] gave only an abstract type system, without giving a concrete type inference algorithm.Chaki et al. [3] requires type annotations.
The full automation was enabled by a combination of a number of small ideas, like inclusion of hiding and renaming as type constructors, and approximation of a CCSlike type by a Petri net (to reduce the problem of checking conformance of inferred types to resource usage specification).• Verification of not only the usual safety property that an invalid resource access does not occur, but also an extended safety (which we call partial liveness) that necessary resource accesses (e.g.closing of a file) are eventually performed unless the whole process diverges.The partial liveness is not guaranteed by Chaki et al.'s type system [3].A noteworthy point about our type system for guaranteeing the partial liveness is that it is parameterized by a mechanism that guarantees deadlockfreedom (in the sense of Kobayashi's definition [14]).So, our type system can be combined with any mechanism (model checking, abstract interpretation, another type system, or whatever) to verify deadlock-freedom for deadlock-or lock-freedom (e.g., Yoshida's graph type system [25]).• Implementation of a prototype resource usage analyzer based on the proposed method.The implementation can be tested at http://www.yl.is.s.u-tokyo.ac.jp/~kohei/usage-pThe rest of this paper is structured as follows.Section 2 introduces an extension of the π-calculus with primitives for creating and accessing resources.Section 3 introduces a type system for resource usage analysis, which guarantees that well-typed processes never perform an invalid resource access.Section 4 gives a type inference algorithm for the type system.Section 5 extends the type system to guarantee that necessary resource accesses (such as closing of opened files) are eventually performed (unless the program diverges).Section 6 describes a prototype resource usage analyzer we have implemented based on the present work.Section 7 discusses related work.Section 8 concludes.

Processes
This section introduces the syntax and the operational semantics of our target language.
2.1.Syntax.Definition 2.1 (processes).The set of processes is defined by the following syntax.

P (processes) :
Here, x, y, and z range over a countably infinite set Var of variables.ξ ranges over a set of labels called access labels.Φ, called a trace set, denotes a set of sequences of access labels that is prefix-closed.The prefixes (like (νx) and (N Φ x)) bind tighter than the parallel composition | .
An access label specifies the kind of an access operation.Typical access labels that we are going to use in this paper are: I for initialization, R for read, W for write, and C for close.
Process acc ξ (x).P accesses the resource x, and then behaves like P .We will often write init(x).P , read(x).P , write(x).P , and close(x).P for acc I (x).P , acc R (x).P , acc W (x).P , acc C (x).P .Process (N Φ x)P creates a new resource with the bound name x that should be accessed according to Φ, and then behaves like P .Φ specifies a set of acceptable sequences of operations that are allowed for the new resource x.For example, (N (I(R+W ) * C) # x)P creates a resource that should be first initialized, read or written an arbitrary number of times, and then closed.Here, (S) # is the prefix closure of S, i.e., {s | ss ′ ∈ S}.We write ǫ for the empty sequence.
We often abbreviate a sequence v 1 , . . ., v n to v, and write x v .P and x( y).P for x v 1 , . . ., v n .P and x(y 1 , . . ., y n ).P .We often omit trailing 0 and write x v and acc ξ (x) for x v .0 and acc ξ (x).0 respectively.
The bound and free variables of P are defined in a customary manner; also (N Φ x)P binds x.We identify processes up to α-conversion, and assume that α-conversion is implicity applied so that bound variables are always different from each other and from free variables.2.2.Operational Semantics.We now formally define the operational semantics of our process calculus The operational semantics is almost the same as the standard reduction semantics for the π-calculus, except that trace sets Φ (which represent how resources should be accessed in future) may change during reduction.

Definition 2.2. The structural preorder
is the least reflexive and transitive relation closed under the rules in Figure 1 Remark 2.3.As in our previous behavioural type systems for the π-calculus [10,14,15], the structural relation is asymmetric.If the standard, symmetric structural relation were used, the type preservation property would not hold: Γ ⊲ * P | P : A does not necessarily imply Γ ⊲ * P : A) for the type system introduced in the next section.Notice that when an invalid access to a resource occurs (i.e. when the program accesses ξ but the specification Φ has no ξ-prefixes), then resource specification Φ is set to ∅ by Figure 2: Reduction Relation (R-NewR1).On the other hand Φ ⊇ {ǫ} indicates a resource that has been correctly used so far, and Φ = {ǫ} indicates one that has been correctly and completely used.
Definition 2.7.A process P is resource-safe if it does not contain a sub-expression of the form (N ∅ x)Q.
We give a type system guaranteeing that any resource-safe, well-typed process cannot be reduced to a non-safe process (in other words, any resource-safe, well-typed process never performs an invalid access) in Section 3.
Example 2.8.The following process first creates a resource x that should be first initialized, read an arbitrary number of times, and then closed.It then spawns four processes; they synchronize through channels c 1 and c 2 , so that x is accessed in a valid order.Example 2.9.The following program is prototypical of recursive functions.There is a replicated service which listens on channel s; it either terminates the recursion by sending a message back on the reply channel r, or it recursively invokes a sub-instance of itself which will reply on a private channel r ′ .In this example each recursive step does a read(x).The following program use an integer to decide whether or not to recurse.Though our language does not have integers and operations on them as primitives, it is trivial to extend our language and type system with those primitives.
(νs) * (s(n, x, r).if n = 0 then r else (νr ′ ) (s n − 1, x, r ′ | r ′ ().read(x).r ) | (N (IR * C) # x)(νr) (init(x).s100, x, r | r().close(x)) 2 The above program corresponds to the following higher-level program: init(x); parbegin read(x); read(x) parend; close(x) Example 2.10.Consider the following producer/consumer program: 1 (νproducer ) (νconsumer ) Remark 2.11.We treat resources as primitives in this paper, but we could alternatively express a resource as a tuple of channels, each of which corresponds to each access operation.For example, the resource in Example 2.8 can be expressed as a tuple consisting of three channels init, read, and close.If we did so, we could directly reuse the previous type systems [10,3] to infer some of the properties discussed in this paper (with different precision).Treating resources as primitives, however, simplifies the type systems introduced in later sections and clarifies the essence: if we expressed a resource as a tuple of channels, we would need primitives for simultaneous creation of multiple channels as in [10], and need to care about whether communications on the resource access channels succeed or not.On the other hand, our resource access primitives are non-blocking, which simplifies in particular the extended type system discussed in Section 5.

Type System
This section introduces a type system that prevents invalid access to resources.The type system in this section does not guarantee a liveness property that all the necessary accesses are eventually made; extensions to guarantee that property are discussed in Section 5.

3.1.
Types.We first introduce the syntax of types.We use two categories of types: value types and behavioral types.The latter describes how a process accesses resources and communicates through channels.As mentioned in Section 1, we use CCS processes for behavioral types.Definition 3.1 (types).The sets of value types σ and behavioral types A are defined by: A behavioral type A, which is a CCS process, describes what kind of communication and resource access a process may perform.0 describes a process that performs no communication or resource access.The types x.A, x.A, x ξ .A and τ.A describe processes that first perform an action and then behave according to A; the actions are, respectively, an input on x, an output on x, an access operation ξ on x, and the invisible action.A 1 | A 2 describes a process that performs communications and resource access according to A 1 and A 2 , possibly in parallel.A 1 ⊕A 2 describes a process that behaves according to either A 1 or A 2 .* A describes a process that behaves like A an arbitrary number of times, possibly in parallel.y 1 /x 1 , . . ., y n /x n A, abbreviated to y/ x A, denotes simultaneous renaming of x with y in A. (νx) A describes a process that behaves like A for some hidden channel x.For example, (νx) (x.y | x) describes a process that performs an output on y after the invisible action on x.The type µα.A describes a process that behaves like a recursive process defined by α △ = A. 2 The type A↑ S describes a process that behaves like A, except that actions whose targets are in S are replaced by the invisible action τ , while A↓ S describes a process that behaves like A, except that actions whose targets are not in S are replaced by τ .The formal semantics of behavioral types is defined later using labeled transition semantics.
As for value types, bool is the type of booleans.res is the type of resources.The type chan (x 1 : σ 1 , . . ., x n : σ n )A , abbreviated to chan ( x : σ)A , describes channels carrying tuples consisting of values of types σ 1 , . . ., σ n .Here the type A approximates how a receiver on the channel may use the elements x 1 , . . ., x n of each tuple for communications and resource access.For example, chan (x : res, y : res)x R .yC describes channels carrying a pair of resources, where a party who receives the actual pair (x ′ , y ′ ) will first read x ′ and then close y ′ .We sometimes omit σ and write chan ( x)A for chan ( x : σ)A .When x is empty, we also write chan .
Note that y/ x is treated as a constructor rather than an operator for performing the actual substitution.We write [ y/ x] for the latter throughout this paper.y/ x A is slightly different from the relabeling of the standard CCS [19]: y/x (x | y) allows the communication on y, but the relabeling of CCS does not.This difference calls for the introduction of a special transition label {x, y} in Section 3.2.Definition 3.2.The set of free variables of A, written FV(A), is defined by: As defined above, (νx) A, y/ x A, and A↑ S bind x, x, and the variables in S respectively.We identify behavioral types up to renaming of bound variables.In the rest of this paper, we require that every channel type chan (x 1 : σ 1 , . . ., x n : σ n )A must satisfy FV(A) ⊆ {x 1 , . . ., x n }.For example, chan (x:res)x R is a valid type but chan (x:res)y R is not.
The label {x, y} indicates the potential to react in the presence of a substitution that identifies x and y.We also extend target to the function on transition labels by: The transition relation   The set traces x (A) defined below is the set of possible access sequences on x described by A. Definition 3.4 (traces).
We define the subtyping relation A 1 ≤ A 2 below.Intuitively, A 1 ≤ A 2 means that a process behaving according to A 1 can also be viewed as a process behaving according to A 2 .To put in another way, A 1 ≤ A 2 means that A 2 simulates A 1 .We define ≤ for only closed types, i.e., those not containing free type variables.Definition 3.5 (subtyping).The subtyping relation ≤ on closed behavioral types is the largest relation such that Remark 3.6.Note that the subtyping relation defined here is the converse of the one used in Igarashi and Kobayashi's generic type system [10].This is due to two different, dual views on behavioral types.Here, we think of behavioral types as describing the behavior of processes.On the other hand, Igarashi and Kobayashi [10] think of behavioral types as describing the assumption on the environment about what kind of process is accepted by the environment.Because of this difference, they write behavioral types on the lefthand side of ⊲, and write Depending on what property the type system should guarantee, a finer subtyping relation may need to be chosen.For example, the above definition allows (x W .0) | (x W .0) ≤ x W .x W .0.We may want to disallow this relation if we want to infer a property like "no simultaneous writes on x can occur." The following properties are satisfied by ≤ .For proofs, see Appendix A. Lemma 3.8.
(1) ≤ is a precongruence, i.e., ≤ is closed under any behavioral type constructor. ( 3.3.Typing.We consider two kinds of judgments, Γ ⊲ v : σ for values, and Γ ⊲ P : A for processes.Γ is a mapping from a finite set of variables to value types.In Γ ⊲ P : A, the type environment Γ describes the types of the variables, and A describes the possible behaviors of P .For example, x : chan (b : bool)0 ⊲ P : x | x implies that P may send booleans along the channel x twice.The judgment y : chan (x : chan (b : bool)0 )x ⊲ Q : y means that Q may perform an input on y once, and then it may send a boolean on the received value.Note that in the judgment Γ ⊲ P : A, the type A is an approximation of the behavior of P on free channels.P may do less than what is specified by A, but must not do more; for example, x : chan ( )0 ⊲ x : x | x holds but x : chan ( )0 ⊲ x .x : x does not.Because of this invariant, if A does not perform any invalid access, neither does P .We write dom(Γ) for the domain of Γ.We write ∅ for the empty type environment, and write x 1 : τ 1 , . . ., x n : τ n (where x 1 , . . ., x n are distinct from each other) for the type environment Γ such that dom(Γ) = {x 1 , . . ., x n } and Γ(x i ) = τ i for each i ∈ {1, . . ., n}.When x ∈ dom(Γ), we write Γ, x : τ for the type environment ∆ such that dom(∆) = dom(Γ) ∪ {x}, ∆(x) = τ , and ∆(y) = Γ(y) for y ∈ dom(Γ).We define the value judgment relation Γ ⊲ v:σ to be the least relation closed under Γ, x:σ ⊲ x:σ Γ ⊲ true:bool Γ ⊲ false:bool.
We write Γ ⊲ v: σ as an abbreviation for (Γ ⊲ v Definition 3.9.The type judgment relation Γ ⊲ P : A is the least relation closed under the rules given in Figure 4.
We explain key rules below.
In rule (T-Out), the first premise Γ ⊲ P : A 2 implies that the continuation of the output process behaves like A 2 , and the second premise Γ ⊲ x : chan ( y : σ)A 1 implies that the tuple of values v being sent may be used by an input process according to v/ y A 1 .Therefore, the whole behavior of the output process is described by x.
For example, true/x, y/z A stands for y/z A. Note that, as in previous behavioral type systems [10,3], the resource access and communications made on v by the receiver of v are counted as the behavior of the output process (see Remark 3.13).
In rule (T-In), the first premise implies that the continuation of the input process behaves like A 2 .Following previous behavioral type systems [10,3], we split A 2 into two parts: A 2 ↓ { y} and A 2 ↑ { y} .The first part describes the behavior on the received values y and is taken into account in the channel type.The second part describes the resource access and communications performed on other values, and is taken into account in the behavioral type of the input process.The condition A 2 ↓ { y} ≤ A 1 requires that the access and communication behavior on y conforms to A 1 , the channel arguments' behavior.
In (T-New), the premise implies that P behaves like A, so that (νx) P behaves like (νx) A. Here, we only require that x is a channel, unlike in the previous behavioral type systems for the π-calculus [10,15].That is because we are only interested in the resource access behavior; the communication behavior is used only for accurately inferring the resource access behavior.
In (T-NewR), we check that the process's behavior A conforms to the resource usage specification Φ.
Rule (T-Sub) allows the type A ′ of a process to be replaced by its approximation A.
We remark that weakening of Γ can be derived (Appendix B, Lemma B.1) and so is not needed as a rule.
The following example shows how information about the usage of resources by an input process is propagated to an output process.
Example 3.10.Let us consider (N Φ x)P , where x : res.Then, the following judgment holds for the output and input processes.
Here, we have used subtyping relations

By using (T-Par) and (T-New), we obtain
x : res ⊲ P : (νy ) and let Γ = s:chan (n:int, x:res, r:chan ) A 1 .Then Γ, n:int, x:res, r:chan ⊲ P 1 : So long as traces x ((νr) (x I .A 1 |r.x C )) ⊆ Φ, we obtain ∅ ⊲ P : 0. See Section 4.3 for the algorithm that establishes traces x (•) ⊆ Φ. 2 Remark 3.12.The type A 1 in the example above demonstrates how recursion, hiding, and renaming are used together.In general, in order to type a recursive process of the form * s(x).(νy Moreover, for the type inference (in Section 4), we must find the least such A. Thanks to the type constructors for recursion, hiding, and renaming, we can always do that: A can be expressed by µα.(νy Remark 3.13.A reader may wonder why the rules (T-Out) and (T-In) are asymmetric, in the sense that information about the continuation of a receiver process is transferred to a sender process but not vice versa.That design choice comes from the observation that a channel or resource exchanged between a sender and a receiver are, in general, statically known only to the sender, so that we have to put information about the behavior on the channel or resource into the type of the sender.For example, consider the process ((νy . z .Since the receiver x(z).z is not in the scope of y, we have to put the information that y will be used for output into the type of the sender x y (as x. y).It is still useful and possible to recover the symmetry in the treatment of senders and receivers to some extent: see Section 8 of our previous paper [10].
The following theorem states that no well-typed process performs an invalid access to a resource.Theorem 3.14 (type soundness (safety)).Suppose that P is safe.If Γ⊲P : A and P −→ * Q, then Q is safe.
Proof.We make use of the following lemma: For the proof of the theorem, we focus on just a single reduction step.By the Lemma we know that judgements are preserved by reduction; we must show that safety is also preserved, by induction on the derivation of reduction.The only interesting case is (R-NewR1), (N Φ x)P τ → (N Φ −ξ x)P ′ , since the other rules do not alter trace-sets Φ.In this case, we are given Γ ⊲ P : A, traces x (A) ⊆ Φ, and P Assume (N Φ x)P is safe; hence so is P ; by the induction hypothesis so is P ′ .From the conditions traces x (A) ⊆ Φ and A

Type Inference Algorithm
This section discusses an algorithm which takes a closed process P as an input and checks whether ∅ ⊲ P : 0 holds.As in similar type systems [11,15], the algorithm consists of the following steps.
(1) Extract constraints on type variables based on the (syntax-directed version of) typing rules.(2) Reduce constraints to trace inclusion constraints of the form Figure 5: Syntax Directed Typing Rules (3) Decide whether the constraints are satisfied.The algorithm for Step 3 is sound but not complete.
We give an overview of each step below.The first two steps are almost the same as those in the previous work.

4.1.
Step 1: Extracting Constraints.The typing rules presented in Section 3 can be transformed to the syntax-directed typing rules shown in Figure 5.In the figure, Γ 1 ∪ Γ 2 is the type environment obtained by merging both bindings, and defined only if Γ 1 (x) = Γ 2 (x) for every x ∈ dom(Γ 1 )∩dom(Γ 2 ).Type equality here is syntactic equality up to α-renaming.And wd(Γ 1 ∪ Γ 2 ) means that Γ 1 ∪ Γ 2 is well-defined.The two sets of typing rules are equivalent in the following sense: If Γ ⊲ P : A is derivable, then there exists A ′ such that A ′ ≤ A holds and Γ ⊲ sd P : A ′ is derivable.Conversely, if Γ ⊲ sd P : A is derivable, so is Γ ⊲ P : A.
Based on the syntax-directed rules, we obtain the algorithm in Figure 6, which takes a process P and outputs a triple consisting of a type environment Γ, a behavioral type A, and a set C of constraints.In Figure 6, Γ 1 ⊗ • • • ⊗ Γ n is defined to be (Γ, C) where Γ and C are given by: The triple (Γ, A, C) output by PT satisfies the following properties: • θΓ ⊲ P : θA holds for any substitution θ such that |= θC.
• If Γ ′ ⊲ P : A ′ , then there exists a substitution θ such that θΓ ⊆ Γ ′ and θA ≤ A ′ .Here, Γ and A may contain variables representing unknown behavioral types and value types.C is a set of constraints on them, and the substitution θ above replaces them with closed behavioral types and value types.Intuitively, the triple (Γ, A, C expresses a set of type judgments for P .The first property above says that the triple contains only valid judgments, while the second property says that every valid judgment is subsumed by the triple.
We do not give a formal proof of the above properties; As usual, they can be proved by induction on the structure of P .

4.2.
Step 2: Reducing Constraints.Given a closed process P , PT(P ) produces a triple (∅, A, C).The set C of constraints consists of unification constraints on value types (where all the behavioral types occurring in them are variables), constraints of the form isChan(σ) (which means that σ is a channel type), subtype constraints on behavioral types of the form α ≥ A, and constraints of the form traces x (A) ⊆ Φ.We can remove the first two kinds of constraints (unification constraints on value types and isChan(σ)) by applying the standard unification algorithm.Thus, we obtain the following constraints: Here, we can assume that α 1 , . . ., α n are different from each other, since α ≥ A 1 and α ≥ A 2 can be replaced with α ≥ A 1 ⊕ A 2 by Lemma 3.8.We can also assume that {α 1 , . . ., α n } contains all the type variables in the constraint, since otherwise we can always add the tautology α ≥ α.Each subtype constraint α ≥ A can also be replaced by α ≥ µα.A, by using Lemma 3.8.Therefore, the above constraints can be further reduced, by Lemma 3.8, to: Here, A ′ 1 , . . ., A ′ n are the least solutions for the subtype constraints.Thus, we have reduced type checking to the validity of trace inclusion constraints of the form traces x (A) ⊆ Φ.
Example 4.1.Recall Example 2.9.By applying the algorithm PT and the first part of Step 2, we obtain the following constraints: By applying the second part of Step 2, we obtain traces x (A 1 ) ⊆ (IR * C) # where (where α, ρ fresh) Step 3: Constraint Solving.We present an approximation algorithm for checking a trace inclusion constraint traces x (A) ⊆ Φ when the trace set Φ is a regular language.(Actually, we can extend the algorithm to deal with the case where Φ is a deterministic Petri net language: see Remark 4.6.) We first describe the algorithm with an example.In Example 4.1 above, we have reduced the typability of the process to the equivalent constraint traces x (A 1 ) ⊆ Φ where Φ = (IR * C) # and x R .r)Here, we have removed A 3 = µα.αsince A 3 ≈ 0.
Step 3-1.Approximate the behavior of A 1 ↓ {x} by a Petri net [22] N A 1 ,x .This part is similar to the translation of usage expressions into Petri nets in Kobayashi's previous work [16,15,12].Since the behavioral types are more expressive (having recursion, hiding, and renaming), however, we need to approximate the behavior of a behavioral type unlike in the previous work.In this case A 1 ↓ {x} is infinite.To make it tractable we make a sound approximation A ′ 1 by pushing (ν) to top level, and we eliminate r ′ /r : x is as pictured.(Here we treat A 1 ⊕ A 2 as τ.A 1 ⊕ τ.A 2 for clarity.We also use a version of Petri nets with labeled transitions.) x I :A 0 2 x I :A 0 2 r:x C r:x C ¿:r © ¿:(A 0 3 jr 0 :x R :r) ¿:r © ¿:(A 0 3 jr 0 :x R :r) ¿:r 0 © ¿:(A 0 3 jr 0 :x R :r 0 ) ¿:r 0 © ¿:(A 0 3 jr 0 :x R :r 0 ) r r x C x C x R :r x R :r r 0 :x R :r r 0 :x R :r r 0 r 0 x R :r 0 x R :r 0 r 0 :x R :r 0 r 0 :x R :r 0 The rectangles are the places of the net, and the dots labeled by τ, x R , etc. are the transitions of the net.Write i x for the number of tokens at node B x .The behavior A ′ 1 corresponds to the initial marking {i 1 =1, i 10 =1}.We say that the nodes B together with the restricted names (r, r ′ ) constitute a basis for A ′ 1 .Note here that traces ) is the set of traces of the Petri net.Thus, ptraces(N A ′ 1 ,x ) ⊆ Φ is a sufficient condition for traces x (A 1 ) ⊆ Φ .The key point here is that A ′ 1 still has infinite states, but all its reachable states can be expressed in the form (νr, r a linear combination of finitely many processes B. That is why we could express A ′ 1 by the Petri net as above.
x and M Φ , which simulates the behavior of P A and M Φ simultaneously, so that the problem of traces To explain, if i 1 > 0 ∧ i 12 =0 then the behavior is able to make an R transition but the specification automaton M Φ is not able.
Step 3-4.Use an approximation algorithm to decide the reachability problem of N A ′ 1 ,x M Φ , in a manner similar to Kobayashi's type-based analyzer TyPiCal [12] for the π-calculus.

4.3.1.
Step 3-1: Construction of N A,x .We first introduce the notion of a basis.The basis is analogous to that of a vector space; Each state is expressed as a linear combination of elements of the basis.Definition 4.2.A pair ({y 1 , . . ., y m }, {B 1 , . . ., B n }) is a basis of A if all of the following conditions are satisfied: • For each B j , there are only finitely many C (up to ≈) such that B j l (If there are more than one such tuple, Index(C) picks one among them.)Therefore, if A↓ {x} has a basis, the behavior of A↓ {x} is simulated by the (labeled) Petri net N A,x,({ y},{ B}) given below.Here, we use a process-like syntax to represent the elements of a Petri net rather than the standard tuple notation (P, T, F, W, M 0 ).A marking state m which has i k tokens for each place p k (k ∈ {1, . . ., n}) is written i A transition that consumes a marking m 1 and produces m 2 is expressed by m 1 γ −→ m 2 , where γ is the label of the transition.
• The initial marking m I is i From now on we omit the basis and just write N A,x for N A,x,({ y},{ B}) .Let us write ptraces(N A,x ) for the set: The construction of N A,x outlined above can be applied only when a basis of A↓ x can be found (by some heuristic algorithm).If A↓ x has no basis or cannot be found, we approximate A↓ x by moving all the ν-prefixes to the top-level; for example, y. (νx) A, * (νx) A and µα.(νx)A are replaced by (νx) (y.A), (νx) * A, and (νx) µα.A respectively.Let A ′ be the approximation of A↓ {x} .It is easy to prove that A ′ is a sound approximation of A↓ {x} , in the sense that traces x (A) ⊆ traces x (A ′ ).We can compute a basis of A ′ as follows (see Appendix D for more details).Since ν-prefixes do not appear inside recursion, we can first eliminate the constructors •↑ S , •↓ S , and y/ x .Let (ν y) A ′′ be the resulting expression, where A ′′ does not contain •↑ S , y/ x , or (νx) .Let B be the set of behavioral types that are subexpressions of the behavioral types obtained from A ′′ by expanding recursive types and do not contain "unnecessary" unfolding [µα.A/α]A.Then, B is a finite set, and ({ y}, B) is a basis of A ′ .We can therefore construct a Petri net N A ′ ,x .By the construction, ptraces(N A ′ ,x ) = traces x (A ′ ) ⊇ traces x (A), so that ptraces(N A ′ ,x ) ⊆ Φ is a sufficient condition for traces x (A) ⊆ Φ.

Steps 3-2 and 3-3: Construction of N
A,x M Φ and reduction of traces x (A) to a reachability problem.Let P N A,x and T N A,x be the sets of places and transitions of N A,x respectively.Let M Φ be a minimized deterministic automaton4 that accepts Φ, and let Q Φ be its set of states and δ Φ be its transition function.
Definition 4.3.The composition of N A,x and M Φ , written N A,x M Φ , is defined as follows: • The set of places is • Initial state is m I | q I where m I is the initial state of N A,x and q I is the initial state of M Φ .Now, ptraces(N A,x ) ⊆ Φ can be reduced to the reachability problems of N A,x M Φ .
Theorem 4.4.ptraces(N A,x ) ⊆ Φ if and only if no marking m | q that satisfies the following conditions is reachable: Thus, we can reduce ptraces(N A,x ) ⊆ Φ to a finite set of reachability problems of N A,x M Φ .Hence ptraces(N A,x ) ⊆ Φ is decidable [18].

Corollary 4.5. ptraces(N A,x ) ⊆ Φ if and only if for every transition rule of the form
Remark 4.6.We can actually extend the above algorithm for checking traces x (A) ⊆ Φ to deal with the case where Φ belongs to the class of deterministic Petri net languages (more precisely, the class of P-type languages of λ-free, deterministic Petri nets [22,21]).If Φ is the P-type language of a λ-free, deterministic Petri net, then its complement Φ is a Petri net language [21].Therefore, we can construct a Petri net that accepts the intersection of the language of N A,x and Φ [22]), so that ptraces(N A,x ) ⊆ Φ can be reduced to the emptiness problem of the Petri net, which is decidable due to the decidability of the reachability problem.
Some of the useful resource usage specifications are not regular languages but are deterministic Petri net language.For example, consider a stack-like resource on which, at any point of program execution, the number of times the operation pop has been performed is less than the number of times push has been performed.Such specification is expressible as a deterministic Petri net language.

Extensions
The type system given so far guarantees that no invalid resource access is performed, but not that any necessary access is performed eventually; for example, the type system does not guarantee that a file is eventually closed.We discuss extensions of the type system to guarantee such properties.
We are interested in type systems that satisfy either partial liveness 5 or the stronger liveness property: • partial liveness: If P −→ * Q and Q −→, then Q does not contain any resource to which some access must be performed.• liveness: In any fair reduction sequence P −→ P 1 −→ P 2 −→ • • •, P eventually performs all the necessary resource access.(Here, a reduction sequence is fair if an input or output action that is infinitely enabled will eventually succeed.Without the fairness assumption, no process can satisfy the liveness property in the presence of a divergent process (νx) (x | * x( ).x , which is too restrictive.) Our idea is to take the resource type system from the previous sections, and combine it with some existing system that annotates those communications that eventually succeed.Specifically, this existing system might be (1) deadlock-freedom [16,15], which guarantees that the annotated communications eventually succeed unless the process diverges; the combination would then guarantee partial liveness.Or the existing system could be (2) lockfreedom [14,15], which guarantees that the annotated communications eventually succeed even in the presence of divergence (assuming a strongly fair scheduler); the combination would then guarantee full liveness.
To formally state which resource access must be performed, we extend the trace sets.
Definition 5.1.An extended trace set is a set of sequences of access labels, possibly ending with a special label ↓, that is closed under the prefix operation.
Intuitively, the special label ↓ means that no further resource access need to be performed.For example, the trace set ({C ↓, RC ↓}) # means that the close operation needs to be performed, while ({↓, R ↓, C ↓, RC ↓}) # means that the close operation need not be performed.
Now we can state the partial liveness property more formally.We write ( ν N) for a (possibly empty) sequence of νand N-binders.

5.1.
A Type System for the Partial Liveness Property.We extend the syntax of processes to allow each input and output prefix to be annotated with information about whether the communication is guaranteed to succeed.Definition 5.3 ((extended) processes).The set of (extended) processes is given by: t (attributes) ::= c | ∅ P ::= x t y 1 , . . ., y n .P | x t (y 1 , . . ., y n ).
The attribute c indicates that when the annotated input or output operation appears at the top-level, the operation will succeed unless the whole process diverges, while ∅ does not give such a guarantee.We often omit tag ∅.
We assume that there exists a type system guaranteeing that any well-typed process is well-annotated in the sense of Definition 5.4 below.There are indeed such type systems [13,16,15].Moreover, the static analysis tool TyPiCal [12] can automatically infer the annotations.Definition 5.4.P is active, written active(P ), if Additionally, P is well-annotated, written well annotated (P ), if for any P ′ such that P −→ * P ′ and active(P ′ ), there exists P ′′ such that P ′ −→ P ′′ .For example, x c .0 | x c ( ). y ∅ .0 is well-annotated, but x c .0 | x c ( ). y c .0 is not.Note that x ∅ ( ). x c .0 is well-annotated since, although the output never succeeds, it does not appear at the top-level.Now we introduce the type system that guarantees the partial liveness.We extend the behavioral types by extending each input, output, or τ -action with an attribute to indicate whether the action is guaranteed to succeed.For example, a process having type x c .x ∅ .0 implies that the process may send values on x twice, and that the first send is guaranteed to succeed (i.e., the sent value will be received by some process), while there is no such guarantee for the second send.
The transition semantics of behavioral types is unchanged; The attribute t is just ignored.
We revise the definitions of the subtype relation and the traces by using the following predicate disabled(A, S).Intuitively, this means that A describes a process that may get blocked without accessing any resources in S. Definition 5.5.disabled(A, S) is the least binary relation between extended behavioral types and sets of variables closed under the rules in Figure 7.
Definition 5.6.The set etraces x (A) of extended traces is: {x}) means that ξ n may be the last access to x, so that ↓ is attached to the sequence ξ 1 • • • ξ n .By definition, etraces x (A) is prefix-closed.Definition 5.7.A 1 ≤ A 2 is the largest relation on closed behavioral types that satisfies the following properties: Note that by the definition, A 1 ≤ A 2 implies etraces x (A 1 ) ⊆ etraces x (A 2 ).The typing rules are the same as those in Section 3, except for the rules shown in Figure 8.The only changes are that attributes have been attached to (ET-Out) and (ET-In), and that traces x (A↓ {x} ) has been replaced by etraces x (A↓ {x} ) in (ET-NewR).

Γ ⊲ pl
Figure 8: Typing Rules for Partial Liveness An important invariant maintained by the typing rules is that the type of an input/output process is annotated with c only if the process itself is annotated with c.For example, we cannot derive x : chan ⊲ pl x ∅ : x c .
The following theorem states the soundness of the extended type system.
Theorem 5.8.If well annotated (P ) and ∅ ⊲ pl P : A, then P is partially live.
Proof.We make use of three lemmas.The first two show that typing and well-annotatedness are preserved by reduction.The third means that the type of a process properly captures the possibility of the process being blocked.2. Type Inference.The type inference algorithm for the extended type system is almost the same as the algorithm for the basic type system discussed in Section 4. The only changes are: • In the constraint generaltion algorithm PT, attribute annotations for input and ouptut processes are propagated to types.For example, the case for output processes becomes: • The constraint traces x (A) ⊆ Φ is replaced by etraces x (A) ⊆ Φ.The second change forces us to adjust the reduction of the constraint to the reachability problem of Petri nets (recall step 3 of the algorithm in Section 4).First, we need to use eptraces(N A,x ) defined below, which corresponds to etraces x (A), instead of ptraces(N A,x ) in the reduction.Definition 5.10.eptraces(N A,x ) is the set where m I is the initial marking of N A,x .pdisabled(m, S) means that disabled(A, S) holds for the behavioral type A expressed by m.
Second, the construction of an automaton needs to be adjusted so that it accepts extended traces.For example, the automaton used in the explanation of Step 3-2 in Section 4 is replaced by the one that accepts IR * C ↓.
With these changes, the validity of a constraint etraces x (A) ⊆ Φ is reduced to the reachability problem of a Petri net N A,x M Φ where composition of a Petri net N A,x and an automaton M Φ is defined in the same manner as Definition 4.3.

Implementation
We have implemented a prototype resource usage analyzer based on the extended type system described in Section 5. We have tested all the examples given in the present paper.The implementation can be tested at http://www.yl.is.s.u-tokyo.ac.jp/~kohei/usage-pi/.
The analyzer takes a pi-calculus program as an input, and uses TyPiCal [12] to annotate each input or output action with an attribute on whether the action is guaranteed to succeed automatically (recall the syntax of extended processes in Section 5).The annotated program is then analyzed based on the algorithm described in Section 4.
The followings are some design decisions we made in the current implementation.We restrict the resource usage specification (Φ) to the regular languages, although in future we may extend it based on Remark 4.6.In Step 3-1 of the algorithm for checking etraces x (A) ⊆ Φ, we blindly approximate A by pushing all of its ν-prefixes to the top-level.In future we might utilize an existing model checker to handle the case where A is already finite.In Step 3-4 for solving the reachability problems of Petri nets, we approximate the number of tokens in each place by an element of the finite set {0, 1, 2, "3 or more"}.That approximation reduces Petri nets to finite state machines, so we can use BDD to compute an approximation of the reachable states.
Figure 9 shows a part of a successful run of the analyzer.The first process (on the second line) of the input program runs a server, which returns a new, initialized resource.We write ! and ?for output and input actions.The resource access specification is here expressed by the number 1 of newR 1, x, which refers to the built-in specification (I(R + W ) * C ↓) # .The second process runs infinitely many client processes, each of which sends a request for a new resource, and after receiving it, reads and closes it.The third process (on the 6th line) is a tail-recursive version of the replicated service in Example 2.9.Here, a boolean is passed as the first argument of s instead of an integer, as the current system is not adapted to handle integers; it does not affect the analysis, since the system ignores the value and simply inspects both branches of the conditional.Note that the program creates infinitely many resources and has infinitely many states.The first output is the annotated version of the input program produced by TyPiCal, where !! and ?? are an output and an input with the attribute c (recall Section 5).
The remaining part shows the trace inclusion constraint and the constructed Petri net.The final line reports that the verification has succeeded, which implies that both the safety property (in Section 3) and the partial liveness property (in Section 5) are satisfied.

Related Work
Resource usage analysis and similar analyses have recently been studied extensively, and a variety of methods from type systems to model checking have been proposed [5,6,7,11,1,17,24].However, only a few of them deal with concurrent languages.To our knowledge, none of them deal with the partial liveness property (or the total liveness property) that we discussed in Section 5. Nguyen and Rathke [20] propose an effect-type system for a kind of resource usage analysis for functional languages extended with threads and monitors.In their language, neither resources nor monitors can be created dynamically.On the other hand, our target language is π-calculus, so that our type system can be applied to programs that may create infinitely many resources (due to the existence of primitives for dynamic creation of resources: recall the example in Figure 9), and also to programs  that use a wide range of communication and synchronization primitives.Capability-based type systems can deal with concurrency to a certain degree ([5], Section 4.2), by associating each resource with a unique capability to access the resource.The type system can control the resource access order, by ensuring the uniqueness of the capability and keeping track of what access is currently allowed by each capability.In this approach, however, resource accesses are completely serialized and programmers have to care about appropriately passing capabilities between threads.Capability-based type systems [5,6] also require rather complex type annotations.Igarashi and Kobayashi's type system for resource usage analysis for λ-calculus [11] can be extended to deal with threads, by introducing the following typing rule: Here, Γ 1 ⊗ Γ 2 describes resources that are used according to Γ 1 and Γ 2 that are used in an interleaving manner.However, it is not obvious how to accurately capture information about possible synchronizations between M 1 and M 2 .
Model checking technologies [2] can of course be applicable to concurrent languages, but they suffer from the state explosion problem, especially for expressive concurrent languages like π-calculus, where resources and communication channels can be dynamically created and passed around.Appropriate abstraction must be devised for effectively performing the resource usage analysis for the π-calculus with model checking.Actually, our typebased analysis can be considered a kind of abstract model checking.The behavioral types extracted by (the first two steps of) the type inference algorithm are abstract concurrent programs, each of which captures the access behavior on each resource.Then, conformance of the abstract program with respect to the resource usage specification is checked as a model checking problem.It would be interesting to study a relationship between the abstraction through our behavioral type and the abstraction techniques for concurrent programs used in the model checking community.From that perspective, an advantage of our approach is that our type, which describes a resource-wise behavior, has much smaller state space than the whole program.In particular, if infinitely many resources are dynamically created, the whole program has infinite states, but it is often the case that our behavioral types are still finite (indeed so for the example in Figure 9).The limitation of our current analysis is that programs can be abstracted in only one way; on the other hand, the usual abstract model checking techniques refine abstraction step by step until the verification succeeds.
Technically, closest to our type system are that of Igarashi and Kobayashi [10] and that of Chaki, Rajamani, and Rehof [3].Those type systems are developed for checking the communication behavior of a process, but by viewing a set of channels as a resource, it is possible to use those type systems directly for the resource usage analysis.We summarize below similarities and differences between those type systems [10,3] and the type system in the present paper.
(1) Whether types are supplied by the programmer or inferred automatically: Types are inferred automatically in Igarashi and Kobayashi's generic type [10] and the type system of the present paper, but the type of each channel must be annotated with in Chaki et al.'s type system.The annotated type contains information about how the values (channels, in particular) sent along the channel are used by senders and receivers, and that information is used to make the type checking process compositional.For the purpose of the resource usage analysis discussed here, we think that it is a burden for programmers to declare how channels are going to be used, since their primary concern is how resources are accessed, not channels.Ideal would be to allow the user to specify some types and infer the others, like in ML.For that purpose, we need to develop an algorithm to check the conformance A ≤ B of an inferred type A to a declared type B. That seems generally harder to decide than the trace inclusion constraint traces x (A) ⊆ Φ, but we expect to be able to develop a sound algorithm by properly restricting the language of declared types.
(2) The languages used as behavioral types: All the three type systems use a fragment of CCS as the language of types to check cross-channel dependency of communications.The types in Igarashi and Kobayashi's generic type system for the π-calculus [10], however, lacks hiding, so that their type system cannot be applied to obtain precise information about resource usage.In fact, their analysis would fail even for the program in Example 2.8.Chaki et al.'s type system does use hiding, but lacks renaming as a constructor.Without the renaming constructor, the most general type does not necessarily exist, which hinders automatic type inference (recall Remark 3.12).
(3) Algorithms for checking the conformance of inferred types with respect to specifications: In Igarashi and Kobayashi's generic type system, how to check conformance of inferred types with respect to the user-supplied specifications was left open, and only suggested that it could be solved as a model checking problem.In Chaki et al.'s type system [3], the conformance is expressed as A |= F (for checking the global behavior, where F is an LTL-formula) and A ≤ A ′ (for checking the conformance of declared types with respect to inferred types).In their type checker PIPER [3], those conditions are verified using SPIN, so that A is restricted to a finite-state process.Corresponding to the conformance check of the above work is the check of trace inclusion constraints traces x (A) ⊆ Φ.Our algorithm based on the reduction to Petri nets works even when A has infinite states.
(4) The guaranteed properties: Both Igarashi and Kobayashi's generic type [10] and the extended type system of the present paper can guarantee a certain lock-freedom property, that necessary communications or resource accesses are eventually performed (unless the whole process diverges), while Chaki et al.'s type system and the type system in Section 3 of the present paper do not.The guaranteed properties depend on the choice of the language of behavioral types and the subtyping relation.In the latter type systems, the ordinary simulation relation is used, so that a process's type describes only an upper-bound of the possible behavior of the process, not a lower-bound of the behavior like a certain resource access is eventually performed.Rajamani et al. [8,23] recently introduced a more elaborate notion of simulation relation called "stuck-free conformance."Even with the stuck-free conformance relation, however, their type system [3] still cannot guarantee the lack of deadlock-freedom of a process.On the other hand, by relying on an external analysis to check deadlock-freedom, the extension in Section 5 keeps the typing rules and the subtyping relation simple, while achieving the guarantee that necessary resource accesses are eventually performed unless the whole process diverges.
Kobayashi's type systems for deadlock-freedom and livelock-freedom [16,14,15] and its implementation [12] form the basis of the extended type systems for partial and total liveness properties discussed in Section 5, and are used for producing well-annotated programs.Conversely, the behavioral types introduced in this paper can be used to refine the type systems for deadlock-freedom and livelock-freedom.Yoshida and Honda have also studied type systems that can guarantee certain lock-freedom properties [25,9,26].So, their type systems can also be used for checking whether programs are well-annotated in the sense of Section 5.
In Section 5, we have utilized the existing analysis for deadlock-freedom to enhance the result of the resource usage analysis.Other type systems for concurrent languages may also be useful.For example, the type system for atomicity [4] can be used to infer the atomicity of a sequence of actions in a source program.By using the atomicity information, we may be able to reduce the state space of behavioral types and check the trace inclusion relation etraces x (A) ⊆ Φ more efficiently.

Conclusion
We have formalized a type system for resource usage analysis and proved its soundness.We have also developed a sound (but incomplete because of the last phase for deciding the trace inclusion relation traces x (A) ⊆ Φ) algorithm for it in order to liberate programmers from the burden of writing complex type annotations.We have also implemented a prototype resource usage analyzer based on the algorithm.
There remains much future work.It is necessary to assess the effectiveness of our analysis, including the design of the type system and the algorithm for deciding the trace inclusion relation traces x (A) ⊆ Φ, in more detail, and refine the analysis if necessary.It is also necessary to make the analyzer more user-friendly, by devising a method for generating comprehensive explanation of the verification result; currently, the analyzer gives only a yes/no answer.Extensions of the type system to deal with other typical synchronization primitives like join-patterns and internal choice is also left for future work.

3. 2 .
Semantics of behavioral types.We give a labeled transition relation l −→ for behavioral types.The transition labels l (distinct from the reduction labels L of Definition 2.4) are l

l−→
on behavioral types is the least relation closed under the rules in Figure3.We write =⇒ for the reflexive and transitive closure of τ a

Figure 3 :
Figure 3: Transition semantics of behavioral types

Figure 6 :
Figure 6: A Type Inference Algorithm

Figure 7 :
Figure 7: The definition of disabled(A, S)

Figure 9 :
Figure 9: A Sample Run of the Analyzer.