Skip to main content
Springer Nature - PMC COVID-19 Collection logoLink to Springer Nature - PMC COVID-19 Collection
. 2020 Jun 17;12227:255–263. doi: 10.1007/978-3-030-52482-1_16

Towards a Formal Account for Software Transactional Memory

Doriana Medić 10,, Claudio Antares Mezzina 11, Iain Phillips 12, Nobuko Yoshida 12
Editors: Ivan Lanese8, Mariusz Rawski9
PMCID: PMC7345309

Abstract

Software transactional memory (STM) is a concurrency control mechanism for shared memory systems. It is opposite to the lock based mechanism, as it allows multiple processes to access the same set of variables in a concurrent way. Then according to the used policy, the effect of accessing to shared variables can be committed (hence, made permanent) or undone. In this paper, we define a formal framework for describing STMs and show how with a minor variation of the rules it is possible to model two common policies for STM: reader preference and writer preference.

Keywords: STM, Transactions, Concurrency

Introduction

Starting from the 1960s, reversible computing has been studied in several contexts ranging from quantum computing  [6], biochemical modelling  [7], programming  [8, 9], and program debugging  [10, 15]. Distributed reversible actions can be seen as defeasible partial agreements: the building blocks for different transactional models and recovery techniques. The work of Danos and Krivine on reversible CCS (RCCS)  [1] provides a good example: they show how notions of reversible and irreversible actions in a process calculus can model a primitive form of transaction, an abstraction that has been found useful, in different guises, in reliable concurrent and distributed programming. Since the seminal work of  [1], other works have investigated the interplay between transactions and reversibility [2, 11] in the area of message passing systems. On the shared memory side, we just recall the work of [12] where a CCS endowed with a mechanism for software transactional memories (STMs) is presented. Another work about reversibility and a high-level abstraction of shared memory (tuple spaces) is presented in [16].

Software Transactional Memory  [3, 4] is an elegant way to address the problem of concurrent programming, by relieving the programmer from the burden of dealing with locks. The lock-based approach is error prone and usually leads to deadlocks when the complexity of the system grows. Opposite to the lock-based approach, STM uses transactions. A transaction is a block of code accessing shared data which is meant to be executed atomically with an “all or nothing” policy: that is either all the effects of a transaction have to be visible when it commits, or none of them has to be visible in case of abortion. This abstraction allows for multiple transactions to be executed “at the same time”. The programmer just needs to specify the sequences of operations to be enclosed in transactions, while the system is in charge of the interleaving between the concurrent transactions. A transaction can either commit and update the system permanently or abort and discard all the changes done by its execution.

In this work, we are interested in the interplay between reversible computing and the STM approach to control the concurrent executions. Therefore, we present a formal framework for describing STMs in a simple shared memory context. In particular, when a transaction aborts, it is necessary to discard all the updates that it made and we need to bring the system back to the state before the execution of the transaction. To accomplish the behaviour above, we implement a rollback operator following the approach given in  [13]. A transaction can access a shared variable either in read or in write mode. Given this, different policies can be used to regulate the transactions which are accessing the same value in the shared memory. According to the implemented policy, some transactions will succeed and some will be aborted. We will show how it is possible to model writer and reader preference  [5] in our framework. Consider the following C-like code where two functions/threads access the same shared variables:graphic file with name 501864_1_En_16_Figa_HTML.jpg

All the possible executions of the two functions are reported above: either the two functions are executed sequentially or are interleaved (leading to an unwanted state). If we wrap the two functions into two atomic blocks then the third behaviour would be automatically ruled out by the system as one of the two transactions will be aborted depending on the implemented policy.

Syntax

In this section we give the syntax of our calculus. Let us assume the existence of the mutually disjoint sets Inline graphic (a set of variables) and Inline graphic (a set of transaction identifiers), ranged over by xyz and th, respectively.

The syntax of the calculus is given in Fig. 1. Write and read access to the variable x are represented with actions Inline graphic and Inline graphic. The sequential execution of the actions Inline graphic and Inline graphic together with the choice operator Inline graphic build the processes, given with AB productions. The term Inline graphic represents a transaction, where t is a unique identifier, A is the body of the transaction and Inline graphic is the set recording the identifiers of the transactions which have the write access to the variable that transaction t has to read. The idea behind the set Inline graphic is to allow transaction t to have read access to any variable, but to record the write access to them. In this way if the transaction that writes on the variable fails, the transaction that reads the same variable has to fail too. More explanations will be given in Sect. 3.

Fig. 1.

Fig. 1.

Syntax

Transactions, together with processes, build expressions. An expression can be prefixed with the actions Inline graphic and Inline graphic and we denote it as Inline graphic. Two expressions X and Y can be executed in parallel, Inline graphic, or in sequential order XY. We can note that the expression X can be the process that is not inside of the transaction, and that operation ;  allows us to have a transaction followed by an action (for example Inline graphic). The whole system, called configuration, is denoted with C and it represents the expressions together with the shared memory. The shared memory M is made of triples of the form Inline graphic for every variable in the system. In Inline graphic, x is the variable name, W and R are the sets recording transactions which had write and read access to x, respectively. Let us note that we abstract away from the value contained by variables, since this is not relevant for our framework. We just need to record whether a variable is read (a transaction reads its value) or modified (a transaction changes its value).

In order to write expressions in a more compact way, we define the notion of history context. For instance, having a transaction Inline graphic we can write it as Inline graphic where Inline graphic. Formally:

Definition 1 (History context)

A history context Inline graphic is a process with a hole Inline graphic, defined by the following grammar: Inline graphic.

Semantics

The semantics of our calculus is presented in two steps. First, we give the basic rules of the framework (common to all the policies) and then, we present the extra rules, necessary to model reader or writer preference. With reader preference, we intend that reading the value of a variable is always possible, i.e. no read access should be suspended, unless the write access already took place. Writer preference, on the other side, allows the write access to the value of a variable x even if some read access already took place. In this case, all the executing transactions with the read access to a value x need to be aborted and brought back to their initial state.

In what follows we provide the auxiliary functions necessary for the semantics of the calculus: the function which computes the set of the transaction identifiers of a given expression and the operation which removes transaction identifiers from the system.

Definition 2 (Set of the transaction identifiers)

The set of the transaction identifiers of a given expression X, written Inline graphic, is inductively defined as:

graphic file with name 501864_1_En_16_Equ1_HTML.gif

Definition 3 (Removing of identifiers)

The operation of deleting transaction identifier t from the configuration C, denoted as Inline graphic, is defined as follows:

graphic file with name 501864_1_En_16_Equ2_HTML.gif

When a transaction fails, the effects of the internal computation are undone and the entire transaction is restarted, that is, brought back to its initial state. As a consequence, the transactions depending on it are also rolled back. Dependency between transactions changes with the chosen preference. We shall see more information about the preferences by the end of this section.

To be able to identify the state of the internal computation of a transaction, we mark it with symbol Inline graphic. For instance, if we consider transaction Inline graphic, the actions Inline graphic and Inline graphic represent the past of the transaction and the action Inline graphic is the next action to be executed.

Now we define our rollback operator which brings a transaction back to its initial state i.e. the symbol Inline graphic is placed in the beginning of the transaction and its set Inline graphic is empty. For instance, if we roll back transaction Inline graphic, we obtain Inline graphic. Formally, we have:

Definition 4 (Rollback operator)

The rollback operator on the transaction Inline graphic, written Inline graphic, is defined as: Inline graphic.

In what follows, we give the semantics of our calculus. We shall start by introducing semantics rules representing the base of our framework (rules that are common for both models) and then we show the additional rules for each preference.

The common rules are given in Fig. 2. An action executed outside a transaction can be seen as an atomic step in which the action is discarded after the execution (rules Inline graphic and Inline graphic). Therefore, there is no need to keep track of its access to the variable. The only constraint is that they cannot access the variable while some transaction has read or write access to it.

Fig. 2.

Fig. 2.

Common rules for both models

Rule Write describes when a transaction can modify the content of a variable. To do so, there should not be another transaction which has already accessed the variable in either writing or reading mode. After the execution, the identifier t is added to the write access set W of the variable x and the symbol Inline graphic is moved to the next computational step. Rule Inline graphic allows the transaction t to execute the action Inline graphic at any moment. Then the identifier t is added to the set R of the variable x and the set Inline graphic is added to the set Inline graphic (if write and read access to the variable x are in the same transaction t, then it is not necessary to save the identifier t into a set Inline graphic).

To have a better intuition about these two rules, we give a simple example. Consider the transaction t with a corresponding shared memory

graphic file with name 501864_1_En_16_Equ3_HTML.gif

After executing the write access to the variable x, we obtain the system

graphic file with name 501864_1_En_16_Equ4_HTML.gif

where the pointer Inline graphic is moved to the next action and the identifier t is added to the write set of the variable x. Now we can perform the read access to variable y and we have:

graphic file with name 501864_1_En_16_Equ5_HTML.gif

where the identifier t is added to the read set of the variable y. The set Inline graphic of the transaction t remains empty since there is no transaction which had write access to variable y.

Rule Inline graphic allows expressions to execute in parallel (in an interleaving fashion) ensuring the uniqueness of the identifier t. By executing its last action, the transaction t can commit if the set Inline graphic is empty, by applying the rule Inline graphic. After it commits, the execution proceeds with the continuation Y and the identifier t is deleted from the remaining system. The intuition is that transaction t can commit if the other transactions, having a write access to the variables that transaction t read, have been committed. The rollback of the transaction t can be done with the rule Inline graphic. It will force every transaction in parallel having the identifier t in their set Inline graphic to roll back too. The intuition is that when the transaction with Inline graphic rolls back, every transaction which has read access to x should roll back as well. For instance, let us consider the system containing following transactions:

graphic file with name 501864_1_En_16_Equ6_HTML.gif

and that transaction t needs to be rolled back. Then, by applying the rule Inline graphic, we obtain the system:

graphic file with name 501864_1_En_16_Equ7_HTML.gif

in which transaction Inline graphic is rolled back too since Inline graphic while Inline graphic remains the same.

Now we can give the rules necessary to model reader and writer preference. To give a better intuition about the differences between the two models, we use the example from the introduction as a running example.

Reader Preference. To model the reader preference we use the rules from Fig. 2 and the rule given below. graphic file with name 501864_1_En_16_Figb_HTML.jpg

The rollback operator is triggered when the transaction t cannot write on the variable x (this happens when Inline graphic or Inline graphic). With the rule Inline graphic the transaction t goes to the state Inline graphic, i.e. the initial state of the transaction. Additionally, the identifier t is removed from every triple of the shared memory.

To illustrate it, we use the example from the introduction, abstracting away from the read and write values contained in variables and representing accesses of two threads to the shared memory in our framework with transactions Inline graphic and Inline graphic. Transaction Inline graphic has read accesses to variables y and x and then writes on variable z, while Inline graphic has read access to variables z and then writes on x. We have the following system

graphic file with name 501864_1_En_16_Equ8_HTML.gif

We assume that read accesses are executed in parallel and the obtained system is

graphic file with name 501864_1_En_16_Equ9_HTML.gif

Now transaction Inline graphic is executing write access to variable z but since in the memory for variable z we have Inline graphic (Inline graphic), the transaction Inline graphic needs to roll back according to the rule Inline graphic, and we have

graphic file with name 501864_1_En_16_Equ10_HTML.gif

where Inline graphic.

Writer Preference. To model the writer preference we use the rules from Fig. 2 and the rules given below. graphic file with name 501864_1_En_16_Figc_HTML.jpg

The rollback is triggered by the writer only in the case when another transaction has write access to the same variable. Therefore the condition on the rule W-RollW is simply Inline graphic. The additional rule, with respect to the reader preference is the rule Inline graphic. It allows a transaction to modify the value of a variable x if other transactions have read access to it. At the same time, all transactions executing in parallel whose identifiers belong to the set R, are requested to roll back.

To illustrate it, we use the same example as for the reader preference where read accesses are executed already. Therefore, we have the system

graphic file with name 501864_1_En_16_Equ11_HTML.gif

Now we can execute the write access to variable z, since in the rule W-Pref the condition for the read set R allows a transaction to perform the write access, and in that case all transactions in parallel having read access to variable z need to be rolled back. Therefore, transaction Inline graphic executes write access, while Inline graphic will be rolled back, and we have:

graphic file with name 501864_1_En_16_Equ12_HTML.gif

where Inline graphic.

Conclusion and Future Work

We have presented a framework to express the STM mechanism in a simple shared memory context. The framework is able to model two different policies for the execution of the concurrent transactions: writer and reader preference. Our intention is to start from a simple calculus and then to add in a modular way: nested transactions, data structures (e.g., C structures) and more complex scheduling policies. Nested transactions will require to record for each transaction a list of its children transactions. These children inherit the access of the parent transaction. There exist different policies to deal with nested transactions: closed nested transactions [17] and open nested transactions [18]. The difference is that in the first case the parent does not execute till all the children have committed, while in the second case the parent can commit even before its children. This may lead to inconsistencies which have to be dealt with compensations.

Our ultimate goal is then to prove that the modular framework satisfies the opacity  [14] property, that is, all the execution traces of our semantics, where the transactional bodies are interleaved, are equivalent to executions in which transactional blocks are executed as a whole (in a lock-based fashion) without being interleaved with other transactions.

Footnotes

This work has been partially supported by French ANR project DCore ANR-18-CE25-0007 and by the Italian INdAM – GNCS project 2020 Reversible Concurrent Systems: from Models to Languages. We also acknowledge partial support from the following projects: EPSRC EP/K011715/1, EP/K034413/1, EP/L00058X/1, EP/N027833, EP/N028201/1, and EP/T006544/1.

Contributor Information

Ivan Lanese, Email: ivan.lanese@gmail.com.

Mariusz Rawski, Email: mariusz.rawski@gmail.com.

Doriana Medić, Email: doriana.medic@gmail.com.

References

  • 1.Danos V, Krivine J. Transactions in RCCS. In: Abadi M, de Alfaro L, editors. CONCUR 2005 – Concurrency Theory; Heidelberg: Springer; 2005. pp. 398–412. [Google Scholar]
  • 2.Lanese I, Lienhardt M, Mezzina CA, Schmitt A, Stefani J-B. Concurrent flexible reversibility. In: Felleisen M, Gardner P, editors. Programming Languages and Systems; Heidelberg: Springer; 2013. pp. 370–390. [Google Scholar]
  • 3.Herlihy, M., Moss, J.E.B.: Transactional memory: architectural support for lock-free data structures. In: Annual International Symposium on Computer Architecture, pp. 289–300. ACM, San Diego (1993)
  • 4.Shavit, N., Touitou, D.: Software transactional memory. In: PODC, pp. 204–213. ACM, New York (1995)
  • 5.Courtois P-J, Heymans F, Parnas DL. Concurrent control with “readers” and “writers”. Commun. ACM. 1971;14:667–668. doi: 10.1145/362759.362813. [DOI] [Google Scholar]
  • 6.Grattage, J.: A functional quantum programming language. In: LICS 2005, pp. 249–258. IEEE Computer Society, Washington (2005)
  • 7.Phillips I, Ulidowski I, Yuen S. A reversible process calculus and the modelling of the ERK signalling pathway. In: Glück R, Yokoyama T, editors. Reversible Computation; Heidelberg: Springer; 2013. pp. 218–232. [Google Scholar]
  • 8.Lutz, C.: Janus: a time-reversible language. Letter to R. Landauer (1986)
  • 9.Yokoyama, T., Axelsen, H.B., Glück, R.: Principles of a reversible programming language. In: Conference on Computing Frontiers, Italy, pp. 43–54. ACM (2008)
  • 10.Lanese I, Nishida N, Palacios A, Vidal G. CauDEr: a causal-consistent reversible Debugger for Erlang. In: Gallagher JP, Sulzmann M, editors. Functional and Logic Programming; Cham: Springer; 2018. pp. 247–263. [Google Scholar]
  • 11.de Vries E, Koutavas V, Hennessy M. Communicating transactions. In: Gastin P, Laroussinie F, editors. CONCUR 2010 - Concurrency Theory; Heidelberg: Springer; 2010. pp. 569–583. [Google Scholar]
  • 12.Acciai L, Boreale M, Dal Zilio S. A concurrent calculus with atomic transactions. In: De Nicola R, editor. Programming Languages and Systems; Heidelberg: Springer; 2007. pp. 48–63. [Google Scholar]
  • 13.Lanese I, Mezzina CA, Schmitt A, Stefani J-B. Controlling reversibility in higher-order pi. In: Katoen J-P, König B, editors. CONCUR 2011 – Concurrency Theory; Heidelberg: Springer; 2011. pp. 297–311. [Google Scholar]
  • 14.Guerraoui, R., Kapalka, M.: On the correctness of transactional memory. In: PPOPP, pp. 175–184. ACM, New York (2008)
  • 15.Giachino E, Lanese I, Mezzina CA. Causal-consistent reversible debugging. In: Gnesi S, Rensink A, editors. Fundamental Approaches to Software Engineering; Heidelberg: Springer; 2014. pp. 370–384. [Google Scholar]
  • 16.Giachino E, Lanese I, Mezzina CA, Tiezzi F. Causal-consistent rollback in a tuple-based language. JLAMP. 2017;88:99–120. [Google Scholar]
  • 17.Gray, J., Reuter, A.: Transaction Processing: Concepts and Techniques (1993)
  • 18.Moss, J.E.B.: Open Nested Transactions: Semantics and Support (2006)

Articles from Reversible Computation are provided here courtesy of Nature Publishing Group

RESOURCES