Presentation is loading. Please wait.

Presentation is loading. Please wait.

A Modality for Safe Resource Sharing and Code Reentrancy

Similar presentations


Presentation on theme: "A Modality for Safe Resource Sharing and Code Reentrancy"— Presentation transcript:

1 A Modality for Safe Resource Sharing and Code Reentrancy
Rui Shi (Yahoo! Inc) Dengping Zhu (Bloomberg Inc) Hongwei Xi (Boston Univ.)

2 The Research Context ATS is a functional programming language with a highly expressive type system rooted in the Applied Type System framework: In ATS, advanced types such as dependent types and linear types are supported. In ATS, a programming style is advocated that combines programming with theorem-proving

3 A Function in ATS swap {l1,l2:addr} ( pf1: pf2: | p1: ptr l1, p2: ptr l2 ) : void = let val tmp = !p1 in !p1 := !p2; !p2 := tmp end // end of [swap]

4 Resource Specification
Resource protection is crucial in programming We need to properly specify resources We need to strike a balance when specifying resources If specification is too weak, verification may underachieve If specification is too strong, verification may become too demanding

5 Views for Classifying Capabilities (1)
Given a type T and a location L, we use for a (primitive) view meaning that a value of the type T is stored at the location L. Given types T1 and T2 and a location L, we use for a (compound) view meaning that a value of the type T1 is stored at L and another value of the type T2 is stored at L+1.

6 Views for Classifying Capabilities (2)
We can also declare recursively defined views (similar to datatypes in a functional language like ML). For instance the following declaration introduces a view constructor array_v: datatype array_v addr) = {l:addr} array_v_nil (a, 0, l) of () | {l:addr} {n:nat} array_v_cons (a, n+1, l) of l, array_v (a, n, l+1))

7 Viewtypes Given a view V and a type T, we can form a viewtype VT = VT
The following type can be assigned to a function (ptrget_L) which reads from a fixed location L: ptr(L))   T) The following type can be assigned to a function (ptrset_L) which writes to a fixed location L: ptr(L), T2)   1) Note that we use 1 for the unit type.

8 Resource Threading There is a serious problem with linear types: resources (of linear types) must thread through function calls. For instance, we have seen this in the types assigned to the functions ptrget_L and ptrset_L. Suppose larray(T) is a type for linear arrays in which each element is of type T. Then the array subscripting function sub for linear arrays needs to be given the following type: larray(T)  int  larray(T)  T So a linear array is threaded through each call to sub.

9 Sharable Arrays We refer to arrays in functional languages like ML as (non-linear) sharable arrays. The question we want to answer is how a sharable array can be implemented based on a linear array. More generally, how sharable data structures can be implemented based on linear ones.

10 A Sharing Modality Given a viewtype VT, we use □VT for a (non-linear) type such that a value of the type □VT represents the handle of a box containing a value of the viewtype VT. The introduction for □ is straightforward: vbox: (VT)  □VT However, the elimination for □ is tricky. Essentially, we need something like this: let □ x = □ v in … end

11 The “double-borrow” problem
Assume that a resource stored in a box has been borrowed. If it is to be borrowed again before it is returned to the box, we have a “double-borrow” problem: let □ x1 = □ v1 in … … let □ x2 = □ v2 in … … end … … end

12 A Type-with-Effect System
A pure function is one that does not borrow resources; it is given a type of the following form: (VT1, …, VT2) 0 VT A non-pure function is one that may borrow resources; it is given a type of the following form: (VT1, …, VT2) 1 VT So, we can distinguish a pure function from a non-pure function at the level of types.

13 Implementing references (1)
We use ref(T) for (non-linear) references to values of the type T. In ATS, ref(T) is defined as typedef ref(T) = [l:addr] | ptr l)

14 Implementing References (2)
fun refget (r: ref(T)):<!ref> = let val (pfbox | p) = r; val vbox (pf) = pfbox in ptrget (pf | p) end // end of [refget]

15 Implement References (3)
fun refset (r: ref(T), x:T):<!ref> void = let val (pfbox | p) = r; val vbox (pf) = pfbox in ptrset (pf | p, x) end // end of [refset]

16 Reentrancy (1) A function f is reentrant if it can be called in a nested manner. That is, another call to f can be made before a call to f is finished. A non-reentrant function is one that is not reentrant. For instance, functions like ctime, drand48, and strtok are non-reentrant. Their reentrant counterparts are ctime_r, drand48_r, and strtok_r, respectively.

17 Reentrancy (2) Pure functions are reentrant
Non-pure functions are not reentrant However, if a function is guaranteed to do borrowing/returning atomically, then this function is still reentrant. We assign such a function a type of the following form: (VT1, …, VT2) 0.5 VT

18 Conclusion We have presented a type-theoretic justification for implementing (non-linear) sharable resources based on linear resources We have fully implemented the sharing modality in ATS and also used it extensively. The solution we adopted to the “double-borrow” problem is simple but effective in practice. A more elaborate solution is certainly possible but it may not fit well in ATS.


Download ppt "A Modality for Safe Resource Sharing and Code Reentrancy"

Similar presentations


Ads by Google