Application and Experimental Evaluation of State ... - Semantic Scholar

10 downloads 50340 Views 282KB Size Report
based techniques for the automated deadlock analysis of Ada programs. Our experiments ..... translation from Ada source code to a Petri net. Although some ...
Application and Experimental Evaluation of State Space Reduction Methods for Deadlock Analysis in Ada S. Duri

U. Buy

R. Devarapalli

S.M. Shatz

Concurrent Software Systems Lab University of Illinois at Chicago Email: [email protected] Abstract An emerging challenge for software engineering is the development of methods and tools to aid design and analysis of concurrent and distributed software. Over the past few years, a number of analysis methods that focus on Ada tasking have been developed. Many of these methods are based on some form of reachability analysis, which has the advantage of being conceptually simple, but the disadvantage of being computationally expensive. In this paper, we explore the effectiveness of various Petri net based techniques for the automated deadlock analysis of Ada programs. Our experiments consider a variety of state space reduction methods both individually and in various combinations. The experiments are applied to a number of classical concurrent programs as well as a set of “real-world” programs. The results indicate that Petri net reduction and reduced state space generation are mutually beneficial techniques, and that combined approaches based on Petri net models are quite effective, compared to alternative analysis approaches.

1 Introduction In both the research and the development communities there is growing interest in concurrent and distributed computing. Much of the hardware technology exists to support practical and economical distributed computing systems. In addition, distributed operating systems concepts are quickly coming into focus and many distributed resource management issues are relatively well understood. Unfortunately, software engineering, in the broader sense, still faces many difficult challenges when applied to distributed systems. In short, distributed software engineering is a bottleneck for achieving widespread use of distributed computing. Development of distributed software requires new techniques to address the unique problems that concurrency and distribution bring to the areas of requirement specifications, design, and testing [24]. In this paper, our interest is in testing of distributed software. In particular, we consider automated support for static testing, or analysis, of concurrent programs that use the message passing paradigm for

1

process communication. As noted by Osterweil and Clarke [22], there is a critical need for further research into testing of concurrent, distributed, and real-time software systems. We agree with this conclusion, and we go a step further—we believe that there is a critical need for experimentally-based research and evaluation of techniques for concurrent software analysis. This paper presents and discusses experimental research on techniques and tools for automated deadlock analysis of concurrent software written in the Ada language. Over the past few years, a number of research investigations have been initiated for static analysis of concurrent and distributed software. Like our work, many existing approaches have focused on Ada as a target language for concurrent program descriptions. Among these investigations are the constrained expressions method [1, 2, 6], the concurrency analysis tool set (CATS) [36], which is based on Taylor’s concurrency history graph concept [29] and on the task interaction graph model (TIG) of Long and Clarke [15], the tasking deadlock detection method of Masticola and Ryder [16], the temporal logic based techniques of Karam and Buhr [14], the process algebra based method of Yeh and Young [33, 34], and the Petri net based methods used in the tasking-oriented toolkit for the Ada language (TOTAL) [21, 26]. Because of the computational complexity of concurrency analysis, in general all existing approaches appear to be very sensitive to the size of the program being analyzed in terms of the use of concurrency constructs and the number of asynchronous processes. Reachability-based analysis techniques have received considerable attention [14, 29, 36]. An advantage of these techniques is that they are relatively simple from a conceptual viewpoint. By enumerating the reachable program states, reachability-based techniques can support various kinds of analysis, such as detection of potential deadlock or starvation. Finally, these techniques have been successfully combined with other analysis approaches, such as symbolic execution [35] and linear algebra [1, 21]. Unfortunately, the applicability of reachability-based techniques is limited by the state explosion problem [23, 28]. In recent years, several methods have been defined with the aim of improving the tractability of reachability-based analysis. Some methods are aimed at model reduction, which involves simplifying a model of a concurrent program while preserving crucial concurrency properties, such as the possibility of deadlock, in the reduced model [15, 30]. Typically, the reduction in model size results in a significant decrease in the size of the corresponding state space. Other methods exploit potential parallelism [11, 31] or symmetries [17, 27] that might exist in the program being analyzed to avoid generation of the full state space. Another idea for limiting the states that are explicitly enumerated during state space generation is to exploit semantic information for groups of events contained in a program model. This idea is used in Section 4.2, where we discuss how to induce atomicity on some sequences of events belonging to a given group: Whenever an event from the group is executed, other events from the group are immediately executed. 2

The atomic execution of events from a group can eliminate many interleavings of these events with events from different groups in the resulting state space. Finally, compositional methods are aimed at performing concurrency analysis in a modular fashion [34]. Each of the above methods can, in some cases, significantly reduce the complexity of concurrency analysis; however, all may fail to produce significant reductions depending on the program being analyzed. In this paper, we explore the effectiveness of various existing state space reduction methods when they are used to support automated deadlock analysis of Ada programs. In particular, we seek to detect situations in which all asynchronous processes (i.e., tasks in Ada terminology) in a program are blocked while mutually waiting for each other to perform some action. This type of global deadlock is conceptually easy to define and corresponds to a terminal state in the state space. A primary goal of our work is to show the power of various combinations of methods. Unfortunately, theoretical investigations of the methods offer little insight into their relative strengths because, in general, the worst case complexity of reachability-based analysis remains exponential (in the number of tasks) even after the methods are applied. For this reason, we have implemented several methods and run experiments with various concurrent programs. In addition, in appropriate cases we have compared our experimental results with similar results obtained by alternative analysis approaches. The analysis methods we consider are based on using Petri nets for modeling interprocess communication in Ada programs [20]. This approach allows us to combine the net reduction method of [30] with any one of three reduced state space generation techniques, namely stubborn sets [31], sleep sets [11], and net symmetry [27]. We will also discuss an additional method that is based on the atomic execution of event groups [5]. Our experimental results have provided valuable insights. For example, a comparison between the combined methods and the individual methods indicates that in most cases the strength of the combined methods cannot be matched by any one method alone. We conclude that Petri net reduction and reduced state space generation methods are mutually beneficial with respect to the effectiveness of the analysis. In addition, when we compare our integrated approach with alternative analysis approaches, we find that our approach is quite effective. Some preliminary results using our integrated approach appeared in a previous paper [8]. This paper extends the previous paper in several important ways. First, we have enhanced the net reduction, sleep sets, stubborn sets and net symmetry methods. As a result, our tools can analyze much larger systems than we reported in [8]. Second, we have extended the set of concurrent programs that we evaluate and analyze automatically. Finally, we provide a more comprehensive discussion of our approach and of our experimental results. This paper is organized as follows. In Section 2 we briefly discuss Petri nets. In our work Petri nets serve 3

as the formal model for Ada tasking programs and provide a uniform foundation for the analysis methods we develop and study. In Section 3 we introduce Ada nets, which are Petri net models of Ada tasking programs. We explain some key points about Ada net generation, which is a fully automated process. In Section 4 we present the various optimization methods we have developed and studied. All methods seek to reduce the size of the final state space that is generated for performing deadlock analysis. Section 5 discusses our experiments with the optimization methods when they are used individually and in various combinations. An evaluation of our experimental results is presented in Section 6. Finally, some conclusions and future research directions are given in Section 7.

2 Petri Nets and Reachability Analysis Petri nets are formal, graph-based models for concurrent systems. The Petri net formalism is explicitly equipped to model key features of concurrent and distributed programs such as asynchronous execution, communication, synchronization, and nondeterminism. Of particular interest to us is the fact that Petri nets are theoretically mature, supported by a number of available tools, and the topic of continued basic and applied research. In this section we give a brief overview of Petri nets. The reader is referred to [20] for further details. An ordinary Petri net is a 4-tuple N

P; T; F; M0), where P

= (

is a finite set of places,

T is a finite

set of transitions, F is an arc set, and M0 is an initial marking, that is, an initial assignment of tokens (i.e.,

markers) to each place p 2 P . Given an arc f from a place p (a transition t) to a transition t (a place p), p is said to be an input (output) place for t, and t is an output (input) transition for p.

State changes are carried out by firing enabled transitions. In an ordinary net a transition is enabled when all its input places have at least one token. When an enabled transition t is fired, a token is removed

from each input place of t and a token is added to each output place of t; this gives a new state (i.e., a new marking). A net marking is dead if there are no enabled transitions. A Petri net is safe if for all reachable markings no place has more than one token. Our approach to deadlock detection in Ada programs is based on the following two steps: 1. An input Ada program is translated to a safe and ordinary Petri net, called an Ada net. 2. A reachability graph of the Petri net is built. If the graph contains any terminal nodes (i.e., nodes with no outgoing arcs), then we conclude that the input program can deadlock. The reachability graph of a Petri net captures the dynamic behavior of the net. The root node of the graph represents the initial state (i.e., the initial marking) of the net, directed arcs represent transition firings, 4

and terminal nodes represent dead markings. The basic algorithm for the construction of the reachability graph of a safe and ordinary Petri net is straightforward [20]. Each graph node is defined by a unique marking that corresponds to a reachable state.

n0 representing the initial marking M0 . The following expansion procedure is subsequently applied in breadth-first order to every created node n , starting from n0 .1 First, the transitions that are enabled in n are found. If no such transitions exist, n is a terminal node and a deadlock is reported. Otherwise, for each enabled transition t , the node n that is reached by firing t from n is defined. The marking of n is obtained from the marking of n by removing a token from every input place of t , and by adding a token to every output place of t . If a node n with the same marking as n is already in the graph, an arc from n to n is added to the graph; otherwise, n is added to the graph with an arc from n to n . The algorithm first creates the initial graph node

i

i

i

i;j

i

j

j

i

i;j

i;j

j

i

i

i;j

k

k

j

j

The reachability graph construction ends when all created nodes have been expanded. Note that this algorithm always terminates because the reachability graph of a safe Petri net is finite. In general, however, the graph can be quite large (i.e., the size of the graph is frequently exponential in the number of processes contained in the input program).

3 Modeling Boolean Variables in Ada Nets Conceptually, it is straightforward to translate an Ada program into a Petri net that captures the task interactions. The result of the translation is a special Petri net, which we call an Ada net. By construction, Ada nets are safe and ordinary Petri nets [26]. In an Ada net, only places that represent the beginning of a task’s control flow contain a token in the initial marking. Our approach for translating Ada tasking behavior into Petri nets is based on the method described in [26]. The translation process is conservative in that all task interactions and possibilities for task blocking are explicitly modeled. Thus, no deadlocks in the program code are hidden by the translation process. Our Ada nets exhibit a uniform structure because similar subnets model different occurrences of a given construct in an Ada program. For instance, the subnet modeling a communication (or rendezvous in Ada terminology) between two tasks generally consists of 6 places and 4 transitions. In addition, each place and transition in this subnet plays a well-defined role in terms of modeling the behavior of a rendezvous. We exploit this fact by associating semantic information with each place in an Ada net. In particular, we distinguish among different kinds of nodes in an Ada net. For example, in the rendezvous subnet the place 1

The only exception to graph construction in breadth-first order is given by the sleep set method. In the implementation of this method we have followed the algorithm defined by Godefroid, which uses depth-first order [11].

5

signifying that a task is ready to accept an entry call is an accept place. Note that the semantic information does not affect the behavioral properties of Ada nets; however, this information is exploited when we do Petri net reduction and also during reachability graph generation. A limitation of the approach described in [26] is that it does not model the effects of variable values on the flow of control in the program being analyzed. As a result, the Ada net derived from an input program may contain spurious behaviors (i.e., behaviors that are not possible in the program). To obviate this disadvantage we have extended the translation method of [26] and we have implemented a method for modeling boolean variables in Ada nets. Our interest is in modeling those boolean variables that can affect the tasking behavior of a program. By tasking behavior, we mean the behavior with respect to task interactions or task blocking. So, for example, boolean variables in guards of selective wait statements are important for our analysis. Since variable modeling in Ada nets is not discussed in any other papers, we discuss this concept here. Other details of Ada net generation can be found in [26]. We model a boolean variable x by two places, namely a true place and a false place. In any reachable state, at most one of these places has a token. When a token is in the true place, x is true, and when a token is in the false place, x is false. If neither place has a token, the value of x is undefined. A portion of a Petri net representing the logical conjunction (x ^ y ) of two boolean variables x and y is

shown in Figure 1. The net consists of eight places and three transitions. Places ptx, pfx , pty , pfy are the true and false places for x and y. Places

p

i

p

t x y



and pfxy are the true and false places for the conjunction. Place

is used to control the firing of transitions corresponding to an evaluation of the conjunction. A token in

this place means that the conjunction must be evaluated. A token in place po means that the conjunction has been evaluated. This place is used as an input place for the segment of the Ada net that models the computations to be performed following the evaluation of the conjunction. All transitions in Figure 1 require that place

p

i

have a token in order to be enabled. In addition,

transition t1 is enabled only if both places ptx and pty have a token, meaning that both x and y are true. When

t1 fires, a token is returned to places p and p (in order to leave the value of x and y unchanged), and a token is added to place p  (meaning that the conjunction is true in this case). Transitions t2 and t3 are used to produce a token in place p  when the conjunction is false. They are enabled by a token in place p and a token in place p , respectively. When both places have a token (meaning that both x and y are false), either t2 or t3 fires nondeterministically, thus adding a token to p  . Finally, when one of the three transitions fires, a token is also added to place p and removed from place p . t x

t y

t x y

f x y

f x

f y

f x y

o

i

In addition to the above subnet for logical conjunction, we have defined similar subnets for logical disjunction; for assigning a value to a boolean variable; and for capturing the flow of control in alternative and iteration constructs of the Ada language. These techniques can handle arbitrary expressions involving 6

pi

p tx

p ty

p fx

t1

t2

p tx*y

po

p fy

t3

p fx*y

Figure 1: Petri net for logical conjunction of boolean values. boolean variables and boolean constants. In the modeling approach that we used for our experiments, logical conjunction and disjunction are always treated as binary operators in Ada nets. For instance, the boolean expression (a ^ b ^ c) is modeled by two subnets similar to the net shown in Figure 1. The first subnet computes expression

a ^ b), and

(

the second subnet computes the conjunction of the first result with c. As we discovered, this approach to

modeling n-ary boolean expressions can have an adverse effect on the symmetry method; however, this

effect can be avoided by choosing a suitable order for the variables appearing in an n-ary boolean expression. This phenomenon is further discussed in Section 6.

4 Optimization Methods We consider the following methods for improving the tractability of reachability-based deadlock detection in Ada programs: Petri net reduction [30]; atomic expression evaluation [5]; stubborn sets of Petri net transitions [31]; sleep sets of Petri net transitions [11]; and a net symmetry method [27]. We developed the atomic expression evaluation method specifically for use in Ada net analysis—the other methods are based on existing and more general Petri net techniques. In addition, we have also developed heuristics (discussed in Section 4.5) to use in conjunction with the net symmetry method in order to make this method more practical than its original formulation as described in [27]. The reader should note that this paper’s prime interest is not in the details of these existing methods, but rather in the evaluation and understanding of the effectiveness of the methods when used specifically 7

for automated deadlock analysis of Ada tasking programs. Consequently, in the next subsections we give a summary of the main aspects of each method rather than detailed descriptions of the methods.

4.1 Net reduction method Net reduction, when applied to Ada nets, is aimed at transforming the Petri net model of an Ada program into a net with a smaller state space, while preserving the possibility of deadlock in the reduced net. This method is applied after the Ada net corresponding to an input program has been generated and before the reachability graph is constructed. The Petri net reduction activity has different goals and uses different algorithms than the activity of translation from Ada source code to a Petri net. Although some reductions could be applied during the translation process (i.e., when building an Ada net), in general the bulk of the reduction activity is more easily applied as a separate step. Moreover, the translation activity is aimed at building a net model that preserves all task interaction events specified in the source program so that the model can support general concurrency analysis. When deadlock detection is the specific goal of the analysis (which is the case for the work reported here), net reduction is used to produce a new net model that has the same deadlock properties as the original net and a smaller state space. In most of the examples we studied, we found that the reduced Ada net is quite different from the unreduced net and does not model all task interactions. For instance, Figure 2 shows the reduced Ada net produced automatically from an Ada implementation of the dining philosophers problem for three philosophers. Places

p11, p12, p21, p22, p31, and p32 are initially marked.

This net is not easily interpreted

as a net model for the dining philosophers problem. For example, although there is a terminal state (corresponding to the deadlock that occurs when all philosophers pick up their left fork), there are no transitions that specifically model the events of picking up or putting down a right fork. Berthelot has defined a large set of reduction rules for Petri nets and a set of sufficient conditions for a place to be redundant in an ordinary Petri net [3]. By definition a redundant place can be removed from a Petri net along with its incident arcs, without affecting the number of reachable states for the net. We identify and remove redundant places in order to allow other reduction rules to be subsequently applied. We do not use all of Berthelot’s rules because some rules have high computational complexity. In general our reduction rules fall into two categories. Rules in the first category are applicable to general Petri nets. These rules were originally proposed in [3] and subsequently extended in [30]. Consider, for instance, the pre-fusion of transitions rule. This rule can merge a transition t with a set of transitions

s1 ; : : :; s , if t is connected to each s by a place p that is the only output of t and that is one of the inputs of s . The effects of this rule when n is equal to two are shown in Figure 3. Rules in the second category n

i

i

8

p

p

11

p

12

p

21

p

22

p

13

23

p

p

32

31

p33

Figure 2: Reduced Ada net of dining philosophers problem with 3 philosophers. take advantage of the specific structure of Ada nets. For example, there are rules that identify and remove redundant places that arise in some modeling situations. In particular, one rule identifies redundant place nodes for certain cases involving two accept statements. This situation occurs, for instance, in the dining philosophers program when a fork task accepts a call on the up entry followed by a call on the down entry. The complexity of our Ada net reduction method is polynomial in the size of the input Ada net. See [25] for a proof and for further details on the reduction rules.

4.2 Atomic expression evaluation The atomic expression evaluation method exploits semantic information contained in an Ada net during reachability graph construction. In particular, this method seeks to minimize the number of states resulting from the evaluation of boolean expressions with multiple operators. Consider, for instance, the boolean

E = (a ^ b) _ (c ^ d), where a, b, c, and d are boolean variables locally defined in a task A. We model this expression using a subnet N consisting of three components. The first component, which is similar to the net shown in Figure 1, computes the conjunction of a and b. Two places, p ^ and p ^ , hold the result of the conjunction. The second component computes the conjunction of c and d into p ^ and p ^ . The third component computes the disjunction of the two intermediate results into places p and p . As a result, the evaluation of N always requires three transition firings, one for each operator in E. expression

E

t a

f

b

a

t c

f c

t E

d

f

E

E

9

b

d

t

p ts1 s1

ts2

s2

Figure 3: Transition pre-fusion reduction rule for Petri nets. The firing of three transitions in subnet NE may significantly increase the number of states in the graph, because in general these transitions can be interleaved arbitrarily with the firing of transitions not in

N

E

.

Moreover, the two transitions performing the evaluation of the conjuncts in E can be fired in either order, further exacerbating the state explosion effect. This effect can be avoided, however, for the following reasons. First, since the boolean expressions we are considering are free of side effects, the value of an expression does not depend on the order in which its components are evaluated. Second, if we assume that all variables appearing in an expression are local within a task, then the value of a variable is not affected by the firing of transitions of other tasks. Third, only the value of expression E is relevant to the analysis (as opposed to the intermediate values of subexpressions appearing in E). To eliminate the intermediate states and the unnecessary interleavings from our state spaces, we partition the transition set of a Petri net into groups. Each boolean expression in the program is associated with a group containing all transitions that perform the evaluation of that expression. An additional group of transitions is defined to contain all the transitions that are not a part of boolean expression subnets. Finally, we add the following rule to our reachability graph generation algorithm: Suppose that a state x, which enables a boolean transition t, must be expanded. If t is fired, only enabled transitions belonging to t’s group are fired next until no transition from the group is enabled. Only the last state, which has the result of the evaluation of the boolean expression, is stored in the reachability graph. This optimization method conforms to the principle of virtual coarsening [31]. The idea underlying virtual coarsening is that sequences of internal actions performed by a process independently of other 10

t2

t1

t3

Figure 4: Example of a Petri net containing independent transitions. processes in a concurrent program can be viewed as a single action without loss of information. Through our experiments with the atomicity method, we have observed that this method can result in a reduction in state space size when boolean expressions are present in the Ada source code being analyzed [5]. In addition, the atomicity method does not have a significant effect on the time required to generate the state space, even when no state space reductions are achieved (i.e., when the Ada source code contains no boolean expressions). For this reason most of the experiments discussed in Section 5 use the atomicity method; however, some experiments without this method are reported in Subsection 5.1.4. The interested reader is referred to [5] for additional details on the impact of this method on reachability graph construction.

4.3 Stubborn set method It has long been recognized that modeling concurrency by all possible interleavings of transition firings is the main contributor to the state explosion problem. Partial order methods seek to identify independent transitions in order to avoid generating unnecessary interleavings. Two transitions are independent when the firing of one transition has no bearing on the fireability of the other transition and vice versa. When two independent transitions are enabled, there are two possible execution sequences which differ only by the order in which these transitions are fired. In either case, both sequences lead to the same end state. Consider, for instance, the simple Petri net shown in Figure 4. This net has six possible firing sequences (e.g., t1 t2 t3 and t2 t3 t1 ). All sequences lead to the same state, however. For the purpose of deadlock analysis, it is therefore sufficient to explore only one of the possible sequences. Both Valmari’s stubborn set method and the sleep set method of Godefroid and Wolper are built around the concept of independent transitions [11, 31]. The stubborn set method is discussed now, and the sleep set method is discussed in the next subsection. The goal of the stubborn set method is the automatic generation of a reduced state space of a vari-

11

Figure 5: Unreduced and reduced state spaces of the Petri net shown in the previous figure. able/transition system, such as a Petri net. The reduction in state space size is achieved by partitioning, in each reachable state, the transition set T of the Petri net into two independent subsets, namely the stubborn set and the nonstubborn set. When expanding a graph node x during reachability graph construction, only enabled transitions that belong to the stubborn set are considered. As a result, only a portion of the state space of the Petri net is explicitly included in the resulting reachability graph. Formal conditions for a transition subset to be stubborn in a given net state are given in [31]. In a nutshell, the conditions are aimed at enforcing the following criteria. First, a stubborn set must contain at least one enabled transition. Second, an enabled transition contained in a stubborn set cannot be disabled by the firing of nonstubborn transitions (i.e., transitions in the nonstubborn set). Finally, a disabled transition contained in a stubborn set should not become enabled by firing only nonstubborn transitions. In general, a given net state can be associated with multiple stubborn sets (i.e., multiple ways of partitioning the transition set into a stubborn set and a nonstubborn set). In the state shown in Figure 4, the singleton sets ft1 g, ft2 g, and ft3 g are all stubborn because each set satisfies the criteria that we just summarized. When a state has multiple stubborn sets, one of the stubborn sets is selected nondeterministically, and only the enabled transition contained in that set are fired. In the example, one of t1 , t2 , or t3 is selected nondeterministically. This strategy leads to the state space reduction shown in Figure 5. On the left-hand side is the full state space of the net shown in Figure 4. The right-hand side shows the state space that would be obtained by applying the stubborn set method. Valmari showed that the effectiveness of the stubborn set method is often sensitive to how an implementation resolves the nondeterministic choice in a state. In our experiments, we have followed Valmari’s heuristic of selecting a stubborn set with a minimal number of enabled transitions [31]. An important strength of the stubborn set method is that it can take advantage of the parallelism that might exist in the specification of a concurrent system when constructing the state space of the system. This

12

t2

t1

t3

t4

Figure 6: Example of a confusion situation in a Petri net. is so because independent transitions in a Petri net model generally correspond to events that can occur concurrently in the underlying system. When a Petri net model contains a high degree of parallelism, this method can result in a dramatic reduction in the number of states that are generated explicitly. In some cases, the size of the state space can be reduced from exponential to linear in the number of processes in the program. A weakness is that this method can be affected by slight variations in a problem description. In particular, we noticed that stubborn sets are sensitive to the presence of redundant places in a Petri net model. For example, when we applied the stubborn set method to a commonly used Petri net for the dining philosophers problem (see for instance [32]), we generated (3n2 ? 3n + 2) states [8], which is consistent with Valmari’s results [31]. Yet, for a net that is similar, except for using two places instead of one place for modeling each fork, the number of states generated using stubborn sets is exponential in the number of philosopher tasks. The extra places in this case are redundant. Therefore, they have no impact on the number of states in the full state space; however, their presence in the net causes transitions that are independent in the original net to become dependent in the net with the redundant places. This fact dramatically affects the size of the state space obtained by stubborn sets.

4.4 Sleep set method Like the stubborn set method,the sleep set method seeks to avoid generating multiple sequences of transitions firings, if the sequences lead to the same state. The theory and the transition selection mechanism underlying

13

the sleep set method are different from the case of stubborn sets, however. In [11] Godefroid and Wolper give an algorithm for building a reduced reachability graph of a finite state system. The algorithm associates a sleep set

S

x

of enabled transitions with each state x. Transitions in

successors of x. Set

S

x

S

x

are not fired when finding the

is defined in such a way that firing sequences that include transitions in

S

x

are

explored at some other stage of reachability graph construction. Sleep sets play an important role in cases of confusion, which occurs when an enabled transition conflicts (i.e., shares an input place) with at least one disabled transition. A case of confusion appears in Figure 6. In the state shown, the enabled transition t1 conflicts with a

disabled transition, t4 . Suppose that t1 is to be fired in the state shown. In this case, the sleep set method

t2 also be fired even though this transition does not conflict with t1 . The reason for firing t2 is that the firing of t2 enables t4 , which does conflict with t1 . If we did not fire t2 in the state shown, we would miss the possibility that t2 and t4 are fired instead of t1 . Consequently, the states reached by firing t1 and t2 must both be included in the reduced reachability graph. Suppose that x1 and x2 are the states reached by firing t1 and t2 respectively from the state shown in the figure. State x2 is included in the reduced reachability graph in order to explore the possibility that t1 becomes disabled by the firing of t2 and t4 . There is no point in firing t1 when expanding node x2 because the states reached by firing t1 are already in the graph (i.e., these states are explored by expanding x1 ). In this case, t1 is added to the sleep set of x2 in requires that

order to avoid including unnecessary states in the reduced reachability graph. As with stubborn sets, the main advantage of the sleep set method is that it can achieve dramatic reductions in the size of the reachability graph, depending on the amount of parallelism that might exist in an Ada program. Of course, the reduced graph has the same deadlock properties as the full reachability graph. Like stubborn sets, the sleep set method is also sensitive to the presence of redundant places in an Ada net. Additional details on applying sleep sets to protocol examples can be found in [13].

4.5 Net symmetry method The net symmetry method achieves reduction in the size of reachability graphs by detecting and exploiting symmetries that might exist in a Petri net [27]. This method is built around the notion of a symmetry function

. A symmetry function is a bijection on the node set Q of a Petri net—Q is the union of the place set P and the transition set T of the net. In the case of ordinary Petri nets, such as our Ada nets,  must satisfy the following properties. First, the image q 0 of a node q is the same type of node (i.e., a place or a transition) as q. Second, suppose that there is an arc f from q to another node r. In this case, an arc f 0 must also exist from q 0 to r0, the images of q and r under  . Third, the initial marking of each place p and of its image p0 must be the same. 14

Symmetry functions are used to partition net nodes into equivalence classes. Two nodes

n1 and n2

belong to the same class if there is a symmetry function that maps n1 to n2 and n2 to n1 . For instance, in

the Ada net of Figure 2 places p11, p21, and p31 are equivalent because they can be mapped into each other by symmetry functions. Likewise, p12, p22, and p32 also belong to the same equivalence class, and so on.

As with net nodes, reachable states can also be partitioned into equivalence classes. Two states x1 and

x2 are equivalent if there is a symmetry function mapping every marked (unmarked) place of x1 to a marked (unmarked) place of x2. The key idea behind the net symmetry method is that only a single state from each state class needs to be included in the reduced reachability graph. Starke has shown that the resulting graph has the same deadlock properties as the full reachability graph [27].

The main problem underlying a practical application of this technique is its computational intractability. The problem of finding a symmetry function for a Petri net is an instance of the graph automorphism problem for a bipartite graph, which is known to be intractable. Starke has defined an algorithm for the generation of the reduced state space of a Petri net using net symmetry [27]. Whenever a new state is generated, the algorithm uses the symmetry functions of the net to determine whether the state is equivalent to any state generated previously. Starke’s algorithm is both sound and complete in that it exploits all symmetries in a Petri net. Unfortunately, the method in its full generality is difficult to apply in practice because of the complexity of finding all symmetry functions in a Petri net. Our Ada nets are generally too large for Starke’s algorithm to be applied directly. As a tradeoff, we implemented a symmetry method that is efficient but not guaranteed to exploit symmetries. In particular, we have identified new heuristics that can be used for the definition of node classes in the special case of Ada nets. In addition, we have defined two sufficient conditions for the existence of a symmetry mapping between two states x1 and x2. We discuss our heuristics first, followed by the sufficient conditions. Some heuristics that speed up the generation of node classes were originally defined by Starke for ordinary Petri nets [27]. These heuristics use information about the in degree and the out degree of a node, and about the type of a node (either a place or a transition) in order to guide the construction of node classes. We found that these heuristics were adequate for the concurrent programs we analyzed in [8]; however, the time required by the generation of node classes increased exponentially when we considered larger versions of the same programs. For this reason, we have defined and implemented an additional heuristic technique which uses semantic information associated with each place node in our Ada nets. In particular, we use the fact that a place class must contain places of the same kind (e.g., accept places). Our new heuristic substantially reduces the time required by our symmetry algorithm. We have also defined but not used another heuristic technique that 15

exploits the initial marking of a Petri net. This heuristic associates each node q in an ordinary Petri net with a nonnegative integer representing the shortest distance from the nearest place that is initially marked to q . We plan to use this heuristic in future experiments if the current method proves to be inadequate. The next issue in the generation of a reduced state space with net symmetries is the definition of symmetry functions mapping equivalent net states. Rather than generating symmetry functions explicitly, we only check two sufficient conditions on the existence of a symmetry function between two states. The first condition is based on the structure of an Ada net and makes explicit use of Ada net semantics. Since we use net places to identify positions in the flow of control of Ada tasks, we associate a unique task with each net place. In addition, we identify groups of symmetric tasks and their associated net places in the Ada programs we analyze. Finally, we consider the equivalence classes of places for a given Ada net. Roughly speaking, the structural condition states that, if a task A is symmetric to one or more other tasks, then A cannot have more than one place in each place class. Thus, if there is any place class with more than one place representing the control flow in a given task, then this task must not be symmetric to any other task in the input Ada program. The second (behavioral) condition for two states x1 and x2 to be equivalent is that each place class in the underlying Ada net has the same number of tokens in x1 and x2.

Similar to Starke’s algorithm, our algorithm for symmetry detection first generates equivalence classes of net nodes. Next, we check the structural condition on the place classes we obtain. If this condition is true, we use the behavioral condition to check whether two states are equivalent during reachability graph construction. If the structural condition is not true, we do not attempt to exploit any net symmetry during reachability graph construction. In this case, we ignore the detected symmetries. For our experiments, only the gas station program with multiple pumps results in the need to abandon the use of the detected symmetries. An alternative approach to symmetry detection is to have a programmer specify which processes are believed to be symmetric. For instance, a particular programming language construct (e.g., a task type in the case of the Ada language) could be used to specify multiple, identical processes. Our approach has several advantages with respect to programmer-defined symmetries. First, we do not require a programmer to specify when processes are symmetric. As a result, symmetric processes can be detected even if a programmer is not aware of the fact that they are symmetric. Second, in some cases our Ada nets satisfy Starke’s criteria for symmetry even though the processes contained in the corresponding programs are not identical. For instance, in many versions of the dining philosophers example, philosophers are found to be symmetric even though they differ in the combination of the forks that they use. Third, we can detect symmetries not only among different tasks but also among different constructs appearing in the same task. This happens, for instance, in the waveform generator system, one of the programming examples we 16

analyzed with our toolkit. Additional details are in Subsection 5.2.3.

4.6 Combinations of methods The above optimization methods are generally compatible with one another. The net reduction method can be combined easily with other optimization methods by simply reducing the Petri net model before applying any form of reachability graph generation. The remaining four methods can be combined with each other by defining a suitable algorithm for reachability graph construction. For example, to combine the net symmetry method with the stubborn set method, the reachability graph construction of the latter method should be changed in the following way. Each time a state is generated, we search the states generated previously for an “equivalent” state rather than for a state identical to the newly generated state. Finally, the atomicity method can be used with any combination of the other four methods. One exception to this state of affairs is given by the combination of sleep sets and net symmetry. As we explain in Section 6, these two methods cannot be combined as easily as stubborn sets and net symmetry.

5 Experiments Our experiments were executed using tools that are part of the TOTAL toolkit for concurrency analysis of Ada programs [26]. The front-end translator system (FETS) generates the Ada net from Ada source code. The net reduction tool (NRT) takes as input an Ada net produced by FETS and returns a reduced Ada net as output. Finally, the reachability graph builder (RGB) tool generates a reachability graph of the reduced Ada net. The portion of the TOTAL toolkit that is relevant to this paper is shown in Figure 7. Note that in the case of experiments that do not involve the Petri net reduction method, an Ada net produced by FETS is input directly into RGB. Our reachability graph builder tool, RGB, is rooted in a tool originally implemented at the University of California at Irvine [19]. We incorporated implementations of the optimization methods (stubborn sets, sleep sets, atomic expression evaluation, and net symmetry), as well as provided basic enhancements aimed at increasing efficiency of operation when storing very large state spaces. RGB now allows a user to select the optimization methods to be used in order to perform experiments with different combinations of the methods. Since we are only interested in deadlock detection, our experiments only store reachable states rather than the full reachability graph. We do count the reachability graph arcs and report this count in our experimental data. In order to assess the relative strengths of individual and combined optimization methods, we have selected a collection of “classical” examples of concurrent programs as well as a set of “real-world” problems. 17

Ada Program

Front - End Translator System

Reduced Ada Net

Net Reduction Tool

Reachability Graph Builder

Ada Net

Stubborn Sleep sets sets

(Reduced) Reachability Graph

Symmetry Atomic expression evaluation

Figure 7: Diagram of TOTAL toolkit. The classical examples include the dining philosophers problem, the readers and writers problem, and the gas station problem. We analyzed both deadlocking versions and deadlock-free versions of each problem. The real-world examples include a border defense system, a host buoy at sea system, and a waveform generator program. The goal of the experiments is to observe the impact of each optimization method, and of several combinations of the methods, on the overall effectiveness of the analysis. When appropriate, we provide comparative observations with respect to alternative analysis approaches. Each experiment carries out a fully automated analysis starting from an Ada program and returning a (possibly empty) set of deadlock states for the program. Some examples of net sizes (Ada net and reduced Ada net) are given for different experiments. All experiments were run on a Sun SPARCstation 2 with 64 MBytes of memory. The source code for each Ada program discussed in this paper is available from the authors unless otherwise noted. Except for Subsection 5.1.4, all experiments were run using the atomicity method for the reasons explained at the end of Subsection 4.2. The following combinations of the other four methods were typically run on each Ada program we considered: 1. No optimization method. 2. Each of the following methods alone: net reduction, stubborn sets, sleep sets, and net symmetry. 3. Net reduction combined with one of stubborn sets, sleep sets, and net symmetry.

18

4. Net reduction combined both with stubborn sets and with net symmetry. Combination 1 above generates the full reachability graph of an unreduced Ada net. Although this approach is in general impractical, we use these experiments as a reference point by which to measure the reductions provided by the other combinations. The experiments in combination 2 above give us an idea of the strength of the optimization methods when they are used individually. The experiments in combination 3 show the effects of combining the net reduction method with one of the three reduced state space generation methods. Combination 4 shows the effects of further integrating stubborn sets and net symmetry. Finally, in Subsection 5.1.4 we show the effects of the atomicity method on three examples of concurrent programs.

5.1 Classical examples 5.1.1

Dining philosophers

Dijkstra’s dining philosophers problem is a very well-known example of a concurrent program. A group of n philosophers is sitting around a table. The philosophers alternate between thinking and eating. Initially n forks are placed on the table between each pair of philosophers. In order to eat, a philosopher must first pick up both forks next to him. The forks are put down when the philosopher finishes eating and starts thinking. This problem is interesting because of the possibility of a circular deadlock. Deadlock may occur if all philosophers pick up their forks in the same order, say, the left fork followed by the right fork. In this case, there is one deadlock state corresponding to the situation in which all philosophers have picked up their left fork and are waiting for their right fork. We considered three cases of this problem. Deadlock is possible only in the first case. In the second case deadlock is avoided by switching the order in which one of the philosophers picks up his forks. In the third case a butler task is employed to guard the entry of the philosophers into the dining room. Thus, each philosopher gets permission from the butler task (by completing a call on a suitable entry) before picking up any of the forks. After eating, a philosopher informs the butler that he is leaving the dining room. The butler task ensures that at no time are all philosophers in the dining room. For this version, we used Ada source code with an “unrolled” butler task—the code contains nested select statements to simulate the effect of counting the number of philosophers entering the dining room. This idea was first suggested in [36]. We put the programs in this form because at present arbitrary scalar variables are not handled automatically by our translation tools. As we expected, our analysis reported no deadlocks for this example. For each case we ran multiple versions with different numbers of philosophers in order to evaluate the growth of the state space. In each version every philosopher and fork is implemented as an Ada task. Thus, in the first and second cases an n philosopher version has 2n tasks, and in the third case an n philosopher 19

phil 3

5

10

20

full 18900 79083 6

nrt 8 18 1 32 120 2 1024 7680 2 1048576 15728640 626

sym 2479 10000 3 82007 543125 164

sl 170 183 1 1648 1835 2

st 183 196 1 1456 1554 3 26799 28342 58

100

200

400

nrt+sym 4 8 1 6 19 2 11 64 2 21 229 4 101 5149 29 201 20299 126 401 80599 762

nrt+sl 6 9 1 10 17 2 20 37 2 40 77 4 200 397 27 400 797 111 800 1597 629

nrt+st 8 15 1 22 45 2 92 190 2 382 780 4 9902 19900 204 39802 79800 3334

nrt+st+sym 4 7 1 6 13 2 11 28 2 21 58 4 101 298 27 201 598 115 401 1198 681

Table 1: Data for dining philosophers problem with deadlock. version has (2n + 1) tasks. The results for the deadlocking version of the dining philosopher problem are reported in Table 1. Each row corresponds to a different problem size. Column 1 gives the number of philosophers in the problem, and the remaining columns give reachability graph data obtained with different combinations of optimization methods. In particular, column 2 (full) corresponds to full reachability graph generation with no optimization method used. Column 3 (nrt) corresponds to net reduction followed by full reachability graph generation; column 4 (sym) corresponds to reduced state space generation using net symmetry; column 5 (sl) corresponds to reduced state space generation using sleep sets; column 6 (st) corresponds to reduced state space generation using stubborn sets; and columns 7 (nrt+sym), 8 (nrt+sl), and 9 (nrt+st) correspond to combinations of the net reduction method followed by one of net symmetry, sleep sets, and stubborn sets. Column 10 (nrt+st+sym) corresponds to net reduction followed by a combination of stubborn sets and net symmetry. The Ada net for 10 philosophers contains 240 places and 180 transitions. The reduced net contains 30 places and 20 transitions. Every entry in the table consists of three numbers. The first two numbers give the number of nodes (i.e., unique states) and arcs (i.e., generated states) in the reachability graph. The third number gives the total time required by the TOTAL toolkit to check for the existence of deadlocks starting from Ada source 20

phil 3

5

10

20

full 18981 79371 6

nrt 6 13 1 24 88 2 768 5696 2 786432 11730944 473

sym 18981 79371 19

sl 174 186 1 1634 1822 2

st 140 148 1 1069 1138 3 23580 24973 50

100

200

400

nrt+sym 6 13 1 24 88 2 768 5696 3 786432 11730944 2450

nrt+sl 6 11 1 12 23 2 27 53 2 57 113 4 297 593 31 597 1193 130 1197 2393 730

nrt+st 6 11 1 18 37 2 83 172 2 363 742 4 9803 19702 210 39603 79402 3318

nrt+st+sym 6 11 1 18 37 2 83 172 2 363 742 4 9803 19702 221

Table 2: Data for dining philosophers problem without deadlock. code. Deadlock detection for any method is done by identifying all terminal states in the corresponding reachability graph. We do not halt reachability graph construction upon encountering a deadlock state. Time figures, which are expressed in CPU seconds, include the time required by the FETS, NRT and RGB tools. Empty table entries signify that the corresponding experiments could not be completed after exhausting some computational resource. In particular, we do not report data about experiments that required longer than approximately one hour of CPU time to generate the reachability graph. All tables in this section follow a similar format. In all cases shown in Table 1, the tool properly reports the existence of a deadlock state. The experiments with the 3-philosopher version show that each of the methods (net reduction, stubborn sets, sleep sets, net symmetry) can substantially reduce the size of the state space of the problem. However, the growth of the state space is still exponential in the number of philosophers when a single method is used. At first, this may seem to contradict Valmari’s claim that the stubborn set method gives a polynomial number of states for the dining philosophers problem [31]. However, the net models used by Valmari are smaller than the (unreduced) Ada net models that are output by the FETS tool. (We obtain smaller models than Valmari’s only after we apply the NRT tool to our Ada nets.) Similar considerations apply to the sleep set method [11]. 21

phil 3

5

10

full 211311 1051050 80

nrt 37 81 2 781 3315 2 989527 9108690 710

sym 19553 95964 29

sl 613 689 2 43316 52363 39

st 681 764 2 38781 45585 109

15

25

35

45

55

nrt+sym 10 23 2 35 145 2 220 1815 5 680 8260 13 2925 57850 76 7770 212415 323 16215 565455 1029 29260 1240470 2675

nrt+sl 37 81 2 779 3002 3

nrt+st 37 79 2 776 2852 3

nrt+st+sym 9 21 2 32 128 2 212 1605 7 667 7433 44 2902 53513 1053

Table 3: Data for dining philosophers with butler. Drastic gains are obtained when the net reduction method is combined with one of the other three

n ? n + 2) states, sleep sets generates 2n states, whereas net symmetry generates (n + 1) states, where n is the number of philosophers. methods. When combined with net reduction, stubborn sets generates

( 2

The best results are obtained by a combination of net reduction, net symmetry, and stubborn sets. This combination still gives (n + 1) states (as did the combination of net reduction and symmetry), but the number of arcs in the state space is now lower. The largest version we analyzed has 400 philosophers and 800 Ada tasks. Table 2 reports data for the dining philosophers problem in which deadlock is avoided by switching the order in which one of the philosophers picks up his forks. In these experiments no deadlock states are reported by the toolkit. Again, the combination of net reduction with either stubborn sets or sleep sets can drastically reduce the size of the graph. A notable difference with respect to the deadlocking versions is that in this case net symmetry fails to yield any reductions. This is so because the basic (deadlocking) version of the dining philosophers problem has a circular symmetry: For a given ordering of the philosophers, the behavior of each philosopher 22

remains the same if all philosophers and forks are rotated. This symmetry does not hold in the second (deadlock-free) version because one of the philosophers picks up his forks in reverse order. Of course, in this version the use of the net symmetry method slightly increases the CPU time due to the overhead of searching for symmetries. Data for the dining philosopher versions in which deadlock is avoided by a butler task are reported in Table 3. For this version, the 10-philosophers Ada net has 381 places and 585 transitions before reduction, and 67 places and 207 transitions after reduction. In all versions the toolkit correctly reports that there are no deadlocks. The presence of the butler task has two adverse effects. First, the size of the full state space for a version with the butler is much larger than the corresponding state space size for a version without a butler. Second, because all philosophers call two entries in the butler task, all philosophers end up in direct conflict with each other. As a result, both stubborn sets and sleep sets fail to reduce the exponential growth in state space size even when these methods are applied in conjunction with net reduction. In the case of the dining philosophers with the butler, only the combination of net reduction and net symmetry results in a polynomial growth in state space size. The largest version we analyzed has 55 philosophers and 111 tasks. When the stubborn set method is combined with net reduction and net symmetry, the number of states and arcs decrease slightly; however, the times required by the analysis increase sharply. This result is due to the added overhead of computing the stubborn sets of all graph nodes. Several other researchers have considered the dining philosophers example for Ada tasking analysis. While these other approaches are not aimed solely at deadlock detection, they do emphasize this particular type of analysis. In [14] Karam and Buhr discuss experimental results of deadlock and starvation detection in Ada programs. In their versions a single Ada task controls all forks. Each of three versions analyzed has 5 philosophers and 6 tasks. In [2] Avrunin et al. discuss their experiments with the toolset for constrained expression analysis of Ada-like specifications. Various versions of the dining philosophers problem are analyzed. In one instance the toolset detects a deadlock in the basic version of the problem with 100 philosophers and 200 tasks. Moreover, two versions with a butler are analyzed, one with deadlock and the other without deadlock. The largest butler problem analyzed has 40 philosophers and 81 tasks. In [6] Corbett discusses enhancements to the constrained expression method that allow the analysis of butler versions with 100 philosophers and 201 tasks. In [33] experiments with the PAL system are reported for the basic version (which is similar to our first version), and for a version in which deadlock is avoided by alternating the order in which philosophers pick up their forks (which is somewhat similar to our second version). The analysis performed by PAL is compositional in that sets of tasks contained in a program can be analyzed independently of each other. The results of partial analyses can then be combined into the analysis of the whole program. As with our 23

cus 3

5

7

9

10

full 72121 265578 40

nrt 170 300 2 1622 3180 4 11762 24164 20 74222 156636 206 180204 383960 681

sym 10672 39316 21 91811 473403 405

sl 882 898 3 8022 8150 15 56922 57690 167

st 1601 1840 5 15573 18552 70 113975 137998 1049

20

30

40

nrt+sym 34 65 2 60 150 3 86 263 6 112 404 11 125 485 15 255 1680 163 385 3575 833 515 6170 2752

nrt+sl 145 165 2 1301 1445 4 9073 9877 18 55789 59949 154 134123 143420 485

nrt+st 104 144 2 832 1280 6 5504 8960 47 32768 55296 510

nrt+st+sym 26 40 2 44 88 4 62 152 7 80 232 14 89 278 21 179 958 510

Table 4: Data for 1-pump gas station without deadlock. approach, the growth in the number of states explored by PAL is linear; however, it seems that PAL requires the user to provide a hierarchical partitioning of the tasks in the program, and that the effectiveness of the analysis is dependent on the particular partitioning used. In this case, the largest versions analyzed by PAL have 100 philosophers and 200 tasks, both for the deadlocking case and for the deadlock-free case. The analysis of the deadlocking version results in the exploration of 1382 states. Finally, a comparison of our current experimental results with the results we reported in [8] shows improvements both in the size of the versions analyzed and in state space sizes. In particular, the largest version analyzed in [8] had 100 philosophers, and the number of states, say, for the combination of net reduction and stubborn sets was (3n2 ? 3n + 2), where n is the number of philosophers. Our results have improved for two reasons. First, we have enhanced our net reduction technique. Thus, our reduced Petri nets now have a smaller state space than previous nets. Second, we have modified our translator to handle larger input Ada programs and improved our stubborn set computation algorithm. In summary, our results for this example indicate that Petri net based analysis is competitive with other analysis approaches to deadlock detection. 24

cus 3

full 110962 397392 57

5

7

nrt 285 453 2 5403 10035 6 80377 160601 108

sym 16295 58320 28

sl 1648 1672 3 30380 31012 42

st 2811 3118 6 58496 67119 220

10

20

30

35

nrt+sym 57 93 2 149 316 3 281 719 6 554 1766 17 2114 11041 294 4674 33816 2128 6329 52141 4637

nrt+sl 248 276 2 4322 4970 6 59964 68880 84

nrt+st 213 273 2 3583 5295 12 49899 79191 315

nrt+st+sym 49 66 2 124 215 4 230 483 8 449 1180 27 1699 7360 753

Table 5: Data for 1-pump gas station with deadlock. 5.1.2

Gas station

In the gas station example, n customers wish to buy gas at a self-service gas station [12]. The station has some gas pumps and an operator who controls the pumps. To buy gas each customer must prepay the operator first. When a pump is available, the operator activates the pump and then the customer can pump gas up to the amount prepaid. Finally, the customer gets change from the operator for the amount that was prepaid but not pumped, and the operator deactivates the pump. This problem is interesting because the flow of control in each task and the interactions among tasks are more complex than in the case of the dining philosophers example and of the readers and writers example, which is discussed in the next subsection. We analyzed both 1-pump and 2-pump versions of this problem. In both cases we considered both deadlock-free and deadlock-prone versions. In the 1-pump case each version contains n customer tasks, a pump task, and an operator task. The 2-pump versions are similar except for the presence of two pump tasks. In all cases we analyzed unrolled versions in which different customers call different entries in the operator task. The results for 1-pump versions that do not deadlock are shown in Table 4. The 5-customer version results in an Ada net of 333 places and 329 transitions, while the reduced net contains 134 places and 165

25

cus 2

4

5

full

nrt 253 492 2 25305 79768 22 212015 777590 279

sym

sl 2030 2249 4

nrt+sym 253 492 2 25305 79768 48 212015 777590 657

st 2391 2740 7 297475 371364 2387

nrt+sl 217 299 2 15869 24636 19 110313 175369 179

nrt+st 187 262 3 9999 15902 47 62495 102462 516

nrt+st+sym 187 262 3 9999 15902 51 62495 102462 554

Table 6: Data for 2-pump gas station without deadlock. transitions. Only the combinations that use both net reduction and net symmetry can avoid an exponential growth in state space size: The largest version we analyzed successfully has 40 customers. Among the four optimization methods we studied, the net reduction method seems to be the most effective in reducing state space size when a single method is used. The net symmetry method fares worse than the stubborn set method and the sleep set method before net reduction is applied but does much better than these methods after the net is reduced. This phenomenon is discussed in Section 6. The experiments with 1-pump versions that can deadlock are summarized in Table 5. These versions are similar to their deadlock-free counterparts, except that the operator sometimes incorrectly sets a flag. As a result, the operator may try to activate the pump for a given customer even when the previous customer is still using the pump. The resulting state spaces are slightly larger than in the corresponding deadlock-free cases. The performance of stubborn sets, sleep sets and net symmetry is otherwise similar to the case of the deadlock-free versions. The experiments for deadlock-free versions of the 2-pump gas station are shown in Table 6. The presence of two pumps significantly increases the size of the state space. Similar results were obtained when we analyzed 2-pump versions with deadlock. As noted in the earlier discussion on symmetry, the 2-pump gas station examples present a unique difficulty to our symmetry method. In particular, the nets do not satisfy the structural sufficient condition discussed in Subsection 4.5. Our tools automatically detect this situation. As a result, the symmetries in this problem are not exploited during state space construction. Thus, we were only able to analyze relatively small versions of this problem (8 tasks). Experiments run with the symmetry method have the same state space sizes as the corresponding experiments without this method, as shown in Tables 6 and 7. Our experimental results with the gas station example compare favorably with published results on this example. In [14] Karam and Buhr discuss experiments with deadlock and starvation detection in 2-customer

26

cus 2

3

4

full

nrt 953 1548 3 25753 55086 13 588073 1508616 424

sym

sl 7183 7454 8 259120 281260 316

st 9733 10708 19 364867 423294 1274

nrt+sym 953 1548 3 25753 55086 20 588073 1508616 860

nrt+sl 883 1063 3 22983 32358 15 490631 774826 598

nrt+st 755 966 3 17591 25798 30 351561 567030 1134

nrt+st+sym 755 966 3 17591 25798 33 351561 567030 1289

Table 7: Data for 2-pump gas station with deadlock. and 1-pump versions. In [2] experiments with various 1-pump versions are discussed, and in the case of unrolled versions, results are reported for up to 6 customers. Our results for the 1-pump cases show a benefit from using the symmetry method. In our earlier work [8], the symmetry method did not detect symmetry in these cases because of the way that Ada nets were generated. The problem is in modeling boolean expression evaluation. In some cases, the ordering of variables in an expression can have an impact on the net structure and thus the realization of symmetry. This is discussed in further detail in Section 6. 5.1.3

Readers and writers

In this problem m reader and n writer tasks must access a shared buffer concurrently. When a writer uses the buffer no other task can use the buffer; however, multiple readers are allowed when no writer is in the buffer. An interesting aspect of this problem is the presence of different mutual exclusion constraints on buffer use. For this example we are interested in detecting violations of a mutual exclusion constraint, that is, that a reader and a writer do not use the buffer simultaneously. Since our framework is aimed at detecting only terminal states, we cast the mutual exclusion detection problem as a deadlock detection problem (similar to [1]). In particular, we modify deadlock-free versions of the example by introducing a test for the violation of the constraint in the input Ada code. If the constraint is violated we cause the program to enter a dead state. In Table 8 we show the results for versions that do not violate the constraint. (Similar results are obtained for versions that violate the constraint). Various versions are analyzed up to a problem with 50 readers and 50 writers. Each version has (m + n + 1) tasks, where m and n are the number of readers and writers. The 10-reader, 10-writer Ada net has 722 places and 827 transitions. The reduced net has 370 places and 516 transitions. A significant aspect of our experiments is that both stubborn sets and sleep sets cannot achieve any

27

R-W 22

23

25

32

52

10 10

full

nrt 31 39 2 36 45 2 46 57 2 64 88 2 318 478 3 17467 27715 57

sym 39818 185415 63 113428 622564 248

sl 162 168 2 188 195 2 240 249 2 331 349 2 1665 1795 4 94522 103748 487

st 162 168 2 188 195 2 240 249 3 331 349 2 1665 1795 6 94522 103748 1126

30 30

50 50

nrt+sym 17 23 2 17 24 2 17 26 2 22 34 2 32 62 3 57 175 9 157 1115 252 257 2855 1830

nrt+sl 31 39 2 36 45 2 46 57 2 64 88 2 318 478 3 17467 27715 66

nrt+st 31 39 2 36 45 2 46 57 2 64 88 2 318 478 3 17467 27715 199

nrt+st+sym 17 23 2 17 24 2 17 26 2 22 34 2 32 62 3 57 175 11 157 1115 950

Table 8: Data for readers/writers problem with mutual exclusion violation. state space reductions after net reduction is applied. This situation, which is relatively rare, is discussed further in Section 6. The net symmetry method provides additional reductions because it recognizes the symmetry among the reader and the writer tasks. As the number of writers increases, the state space size remains essentially the same except for the addition of an arc for each writer. In addition, the state space size increases linearly in the number of readers when net reduction and net symmetry are used. Other researchers have considered this example. Data for 4 task versions are reported in [14], and figures for 5 and 6 task versions are discussed in [1] and [2]. In [6] Corbett reports on a technique which allows the constrained expression approach to handle an arbitrarily large number of readers and writers. The technique cleverly exploits the fact that the readers (and the writers) have identical behavior. 5.1.4

Experiments with atomicity method

All experiments discussed in the previous subsections make use of the atomicity method. In this subsection we report data showing the effects of the atomicity method on our experiments. In particular, Table 9 has 3 columns. In the first column we indicate what program is analyzed. In the second column 28

Example phil 20

gas 5

r10-w10

with atomicity 1048576 15728640 626 1622 3180 4 17467 27715 57

without atomicity 1048576 15728640 617 3512 7300 5 58439 86618 123

Table 9: Experiments showing the effects of the atomicity method. we report the results of experiments with the net reduction method and the atomicity method. In the third column we give data for the net reduction method alone. The stubborn set method, sleep set method, and net symmetry method are not used in the experiments reported in Table 9. We considered 3 examples of concurrent programs to show the impact of the atomicity method. In the first line of Table 9, we report data for the basic (deadlocking) version of the dining philosopher problem with 20 philosophers. The following line has data for the deadlock-free version of the 1-pump gas station with 5 customers. The last line has data for a deadlock-free version of the readers and writers example with 10 readers and 10 writers. The experiments involving the atomicity method show two interesting facts. First, the use of this method has little impact on the run time of an analysis even when no state space reductions are achieved. This happens, for instance, in the dining philosophers example because no variables are used in the Ada source code of this example. Second, when variables are present in an Ada program, the atomicity method can achieve good reductions in state space size. This is so because the atomicity method avoids including states that correspond to intermediate stages during the evaluation of a boolean expression in a reachability graph. In particular, the data in Table 9 show a clear reduction in state space size for the gas station example and for the readers and writers example. Similar reductions are obtained when the atomicity method is combined with the other reduced state space generation methods. For these reasons, we have used the atomicity method in all our experiments except, of course, for experiments reported in Table 9.

5.2 Real-world examples In this subsection we present the analysis results of three experiments using real-world programs: A border defense system, a host buoy system and a waveform generator. An important point to be made about these programs is that they were not designed for the purpose of testing any particular concurrency analysis method. In fact, the source programs were often a bit hostile to automated translation into Ada nets since 29

name dead

live

full

nrt 55347 377076 22 55346 377075 22

sym

sl

st

nrt+sym 55347 377076 75 55346 377075 74

nrt+sl 19961 53589 21 19960 53588 22

nrt+st 5599 10995 8 5598 10994 8

nrt+st+sym 5599 10995 9 5598 10994 9

Table 10: Data for border defense system. these programs used many Ada constructs that our translator is not designed to handle, such as packages and task types. Thus, for these examples we had to perform some hand modifications of the Ada sources in order to get a proper net model of the corresponding programs. Of course, the important thing is that our experiments are reporting on the effectiveness of different methods when applied to a common model. 5.2.1

Border defense system

The BDS (Border Defense System) program is a game simulation of a system for border defense. The program is about 11,000 lines of Ada source code with 15 tasks. It was written by T. Griest of LabTek Corporation (Woodbridge, Connecticut) and made available by U.S. Army CECOM [7]. The BDS program uses tasking to track and detect targets, and to launch rockets that destroy the targets. It consists of two main tasks, Control and Track. Task Control controls the rockets by getting information from other tasks that represent rockets and targets. In addition, there are a few Guidance tasks which compute guidance information for the rockets. Task Track is similar in function to task Control, but Track also provides position and other information to a display task. Much of the program code is computationally intensive, doing sensing, tracking, guiding and updating of information about the rockets and targets. We analyzed two versions of this program. The first version does not model any boolean conditions. In this case, the toolkit detected a few deadlocks, which we were able to identify as spurious deadlocks. These deadlocks were caused by exploring paths that are not feasible when boolean conditions are taken into account. In the second version, we model boolean conditions affecting tasking behavior. As we expected, no deadlocks were detected. The unreduced Ada net for this version contains 260 places and 217 transitions. The reduced Ada net has 59 places and 61 transitions. In Table 10 we report data for the two versions that we analyzed. Data for the first (deadlocking) version are reported in the first line. Data for the version without deadlock are reported in the second line. In both cases, we were unable to generate (within the given time and memory constraints) the state space for the unreduced net when using only one of the following methods: stubborn sets, sleep sets, or net symmetry. 30

This is expected since this program uses a fairly large number of tasks, and each task has a relatively complex control structure. Given that there are no symmetries in the net, the net symmetry method fails to give any reduction when used alone or in combination with other methods. As we show in Table 10, the state space sizes for the experiments that use the net symmetry method are the same as the state space sizes for the corresponding experiments where this method is not used. As we have observed before, the CPU time increases when using the net symmetry method since some time is used to search for the symmetries. The sleep set method and the stubborn set method can successfully reduce state space size when these methods are combined with net reduction. 5.2.2

Host buoy system

A detailed description of the system, and the requirements can be found in [7, 9, 18]. To quote them, the buoy system can be briefly described as: The “Host Buoy at Sea” system is a group of free floating buoys that provide navigation and weather data to air and ship traffic at sea. The buoys collect data on air and water temperature, wind speed, and buoy heading through a variety of sensors. Each buoy can send messages (weather reports, buoy sensor status reports, SOS signals, and low power warning) and can receive messages (requests from passing vessels). Buoys have a red light that can be activated by a passing vessel on sea-search operations. A sailor reaching the buoy can flip a switch on the side of the buoy to initiate an SOS broadcast or a vessel may activate the SOS broadcast. The original program contains 15 tasks and around 2200 lines of Ada code [9, 18]. It was implemented to test out a software design methodology being developed for the Charles Stark Draper Laboratory, Inc. in Cambridge, Massachusetts2. Since the program was not intended to be a deliverable product, it was not subject to the testing procedures that are typically applied to systems that are delivered to Draper Laboratory customers. Moreover, the host buoy system was designed for a multi-processor environment consisting of three processors. A set of tasks runs on each processor. A detailed description of the tasks can be found in [18] along with a manually-produced colored Petri net model of the whole system. Our experiments for this system are summarized in Table 11. For our Ada net, the complete state space was too large to generate completely without the use of any optimization methods. Even the complete state space of the reduced net was too big to generate explicitly. The reason that net reduction alone was not sufficient to analyze the system is that the system consists of three entirely independent sets of tasks running 2

The Ada source code for this example cannot be obtained without permission from Charles Stark Draper Laboratory, Inc.

31

name test

full

intr

proc2

proc3

1512 5652 1 1080 3834 1

nrt 3865 15361 3 760374 7986216 364 2 4 1 3 5 1

sym

1512 5652 2 1080 3834 2

sl 7942 8200 10 31807 35791 36 16 16 1 20 20 1

st 2920 3036 7 25300 27832 47 16 16 1 20 20 1

nrt+sym 3865 15361 5 260982 2736276 508 2 4 1 3 5 1

nrt+sl 560 818 3 1155 2066 3 2 4 1 3 5 1

nrt+st 303 404 3 1209 2062 3 2 2 1 3 3 1

nrt+st+sym 303 404 3 382 649 3 2 2 1 3 3 1

Table 11: Data for host buoy system. on different processors. The independence of the sets of tasks leads to a large number of interleavings of individual states, which cannot be avoided by net reduction followed by full state space generation. We separately analyzed the systems of tasks for each of the three processors. For analysis purposes we used two versions of the tasks on the first processor. The first version, which we call test, is based on the original source code. This version contains some interrupt handling routines that are never invoked. In the second version, which we call intr, we added invocations to the interrupt routines in order to test these routines. Both versions have large state spaces when considered without the use of any optimization method. For version test, net reduction, sleep sets, and stubborn sets provide good reductions in state space size and report no deadlocks. Stubborn sets gives the least number of nodes and arcs when each of the methods is used alone. The combined use of net reduction and stubborn sets gives the best performance when the methods are used in combination. The symmetry method gives no reduction when used alone or in combination with the other methods. This is so because the Ada net contains no symmetries. The intr version is more complicated than the test version because we model the interrupt handling and interrupt generating tasks. This increases the number of tasks and the parallelism in the net. Because all the interrupt generating tasks are identical to each other, the resulting net contains some symmetries, which in fact result in state space reductions when the net symmetry method is used. Using the net reduction method we were able to generate the reachability graph and to determine that the tasking system is free of deadlock. The sleep set and the stubborn set methods are uncharacteristically more effective than net reduction. This is so because there are two independent sets of tasks in the intr version. When net reduction is used alone, all interleavings of actions performed by the two sets of tasks are included in the reachability graph. However, sleep sets and stubborn sets can take advantage of the

32

parallelism between the two sets of tasks. Some symmetries were identified in the net but we were unable to generate the reachability graph using the symmetry method alone. However, the symmetry method gives significant reductions when used in combination with other methods—compare, for example, the combination of stubborn sets and net reduction with the combination of net reduction, stubborn sets, and net symmetry. The latter combination gives better results than any other combination. No combination of methods reported a deadlock; yet, we expected a deadlock to occur in the intr version as reported in [18]. In particular, we expected to find the interrupt handler task involved in a deadlock. By analyzing the state space we found that other tasks were live even when the interrupt handler is blocked. This phenomenon is caused by the presence of two independent sets of tasks on processor one. When we constructed a version of the program that exclusively contains the interrupt handler and the related tasks, our analysis identified the same deadlock as reported in [18]. Finally, the analysis of the tasking systems on the second and the third processors is straightforward (see Table 11). 5.2.3

Waveform generator

The waveform generator is a 1200 line Ada simulation of electric equipment which generates various waveforms. The program simulates a pulse generator and a function generator. It produces various output probe signals depending on the function it is simulating. The system also simulates the closing and opening of the switches which control the equipment, and aborts in case of very high input line voltage. This program contains two main tasks which simulate the function generator and the pulse generator. The tasks are used to control the switches producing the waveforms. Each of these tasks has two possible entry calls to open and close the switches. The program was originally developed by L. DeAcetis. We obtained the code from R. Lacavora of Mitre Corporation in Houston, Texas. We analyzed two versions of the program [7]. The version called labels uses labeled loops containing exit statements. The version called nolabels uses booleans, normal loops, and exits to simulate the effect of labeled exits through multiple nested loops. The unreduced Ada net for the nolabels version contains 97 places and 105 transitions, while the reduced net contains 21 places and 60 transitions. We experimented with two logically similar versions to study the effect of modeling labeled loops on the program state space. The results of our analyses with the waveform generator are summarized in Table 12. As we expected, we did not detect any deadlocks in either version of this program. The results did give some interesting insights into variable modeling and the optimization methods used, however. For instance, each of net reduction, stubborn sets, and sleep sets yields substantial reductions in state space size when used alone or in combination. 33

name nolabels

labels

full 11236 32812 5 4983 14562 3

nrt 78 326 2 31 242 2

sym 11236 32812 15 4983 14562 8

sl 1164 1360 2 789 966 2

st 269 291 2 221 251 1

nrt+sym 78 326 2 23 162 2

nrt+sl 78 230 2 27 222 2

nrt+st 52 218 2 29 214 2

nrt+st+sym 52 218 2 21 138 2

Table 12: Data for waveform generator. Experiments with the symmetry method show another interesting phenomenon. We expected some kind of symmetry to be detected in this program because it has two identical tasks. In the net, however, these two tasks are not found to be symmetric because the third task makes calls to identical entries in these tasks in sequential order. But when the net is reduced by NRT some new symmetry is detected. The new symmetry can be explained with the help of Figure 8, which is similar in spirit to a part of the waveform generator code. Consider the control flow in task T2. After accepting a call to entry E1 , control is transferred to the “end select” statement, and then to “end second” statement, which takes control back to the beginning of the second loop. After accepting a call to entry

E2, control is transferred to the “exit

second” statement, and then to the “end first” statement, which takes control back to the beginning of the first loop. Although the flow of control appears to be different depending on which entry is accepted, the resulting behavior is identical (i.e., an indefinite loop around the selective wait statement). However, the differences in the two accept alternatives can hide the symmetry in the unreduced net because the control paths just mentioned are structurally different in the unreduced net. Thus, the places corresponding to the two accept statements are not found to be symmetric in task

T2 .

But when net reduction is applied, the two control

paths have identical structure. Thus, the symmetry between the two select alternatives (and between the corresponding entry calls in task T1) is detected. Note, however, that the symmetry method gives reductions only for the version of the program with labeled loops. In fact, when boolean variables are used instead of labeled loops, the two control paths are different even after net reduction is applied. When labeled loops are used, the combination of net reduction, stubborn sets, and net symmetry gives the best results with respect to the other combinations.

34

Task T2 . . . First: loop Second: loop select accept E1; or accept E2; exit Second; end select; end Second; end First; . . .

Task T1 . . . if ... then T2.E1; else T2.E2; end if; . . .

Figure 8: Code segment related to waveform generator example.

6 Evaluation of Experimental Results The results in the previous section indicate that each of the four optimization methods we considered can provide significant reductions in state space size. In this section we evaluate the effectiveness of the methods that we used for our experiments. In the first subsection we give some observations about the effectiveness of our integrated approach. In the following subsections we discuss each of the net reduction method, partial order methods, and the symmetry method.

6.1 Evaluation of integrated approach First and foremost, it is evident from our experimental results that net reduction, partial orders, and net symmetry should all be used in combination in order for Petri-net-based reachability analysis of Ada tasking programs to be effective. This conclusion is justified by noting the differences in the effects of each method when the method is applied to different program examples. Consider, for instance, the basic dining philosophers example (i.e., with deadlock). Here the combination of net reduction with any of the other methods reduces state space growth to polynomial in the number of philosophers. If the order in which one philosopher picks up his forks is switched, the net symmetry method has no effects, whereas partial order methods can still avoid exponential state space growth. In the version with a butler task, however, partial order methods fail to achieve significant reductions, and it is the net symmetry method that leads to polynomial growth in state space size. This is also true of the 1-pump gas station example (with and without deadlock) and of the readers and writers example.

35

The real-world examples we considered give a different picture. In general, the symmetry method has not been very effective because these examples do not contain many symmetries. In particular, the BDS example and the host buoy example (basic case) do not contain any symmetries. Small symmetries were found in the labeled version of the waveform generator (after net reduction), and in the host buoy system (with explicit invocation of interrupt routines). Note, however, that net reduction and partial order methods generally gave good reductions in all real-world examples we considered. Our experiments with real-world examples have provided both encouraging results and valuable insights into the strengths and the limitations of Petri-net-based reachability analysis. First, our toolkit was able to complete the analysis of all real-world examples we considered in a few seconds when suitable combinations of optimization methods were used. Second, the analysis of the real-world examples required a certain amount of manual intervention. For example, some of the constructs used in the source code of these examples could not be processed automatically by our toolkit. Of course, this is a limitation of our translation tools, rather than a limitation of our analysis approach. In addition, manual intervention was required to identify independent sets of tasks in the host buoy example. Again, we believe that the presence of independent sets of tasks could be automatically detected by suitable translation tools.

6.2 Evaluation of net reduction First, the net reduction method is usually more effective at reducing the complexity of state space generation than stubborn sets, sleep sets, or net symmetry when any method is applied alone. In particular, net reduction generally results in smaller state spaces than any of the other three methods when a single method is used. Note, however, that the net reduction method exploits Ada-specific knowledge, whereas stubborn sets and sleep sets do not use such knowledge. Moreover, our symmetry method uses some Ada-net-specific information, but only while searching for symmetries (i.e., before reachability graph construction). An additional advantage of the net reduction method is that it can often enhance the effectiveness of reduced state space generation methods. In the basic versions of the dining philosophers example, net symmetry, sleep sets, and stubborn sets fail to achieve polynomial state space growth unless net reduction is first applied to the Ada net models. Likewise, the reduced Ada net for the waveform generator system exhibits symmetries that are hidden in the unreduced Ada net.

6.3 Evaluation of partial order methods The success of stubborn sets and of sleep sets is usually dependent on the amount of parallelism that might exist in a given problem. As we expected, these two methods do best when a problem exhibits a high degree

36

of parallelism, such as the basic dining philosophers example. In both deadlock-free and deadlock-prone versions these methods have reduced state space size from exponential to polynomial in the number of philosophers. Various factors can prevent this reduction, however. For instance, state space size remains exponential unless the net reduction method is applied first (see Tables 1 and 2). In addition, state space size is still exponential for variations of this problem in which the butler is used to prevent deadlock (see Table 3). In the readers and writers example, stubborn sets and sleep sets do not provide any state space reductions after the net reduction method is applied. This result is somewhat surprising because intuitively this example provides a certain degree of parallelism (i.e., among readers). In particular, each reader goes through the following three phases: (1) request a resource, (2) use the resource, and (3) relinquish the resource. The parallelism is present only during the second phase. In our Ada code for this example, requesting a resource and relinquishing the resource are modeled using two rendezvous with the same task (buffer). Resource use is modeled as the time between these two rendezvous. Thus, stubborn sets and sleep sets cannot take advantage of any explicit parallelism in this case. In terms of the Ada constructs appearing in this example, the failure of sleep sets and of stubborn sets is caused by the presence of a selective wait statement in the task that controls the buffer. Suppose that two readers are trying to get access to the buffer when no writers are in the buffer. The Ada selective wait statement results in a conflict situation in the Ada net for reader access to the buffer. This causes both stubborn sets and sleep sets to explore all paths in the reachability graph. A similar situation occurs in the butler versions of the dining philosophers example. Comparing the relative performance of sleep sets and stubborn sets is quite difficult because both methods are nondeterministic. In most cases these two methods seem to achieve similar state space reductions; however, there are some meaningful differences in the performance of these methods. For instance, in the dining philosopher versions without a butler, the sleep set method clearly outperforms stubborn sets (see Tables 1 and 2); however, in the BDS example, the stubborn set method does much better than sleep sets (see Table 10). In some cases the different performance of stubborn sets and sleep sets can be traced back to the net structure of the program being analyzed. Suppose that there is a net state in which an enabled transition,

t1 , conflicts (i.e., shares an input place) with a disabled transition, t2 . Also, suppose that another enabled transition, t3 , conflicts with t2 but not with t1 . On the one hand, the sleep set method requires that t3 be fired if t1 is fired. By definition of sleep sets, if a transition t fired, all enabled transitions that are directly or indirectly conflicting with t must also be fired [11]. On the other hand, stubborn sets does not require that t3 be fired if t1 is fired. Thus, in this and similar situations stubborn sets can explore fewer states than sleep 37

sets. An additional advantage of stubborn sets is that this method can be easily combined with net symmetry. Sleep sets and net symmetry cannot be combined as easily because each net state must include a transition subset (i.e., a sleep set), when the sleep set method is used. This fact complicates the notion of equivalence between net states and makes our sufficient conditions for two states to be equivalent invalid. An advantage of sleep sets over stubborn sets is that sleep sets can “remember” not to fire a transition after a case of confusion occurs. Consider, for instance, the situation in Figure 6. If transition t1 is fired, both methods require that t2 be fired too. Unlike stubborn sets, the sleep set method prevents t1 from firing

in the state reached by firing t2 (i.e., because t1 is included in the sleep set of this state). It is precisely this feature that causes sleep sets to do better than stubborn sets in the dining philosophers example. A final consideration is that Valmari has defined a good heuristic for the selection of a stubborn set in a state (i.e., select a stubborn set with a minimal number of enabled transitions) [32]. A similar heuristic has not been defined for sleep sets [11]. Thus, in our implementation of stubborn sets we compute all stubborn sets of each state in an effort to find a set with a minimal number of enabled transitions. We do not perform a similar computation for the sleep set method, however. This fact explains why the times required for state space construction are usually longer for stubborn sets than for sleep sets. It would be interesting to see if good heuristics can be defined for sleep sets as well, and whether these heuristics can reduce the size of the state spaces produced by this method.

6.4 Evaluation of net symmetry We deem the net symmetry method to be effective but fragile. This method gives significant reductions whenever a program has symmetries and these symmetries can be used cost-effectively. This happens in the basic dining philosophers problem with deadlock, in the dining philosophers problem with the butler, in the readers and writers example, and in the gas station problem with one pump. This method, however, fails to yield any state space reduction in the dining philosophers problem when the order in which one philosopher picks up his forks is reversed (to avoid deadlock). Also, in general the method is computationally intractable, forcing our implementation to abandon detected symmetries in the 2-pump gas station example. The experiments with the gas station example reveal some interesting results. The net symmetry method fares worse than stubborn sets and sleep sets when net reduction is not applied (see, for instance, Tables 4 and 5). After net reduction is applied, however, the net symmetry method gives better results than the other two methods. The gas station example has both parallelism and symmetry. In the case of an unreduced Ada net, stubborn sets and sleep sets are very effective because they take advantage of potential parallelism among independent actions. The net reduction method, however, provides a virtual coarsening effect, thus 38

select when

a => accept E1 ... if (b and c and d) then ...

or when

or when

b => accept E2 ... if (c and d and a) then ... c => accept E3 ... if (d and a and b) then ...

or when

d => accept E4 ... if (a and b and c) then ... end select;

Figure 9: Sample Ada code showing effects of boolean expressions on symmetry method. reducing the amount of parallelism in the reduced Ada net. For this reason, after net reduction is applied, the net symmetry method improves substantially with respect to the sleep set method and the stubborn set method. To verify this assertion, we modified a reduced Ada net by manually introducing identical sequences of independent computation steps in each customer task. The sequences increase the parallelism among customer tasks while preserving their symmetry. As we expected, the stubborn set method and the sleep set method perform better than the net symmetry method in the case of the modified net. It is worth noting that the net symmetry method can fail to achieve any reductions if the net generation activity hides certain kinds of symmetry. This phenomenon can happen, for instance, when the source code contains boolean expressions with n-ary operators. Thus, if a, b, and

c are boolean variables, expression (a ^ b ^ c) is modeled differently from expression (a ^ c ^ b). In the first case, the conjunction of a and b is computed first, followed by the conjunction of the result with c. In the second case, (a ^ c) is computed first, followed by the conjunction of this result with b. Thus, the order of variables in an expression can

affect the resulting net structure. The order of variables in boolean expressions can have an adverse effect on the symmetry method, for instance, in the case of the gas station example with one pump. Because we use an unrolled version of the operator task, some of the operator code is similar to the code segment shown in Figure 9. In this code segment the different accept alternatives are intended to be used by different customer tasks. The order of variables in the different boolean expressions is chosen in such a way as to preserve the symmetry among the different select alternatives (and among the customer tasks calling the corresponding entries).

39

The symmetry is lost, say, if the last expression appearing in the code is replaced by (b ^ c ^ a). In some earlier experiments with with the 1-pump gas station example, we observed that the net symmetry method gave no gain for versions with more than three customers because variable modeling hid symmetries [8].

7 Conclusions and Future Work Directions In this paper we have reported on a variety of experiments with several methods for controlling the complexity of reachability-based deadlock detection in Ada programs. To our knowledge, this is the most comprehensive experimental evaluation of techniques for concurrency analysis. Furthermore, our experimental results indicate the effectiveness of Petri net techniques for automated analysis of Ada tasking programs. First, the experiments indicate that, in general, Petri net reduction and reduced state space generation methods can be mutually beneficial with respect to the efficiency of the analysis. Second, when comparison data is available, we observe that our integrated approach often gives better results than previously published results for alternative approaches. Of course, there are also cases in which our approach does not fare as well as other methods. Thus, it appears that no existing analysis approach clearly outperforms all other approaches over a broad range of concurrent programs. Third, our toolkit has been able to analyze automatically three real-world programs as well as relatively sizable versions of traditional examples of concurrent programs. We conclude that Petri-net-based reachability analysis holds considerable promise toward practical application to software development environments. We are currently investigating ways to incorporate semantic information about Ada nets in the stubborn set and the sleep set methods. There are two ways in which semantic information can be exploited during the computation of sleep sets and stubborn sets. First, in some cases transitions that share an input place are known never to be enabled simultaneously (e.g., because they model different computations in a given task). This knowledge can be exploited when computing stubborn sets and sleep sets. Second, consider two disjoint transition subsets, T1 and T2, that model the evaluation of two boolean expressions. Transitions in

T1 sometimes share input places (i.e., places that model boolean values) with transitions in T2. In this case, the firing of transitions in T1 will never disable transitions in T2, and vice versa. This is so because when transitions in T1 and T2 are fired, they always put tokens back into the shared input places. Thus, the conflicts between transitions in T1 and transitions T2 can sometimes be ignored with respect to the computation of sleep sets and stubborn sets. We are also investigating the analysis of concurrency properties different than global deadlocks. In particular, we have defined but not implemented a technique for verifying arbitrary safety properties. Moreover, we are considering extensions of our integrated approach to real-time analysis of Ada code. In

40

[4] a timed extension of ordinary Petri nets is introduced, which is especially well-suited for automated analysis. This model, which is called a simple time Petri net or STP net, is amenable to the net reduction and the reduced state space generation techniques that we have discussed here. Preliminary experiments with STP nets have shown that this approach to real-time analysis is promising. Finally, we are extending the FETS and NRT tools in order to analyze automatically Ada programs containing scalar variables. When these tools are available, we will be able to analyze rolled as well as unrolled versions of our examples.

Acknowledgments We thank H. S. Kim for his work on earlier versions of the implementation of stubborn sets. We are grateful to M. Tiusanen for bringing Starke’s symmetry method to our attention. Additional thanks are due to P. Godefroid for helping us understand and implement the sleep set method. We also wish to thank W. McLendon and A. Clough of Draper Laboratory for giving us permission to use the Ada source code of the host buoy system, S. Masticola for providing us with the source code of the border defense system, and R. Lacavora for providing us with the source code of the waveform generator system. Finally, we are thankful to the anonymous referees for a very careful reading of an earlier version of this article. Their valuable comments and suggestions have helped us considerably in improving the article.

References [1] G. S. Avrunin, U. A. Buy, J. C. Corbett, L. K. Dillon, and J. C. Wileden. “Automated analysis of concurrent systems with the constrained expression toolset.” IEEE Trans. Softw. Eng., 17(11):1204– 1222, November 1991. [2] G. S. Avrunin, U. A. Buy, J. C. Corbett, L. K. Dillon, and J. C. Wileden. “Experiments with an improved constrained expression toolset.” Proceedings of the 4th Symposium on Testing, Analysis, and Verification, Victoria, British Columbia, pp. 178–187, October 1991. [3] G. Berthelot. “Checking properties of nets using transformations.” In G. Rozenberg, editor, Advances in Petri nets, LNCS 222, Springer-Verlag, New York, New York, pp. 19–40, 1987. [4] U. Buy and R. H. Sloan. Analysis of real-time programs with simple time Petri nets. In Proceedings of the 1994 International Symposium on Software Testing and Analysis, Seattle, Washington, pp. 228–239, August 1994. [5] U. Buy, R. Devarapalli, S. Duri and S. M. Shatz. “Using state space reduction to aid in Ada tasking analysis: Concepts and experiments.” Technical Report UIC-EECS-92-9, Concurrent Software Systems Lab, EECS Dept., University of Illinois, Chicago, Illinois, October 1992. [6] J. C. Corbett. “Identical tasks and counter variables in an integer programming-based approach to verification.” Proceedings of the 7th International Workshop on Software Specifications and Design,

41

Redondo Beach, California, pp. 100–109, December 1993. To appear in ACM Software Engineering Notes. [7] R. Devarapalli. Applying TOTAL to realistic Ada tasking programs: Experiments, problems, and solutions. Master’s project report, Department of Electrical Engineering and Computer Science, University of Illinois, Chicago, Illinois, May 1993. [8] S. Duri, U. Buy, R. Devarapalli, and S. M. Shatz. “Using state space methods for deadlock analysis in Ada tasking.” In Proceedings of the 1993 International Symposium on Software Testing and Analysis, Cambridge, Massachusetts, pp. 51–60, June 1993. [9] T. Fujita-Yuhas, A. Clough, and R. Vidale. “Development methodology for hard real-time systems – IR&D 281 Final Report.” Technical Report CSDL-R-2307, The Charles Stark Draper Laboratory, Inc., Cambridge, Massachusetts, November 1990. [10] M. R. Garey and D. S. Johnson. Computers and Intractability. W. H. Freeman & Company, New York, New York, 1979. [11] P. Godefroid and P. Wolper. “Using partial orders for the efficient verification of deadlock freedom and safety properties.” In K. G. Larsen and A. Skou, eds., Computer-Aided Verification, LNCS 575, Springer-Verlag, New York, New York, pp. 332–342, 1991. [12] D. Helmbold and D. Luckham. “Debugging Ada tasking programs.” IEEE Software, 2(2):47–57, March 1985. [13] G. Holzmann, P. Godefroid, and D. Pirottin. “Coverage preserving reduction strategies for reachability analysis.” In Proceedings of the 12th International Symposium on Protocol Specification, Testing, and Verification, Lake Buena Vista, Florida, pp. 349–363, North-Holland, June 1992. [14] G. M. Karam and R. J. Buhr. “Starvation and critical race analyzers for Ada.” IEEE Trans. Softw. Eng., 16(8):829–843, August 1990. [15] D. L. Long and L. A. Clarke. “Task interaction graphs for concurrency analysis.” Proceedings of the 11th International Conference on Software Engineering, Pittsburgh, Pennsylvania, pp. 44–52, May 1989. [16] S. P. Masticola and B. G. Ryder. “A model of Ada programs for static deadlock detection in polynomial time.” Proceedings of the ACM/ONR Workshop on Parallel and Distributed Debugging, pp. 97–107, May 1991. [17] C. E. McDowell. “A practical algorithm for static analysis of parallel programs.” J. Parallel and Distributed Process., pp. 515–536, June 1989. [18] W. W. McLendon, Jr. Modeling and analysis of Ada tasking using colored Petri nets. Master’s Thesis, Department of Computer Science, Boston University, Boston, Massachusetts, May 1991. [19] E. T. Morgan and R. Razouk. “Interactive state-space analysis of concurrent systems.” IEEE Trans. Softw. Eng., 13(10):1080–1091, October 1987. [20] T. Murata. “Petri nets: Properties, analysis and applications.” Proceedings of the IEEE, 77(4):451–480, April 1989.

42

[21] T. Murata, B. Shenker, and S. M. Shatz. “Detection of Ada static deadlocks using Petri net invariants.” IEEE Trans. Softw. Eng., 15(3):314–326, March 1989. [22] L. Osterweil and L. A. Clarke. “A proposed testing and analysis research initiative.” IEEE Software, 9(5):89–96, September 1992. [23] J. H. Reif and S A. Smolka. “The complexity of reachability in distributed communicating processes.” Acta Informatica, 25(3):333–354, April 1988. [24] S. M. Shatz, Distributed software engineering, Macmillan Publishing, New York, New York, 1993. [25] S. M. Shatz, S. Tu, T. Murata and S. Duri. “Theory and application of Petri net reduction for Adatasking deadlock analysis.” Submitted. Available as Technical Report UIC-EECS 91-15, EECS Dept., University of Illinois, Chicago, Illinois, November 1993. [26] S. M. Shatz, K. Mai, C. Black, and S. Tu. “Design and implementation of a Petri net-based toolkit for Ada tasking analysis.” IEEE Trans. Par. Dist. Syst., 1(4):424–441, October 1990. [27] P. H. Starke. “Reachability analysis of Petri nets using symmetries.” Syst. Anal. Model. Simul., 8:293–303, 1991. [28] R. Taylor. “Complexity of analyzing the synchronization structure of concurrent programs.” Acta Informatica, 19:57-84, 1983. [29] R. Taylor. “A general purpose algorithm for analyzing concurrent programs.” Commun. ACM, 26(5):362-376, May 1983. [30] S. Tu, S. M. Shatz, and T. Murata. “Applying Petri net reduction to support Ada-tasking deadlock detection.” Proceedings of the 11th International Conference on Distributed Computing Systems, Paris, France, pp. 96–103, May 1990. [31] A. Valmari. “A stubborn attack on state explosion.” Proceedings of the 2nd International Workshop on Computer-Aided Verification, LNCS 531, Springer-Verlag, New York, New York, pp. 156–165, 1991. [32] A. Valmari. “Error detection by reduced reachability graph generation.” Proceedings of the 9th European Workshop on Applications and Theory of Petri Nets, Venice, Italy, pp. 95–112, June 1988. [33] W. J. Yeh. Controlling state explosion in reachability analysis. PhD Dissertation, Purdue University, West LaFayette, Indiana, December 1993. [34] W. J. Yeh and M. Young. “Compositional reachability analysis using process algebra.” In Proceedings of the 1991 International Symposium on Testing, Analysis, and Verification, Victoria, British Columbia, pp. 49–59, October 1991. [35] M. Young and R N. Taylor. “Combining static concurrency analysis with symbolic execution.” IEEE Trans. Softw. Eng., 14(10):1499–1511, October 1988. [36] M. Young, R. N. Taylor, K. Forester, and D. Brodbeck. “Integrated concurrency analysis in a software development environment.” In R. A. Kemmerer, editor, Proceedings of the ACM SIGSOFT ’89 Third Symposium on Software Testing, Analysis and Verification, pp. 200–209, 1989. Appeared as Software Engineering Notes, 14(8).

43

Suggest Documents