A Program Logic for Reasoning About C11 Programs With Release-Sequences

With the popularity of weak/relaxed memory models widely used in modern hardware architectures, the C11 standard introduced a language level weak memory model, A.K.A the C11 memory model, that allows C/C++ programs to exploit the optimisation provided by the hardware platform in memory ordering and gain benefits in efficiency. On the other hand, with the weakened memory ordering allowed, more program behaviours are introduced, among which some are counterintuitive and make it even more challenging for programmers to understand or to formally reason about C11 multithread programs. To support the formal verification of the C11 weak memory programs, several program logics, e.g. RSL, GPS, FSL, and GPS+, have been developed during the last few years. However, due to the complexity of the weakened memory model, some intricate C11 features still cannot be handled in these logics. A notable example is the lack of supporting to the reasoning about a highly flexible C11 synchronisation mechanism, the release-sequence. Recently, the FSL++ logic proposed by Doko and Vafeiadis moves one step forward to address this problem, but FSL++ only considers the scenarios with atomic update operations in a release-sequence. In this article, we propose a new program logic, GPS++, that supports the reasoning about C11 programs with fully featured release-sequences. We also introduce fractional read permissions to GPS++, which are essential to the reasoning about a large number of real-world concurrent programs. GPS++ is a successor of our previous program logic GPS+, but it comes with much finer control over the resource transmission with the newly introduced restricted-shareable assertions and an enhanced protocol system. A more sophisticated resource model is devised to support the soundness proof of our new program logic. We also demonstrate GPS++ in action by verifying C11 programs with release-sequences that could not be handled by existing program logics.


I. INTRODUCTION
To discuss the behaviours of shared-memory concurrent programs, a memory model must be assumed, as it fundamentally defines how the threads communicate with each other. The traditional strong memory model, i.e., the sequential-consistency (SC) [1] model, assumes a single global memory that is accessed by all threads in an interleaving manner while the instructions in each thread are executed strictly following their program orders. However, this model is abandoned by most of the modern hardware architectures, The associate editor coordinating the review of this manuscript and approving it for publication was Porfirio Tramontana .
as it leaves very little room for optimisation. Modern hardware architectures embrace more relaxed memory models, which allow memory accessing operations to be reordered and threads to have their own observations about the memory states. For instance, the memory model used for the x86 architecture is the total-store-order (TSO) model instead of the SC model, as with write buffers facilitated, the x86 architecture allows some store operations to be reordered after the following load operations as long as a total order for all store operations is preserved. Other platforms like ARM and PowerPC adopt even weaker memory models.
With the various levels of memory weakening allowed by different hardware platforms, a unified interface is essential to help programmers to compose programs that have best performance regardless the underlying platforms. Therefore, in the C11 standard [2], [3], a language-level weak memory model, i.e., the C11 memory model, is introduced and has later been formalised by Batty et al. [4]. However, it remains challenging to understand or to reason about the counterintuitive behaviours introduced by this weakened memory model. Several program logics (RSL [5], GPS [6], [7] FSL [8], GPS+ [9], [10], and FSL++ [11]) focusing on C11 programs have been proposed during the last few years, but the reasoning about some highly intricate features of the C11 memory model is still not supported. A notable example is that the support to a highly flexible C11 synchronisation mechanism, i.e., the release-sequences, is usually left out. As shown in Table 1, there are four commonly used paradigms to establish C11 synchronisations. From the most straightforward way that only uses release write and acquire read pairs to the ones with fully featured release-sequences involved, the complexity increases along with its flexibility, as more program commands' interactions need to be taken under consideration. The formal reasoning about the most flexible paradigm facilitating with fully featured release-sequences is not supported until this work.
Beside the memory optimisations, another approach to maximising the benefits of multiprocessing is to reduce the fractions of tasks that could not be parallelised. For instance, instead of enforcing all the accesses to a shared resource to be mutually exclusive, a readers-writer-lock allows multiple readers (or a single writer) to exist at a time. The readers-writer-lock is widely adopted by real-world programs (e.g. the Linux kernel, pthread library, etc.). However, to formally verify a sophisticated algorithm like the readers-writerlock, fractional permissions [12], [13] will be a necessary ingredient, which is not yet supported in the GPS family.
In this article, we propose GPS++, a program logic that supports the reasoning about C11 programs with fully featured release-sequences. To achieve this, our logic is facilitated with an enhanced per-location protocol system, a new type of assertions, i.e., the restricted shareable assertion, and a set of new reasoning rules to deal with C11 release-sequences related operations. We also introduce the support to fractional permissions, which enables us to use the proposed logic against sophisticated real-world concurrent algorithms such as the readers-writer-lock.
This article extends the earlier conference version [14] significantly with the following additional contributions: 1. The support for fractional read permissions in the new logic, that allows it to reason about real-world concurrent algorithms that otherwise would not be possible; 2. The proof in the new logic of the correctness of a non-trivial concurrent program, i.e. readers-write-lock (which cannot be handled by previous logics in the GPS family) that illustrates the applicability of GPS++; 3. A more sophisticated resource-map-based instrumented semantic model that help characterise the subtle new features in GPS++; 4. The formulation of the soundness of the GPS++ logic, together with proof sketches for lemmas and theorems.
In the rest of the article, we first introduce our core language that captures most essential C11 features and the C11 memory model in §II. Then we discuss this work's foundation, the GPS+ logic, in §III, before presenting our new logic in §IV. We demonstrate the power of our new program logic by using it to verify example programs including a variant of the readers-writer-lock in §V. After that, we present the formal foundation of GPS++ in Section VI and illustrate its soundness in §VII. Finally, related work is discussed in §VIII and the article is concluded in §IX.

II. THE LANGUAGE AND THE MEMORY MODEL A. THE LANGUAGE
We use the expression-oriented language presented in Fig. 1 as our core language. It is used to capture the essential features of the C11 memory model. With the support to atomic read/write (load/store), fences, and compare-and-swap (CAS) our language can express C11 programs using various kinds of inter-thread synchronisation mechanisms, including the powerful release-sequence.
Our language has variable names (represented by metavariable x) and integer values (represented by metavariable V ) as values (Val). The pointer arithmetic, letbinding, loop command repeat e, conditional statement if . . . then . . . else, thread forking fork e, memory allocation alloc(V ), memory load (read) [ (v, v, v), and fence operations fence O are supported as our expressions (e). Specifically, in the loop command repeat e the loop body e will be repeatedly executed until a non-zero value is returned. VOLUME 8, 2020 Note that a memory order O needs to be specified for some expressions indicating which degree of memory relaxation can be applied to the annotated operation. Following the C11 language, we require a memory location is either atomic or non-atomic and this cannot be changed once defined. For an atomic location v 1 , the memory order O used in a load operation [v 1 ] O can be acquire (acq) or relaxed (rlx); the memory order O in a store operation [v 1 ] O := v can be either release (rel) or relaxed (rlx). Meanwhile, memory accesses to non-atomic locations can only be annotated as non-atomic (na). The compare-and-swap expression CAS O 1 ,O 2 (v 1 , v 2 , v 3 ) requires v 1 to be the address of an atomic location and performs the following steps in a single atomic move: firstly, the value of v 1 is loaded with the memory order O 1 (which can be either acq or rlx), then the value is used to ''compare'' with the expected value v 2 ; if they are the same, the value v 3 is stored to location v 1 with the memory order O 2 (which can be rel or rlx) (the ''swapping'') and a numerical value 1 is returned indicating its success; otherwise 0 is returned indicating the failure of the compare-and-swap process.

B. THE GRAPH SEMANTICS
The C11 memory model resides at language-level aiming at abstracting away the differences of underlying hardware memory models. Therefore, it is not straightforward to express it in an operational manner. The axiomatic approach is often used instead to formalise the C11 memory model, where execution graphs are used to represent candidate executions (with the program actions/events as vertices and their relations represented by the edges) and a set of axioms decide if an execution is legal or not. This is the approach adopted by Batty et al. [4] to give the first formalisation of the C11 memory model. The memory models used in the C11 program logics [5], [6], [8]- [11] are defined in a similar manner but with certain simplifications, e.g., only accepting synchronisations created using a simple way without release-sequences involved. This work follows the graph based axiomatic semantics, with extra information added for threads (highlighted in Fig. 2), and supports synchronisations with fully featured release-sequences.
As shown in Fig. 2, the event graph G (A, T , sb, mo, rf) concerns a set of events, and records their action type information in A (the action types will be further discussed shortly), their thread identities in T (i.e. to which threads they belong), as well as their relations in sb, mo, and rf. The sequenced-before relation (sb) represents the non-transitive program order. All store operations accessing a same location form a strict-total order, which we record in the modificationorder (mo). When a load operation reads from a store operation, this relation is tracked in the reads-from map (rf). We formalise the thread pool as T which tracks each numerically indexed thread's last event and the expressions to be executed.
As shown in Fig. 3 and Fig. 4, we adopt a two-layer semantics, namely, event-step and machine-step, following GPS and GPS+. An event-step (e α → e ) is the execution of e, resulting in a return value or a remainder expression (e ) and an action (α) to be added to the execution graph in the machinesteps. The executions of arithmetic, let-banding, repeat, and conditional expressions returns different values or remainder expressions but they only generates skip actions (S) as they do not involve memory accesses. The allocation expression alloc(n) generates an allocation action A( .. + n − 1), which indicates n fresh memory location ranging from to + n − 1 are allocated and is returned. Store and fence expresses generate corresponding write (W) and fence (F) actions with specified memory orders; and we let them always return 0 as they should not be used to change the program control flow. Note that the event-step rule for read action R only specifies that it should return some numerical value V . The actual value can be read is constrained by the memory model axioms (consistentC11) in the machine-steps (which will be discussed shortly in this section) with the global execution taken under consideration. There are two rules for CAS expressions to correspondingly capture the successful and failure cases. In the case of success, an update action U( , V o , V n , O r , O w ) is generated, where the current value V o stored at location is required to be the same as specified in the expression; otherwise, the CAS should be considered as failed and is treated as an atomic read action which reads some value other than V o .
We use the machine configuration T ; G to represent the execution states, where the thread pool T contains the expressions to be executed in each thread and the execution graph G is a record of the execution history. Machine-step rules are used to update the machine configurations. The first rule states that an arbitrary thread from T can take a move (e α → e ) and generate a new machine configuration ( T ; G ) based on the current one ( T ; G ) with the new event (a ) and the corresponding relations added to the event graph given that the C11 memory model axioms are preserved in the extended graph (consistentC11(G )). More specifically, assume the thread i in the thread pool T is chosen to execute, its last event is a and the expression to be executed is e. Then e is reduced to e following the corresponding event-step semantics rule, yielding a new action α with a new event name a . We update i in the thread pool with this information (a , e ), then add the newly generated event to the event graph as the following, yielding a new graph G . Firstly, the mapping a → α and a → i are added to the action map (G .A) and the thread map (G .T ), respectively. This information will be crucial for reasoning about programs with C11  release-sequences, as we will need to know if different writes are from a same thread or not. Secondly, we know that a comes after a, so we record it in the sequenced-before relation (G .sb). Finally, the modification-order only gets updated if a is a write (W) or a success update action (U), so we have G .mo ⊇ G.mo. Similarly, the read-from relation only gets updated if a is a read (R) or an update action (U) which reads from a write/update action b. The exact way these two relations to be updated is restricted by the C11 memory model axioms consistentC11 that to be presented in the next subsection.
The second machine-step rule indicates that the fork e command creates a new thread (i.e. j) that will be added to the thread pool. The expression e is waiting to be executed in the new thread while the parent thread (i) has whatever left in the evaluation context K [0].
A thread terminates if its expression is reduced to be a pure value and the program terminates when all its threads terminate.

C. THE MEMORY MODEL
A memory model defines how different CPU cores can access a shared memory, and thus controls how multithread programs should behave. As a language-level memory model that must be sufficiently generalised, the C11 memory model regulates the program behaviours by using a group of axioms based on the event graph. We have discussed the event graph; now we first introduce several derived relations before we can formally introduce the C11 memory model axioms.

1) HAPPENS-BEFORE RELATION
The happens-before relation is the cornerstone of the causality in C11 programs. That is, for two events a and b, unless we can establish that a happens before b (a hb → b), there is no guarantee that a's effect will be observed by b. The happens-before relation is derived from the sequencedbefore and the synchronised-with relations (to be discussed shortly in §II-C2), i.e., hb (sb ∪ sw) + . Intuitively, the happens-before relation preserves the program order for events within the same thread; however, for the events from different threads can by ordered in hb only if their threads are synchronised at appropriate locations.
This idea is demonstrated in Fig. 5 with an unsuccessful message passing program. In this example, we assume both x and y are initialised as 0. In the first thread, the flag y is changed to 1 (event b) after the message x is set to be 42 (event a); the second thread first reads y to be 1 (event c) then reads x (event d). Though a chain of relations can be established as a sb → b rf → c sb → d, the stale value 0 can still be read by d as the read-from relation between b and c is not strong enough to form a synchronisation, thus the VOLUME 8, 2020 happens-before relation a hb → d could not be derived and a's effect is not guaranteed to be seen by d.

2) RELEASE-SEQUENCE AND SYNCHRONISATION
As a weak memory model, the C11 memory model allows threads to have different observations about the memory. 1 But when necessary, one thread's observation can be passed to another if they are synchronised. To form a synchronisation and share its observation, the sharer's thread must first perform a release action. Intuitively, the release action would label its up-to-date memory observation as ready to be shared. Then a sequence of store operations, i.e. a releasesequence, work like messengers notifying their readers that some information can be acquired. However, the acquisition is only successful after an acquire action is performed in the reader's thread. In this way, the acquire action is synchronised with the release action and is obliged to acknowledge the memory modifications happened before the release action.
The release-sequence plays the crucial role in this process. It is led by an action with the release memory order, i.e., the release head, which can either be a release fence or a release store, and is followed by the longest sub-sequence of store operations from the modification order (mo) where these store operations are either in the same thread as the release head or atomic update operations (i.e., U).
As the example shown in Fig. 6a the release write event a is the release head; and the release-sequence also contains b and c as they follow a in the mo order and is either in a's thread (b) or is an atomic update (c). Another thread can acquire a's observation by reading from any event from this sequence. Fig. 6b shows that a release-sequence can be interrupted if a non-update store operation (c in this case) from a different thread is positioned in the chain of mo order. In the case shown in Fig. 6b, the release-sequence only contains the head a. As shown in Fig. 6c, a relaxed write can lead a hypothetical release-sequence and in this case itself is called a hypothetical release head. If an operation acquires from this sequence, it is synchronised with a release fence prior to the hypothetical release head if there is any.
To formally define the synchronised-with relation, we first define a predicate (along with some shorthand definitions) that indicates if an action b is qualified to be a member of the release-sequence led by action a: 1 For instance, in the example shown in Fig. 5, thread 2 can observe a state where x = 0 ∧ y = 1, which is infeasible from the perspective of thread 1.
For a store action a, we say that event b is in a's releasesequence, a rs → b or rs(a, b), if and only if: Then we can formally define the synchronised-with relation as that shown in Fig. 7: We have introduced the highly flexible release-sequence based C11 synchronisation mechanism. In Fig. 8, we demonstrate how C11 synchronisations can be formed in different manners by restoring the message passing protocol discussed in Fig. 5 in various ways. Recall that, as summarised in Table 1, existing C11 program logics usually support simplified versions of the C11 synchronisation mechanism, due to its complicity, with limited scenarios allowed to from synchronisations. These demonstrations are also used to illustrate which types of C11 synchronisations can be supported by existing C11 program logics.
The first C11 program logics, RSL and GPS, can only be used to reason about C11 programs with synchronisations formed between release write and acquire read pairs as that is shown in Fig. 8a. With C11 fences supported, FSL and GPS+ can also reason about programs like that is shown in Fig. 8b. Still, they do not accept release-sequences with more than one element. FSL++ overcomes this limitation, but expect the release head, it only accepts atomic update operations to be in a release-sequence (Fig. 8c). To the best of our knowledge, only this work supports the reasoning about C11 programs with synchronisations based on fully-featured release-sequences, including the scenario shown in Fig. 8d.

E. THE AXIOMATIC MODEL
With the preparations that have been made about synchronisations, happens-before relations and etc., in this subsection, we present the axiomatic definitions for the C11 memory model in Fig. 9 following a similar approach used by [4]. Intuitively, the axioms are regulations that rule out illegal executions, e.g., ''no one can read from an event that happens after itself'' or ''an update action cannot be interrupted'', and etc. These axiomatic rules also leave us enough room to ensure the aforementioned principle: no guarantee of observation without happens-before relations.
Specifically, ConsistentMO1 states that mo is a binary relation over writing actions. ConsistentMO2 requires all writing actions in mo to follow a strict total order. Consis-tentRF1 indicates there always is at least one writing action    before a reading on the same location, that is, all locations are initialised before reading. ConsistentRF2 says that a reading action cannot read from a writing that happens after itself. For a non-atomic reading action, ConsistentRFNA requires it must read from a writing action that happens before it. Coherence puts restrictions on happens-before relations and the modification orders, e.g. a reading actions should not read older value than its happens-before ancestors. AtomicCAS enforces no interruption could happen to an atomic update action. ConsistentAlloc states the sets of locations allocated by two allocation actions will not intersect, that is, no location will be allocated more than once. Acyclic is introduced to rule out the thin-air-read problem following [6], [9].
Note that while atomic locations are meant to be accessed concurrently, concurrent accesses (accesses that are not ordered in hb) to non-atomic locations with at least one write action lead to a hazardous situation called data-race, in which the program behaviour is undefined. The memory error is another hazardous situation, which involves accessing a location before it is allocated. Definitions for these two hazardous situations are needed to complete our semantical model as we need them to rule out executions with undefined results.

III. RECAP OF GPS+
Verifying concurrent programs is difficult. To reason about C11 concurrent programs with weak memory behaviours is even harder. To do this, GPS-like logics amalgamate three techniques from state-of-the-art concurrent program logics (e.g. [15]- [28]), namely ghost states, protocols and separation logic. Our proposed program logic, GPS++, follows the line of GPS works. In this section, we lay the foundation for the discussion of our program logic by briefly introducing its closest predecessor GPS+.

A. PROTOCOLS FOR ATOMIC LOCATIONS
As illustrated in previous sections, in C11 concurrent programs threads communicate with each other by writing and reading atomic locations. As updates may happen in other threads, it is difficult to determine the precise value of an atomic location. Therefore, GPS/GPS+ employs the concept of per-location protocols and each atomic location has its own protocol depicting how its states can evolve along with the program execution. The possible states for an atomic location are partially ordered, and the state assertion is used to describe the lower-bound state an atomic location can be in. That is, assuming an atomic location 's protocol is τ , the state assertion : s τ says that is at least at state s.
Atomic locations can be concurrently accessed by different threads, therefore their state assertions should be able to be duplicated and shared between different threads. These assertions that do not require exclusive ownership are called knowledge in GPS logics. A knowledge assertion is decorated with the notation and the following rules applied: : s τ ⇒ : s τ P ⇔ P * P P ⇒ P The first rule states that a state assertion is knowledge. The second rule says that copies can be made out of a knowledge assertion. When necessary a knowledge assertion can also be transformed back to its normal form using the third rule.
To complete the protocol definition τ for its atomic location , a partial order τ must be provided to depict all 's possible state transitions. That is, assuming is currently in state s and a write command moves it to state s , this is valid if and only if s τ s is defined in the protocol. In addition, state interpretations need to be specified for all states. A state interpretation τ (s, z) describes the conditions that must be satisfied for a write command to be permitted to write value z to and transfer to state s. On the other hand, when a reader reads at state s, it knows some conditions have been established in the writer's thread. Therefore, they can reach agreement about these facts, i.e., they are synchronised. The following rules formally capture this process.
The [GPS+-RELEASE-STORE] rule states that to move to the target state s , the state interpretation τ (s , v) must be derivable from the resource P currently possessed in its precondition (the first premise). Note that the ghost move used to imply the state interpretation refers to a transition that only affects auxiliary states leaving physical states unchanged. Note also that due to the possible moves from the environment, the actual state of before the writing may be different from the lower-bond state s in the triple's precondition. Therefore, the second premise is introduced requiring that the target state s is reachable from any possible state s that might be currently in. [GPS+-ACQUIRE-LOAD] The [GPS+-ACQUIRE-LOAD] states that some knowledge Q can be added to an acquire read's postcondition if the knowledge can be derived from the candidate states' interpretations. Note that only knowledge assertions can be retrieved, as the read operations from different threads may observe a same state and try to retrieve the same information. If the information to be retrieved is not duplicable, conflicts will raise. The assertion P included in this rule enables relyguarantee style of reasoning and reduces the possible states that can be read [6].

B. ESCROWS FOR NON-ATOMIC LOCATIONS
The [GPS+-ACQUIRE-LOAD] rule only retrieve knowledge assertions from state interpretations. However, the ownership of some exclusive resource is also often needed to be transmitted across threads. This can be done by using escrows in GPS/GPS+. Intuitively, an escrow σ : P Q is a safe protecting Q with a non-duplicable resource P as the key. Following ghost move rules are used to put some resource (Q) under escrow and retrieve it: is no longer ownership-dependent. It can be transformed into knowledge following the rule: As shown in the second rule, the ''key'' P will be consumed once it is used to open the safe and retrieve the resource Q. Therefore P is preferred to be a ghost assertion instead some assertions relating to physical resources. A ghost assertion in the form γ : t µ indicates that γ is a ghost variable, and its value is a ghost permission t drawn from some partial commutative monoid (PCM) type µ. With a fresh identity, a new ghost value t can be introduced out of thin air: true ∃γ . γ : t µ .

C. WORKING WITH FENCES
As shown in Fig. 8b, synchronisations can also be established by using relaxed write and read operations but only with the help from C11 fences. In GPS+, this process is interpreted as that a relaxed write can only share the resource made shareable (denoted as P ) by a prior release fence. On the other hand, when some resource is retrieved by a relaxed read, it cannot be used instantly. Instead, it is marked as waiting-tobe-acquired P and an acquire fence is needed to transform it back to its normal form.
The fence related rules are adopted by our new program logic. Detailed discussions will be provided in the next section to illustrate how we make them compatible with other more complicated features.

IV. REASONING ABOUT C11 RELEASE-SEQUENCES AND FRACTIONAL PERMISSIONS
The use of release-sequences provides C11 programs great flexibility to choose the best way to synchronise their threads. However, as discussed in previous sections no existing program logic supports the formal verification about the use of fully featured release-sequences due to its complexity. Also, there is no work in GPS family that supports fractional permissions. In this section, we introduce our new reasoning framework, GPS++, that support the aforementioned features with the aid from several novel techniques.

A. A NEW TYPE OF ASSERTION AND THE ENHANCED PROTOCOL SYSTEM
The key to reason about the C11 synchronisation process is to deal with the relaxed write operations involved. As that is discussed in §II-C2, unlike a release write, a relaxed write cannot form a synchronisation by itself. That is, no resource can be shared by a relaxed write to its readers unless (1) there is a release fence prior to it; or (2) it belongs to a release write's release-sequence. To reason about the behaviours of a relaxed write in the C11 synchronisation, its context must be taken under consideration. The first scenario is relatively easier, as we can adopt the shareable assertion introduced by GPS+ to indicate if there is a prior release fence that makes some resource available for the relaxed write operation to share. The second scenario is more complicated, as we need to know if there is a prior release write to the same memory location and if so, whether or not the release-sequence led by that release write is still valid at the point where the relaxed write takes place.
To tackle this problem, a naive solution is to introduce location-based restricted shareable assertions. That is, a release write operation on location may create an assertion P , which indicates P is shareable by following relaxed writes operation on who are assumed to be the members of its release-sequence. However, as discussed in §II-C2 a release-sequence could be interrupted by non-update writes from other threads and this definition is not sufficient to be used to detect these potential interruptions. Therefore, we introduce state-based restricted shareable assertions (which we call restricted-shareable assertions for short) instead. Specifically, a release write that changes location to state s may make some resource P shareable, P s , for the members of its release-sequence. To check if a following relaxed write belongs to the release-sequence and can use the restricted-shareable resource P s , we first check (1) whether they are operations on the same location; (2) whether they are in the same thread; and (3) whether the sequence is free from interruptions. The check for condition (1) can be done by simply examining whether the two writes follow the same protocol. To enable the checks for condition (2) and (3), we extend the state interpretation τ (s, z) used in GPS+ to the form like τ (s, z, tid, upd), where tid indicates in which threads the target location can be transformed to the state s, and upd is 1 if the state s can only be reached by atomic update operations or 0 otherwise. With these preparations, we derive the following predicates: With these definitions, the thread and interruption checks can be formalised as: where s is the state established by the release head and s is the target state of the relaxed write being checked. The following properties can be derived for our new restricted-shareable VOLUME 8, 2020 assertions based on our semantical model: The [SEPARATION-R] rule indicates that a restrictedshareable assertion can be split as while as several restricted-shareable assertions can be merged if they are restricted to the same state. The [UNSHARE-R] rule states that a restricted-shareable assertion can be transformed back into its normal form via a ghost move.
The new restricted-shareable assertion, the enhanced protocol system, and their properties are semantically supported by our upgraded resource model, which will be presented in later sections.

B. REASONING ABOUT C11 RELEASE-SEQUENCES
With our new restricted-shareable assertions and the enhanced protocol system introduced, new reasoning rule can be devised to handle the C11 programs with fully featured release-sequences. In this section, we first introduce the essential rules most related to C11 synchronisations in Fig. 10. Rules to deal with fractional permissions are presented in §IV-C, while other rules are discussed in §IV-D.
Unlike a release write in GPS+ which only needs to concern about what resource it can share to its readers, a release write in this work can also initiate a releasesequence, that is, it can make some resource shareable by the qualified relaxed writes followed. This idea is formalised in our [RELEASE-STORE] rule as that part of the resource P currently held in the release write's precondition can be transformed into a restricted shareable assertion Q 1 s .
We require the P used in the rule must be normal, i.e., it can not contain any special forms of assertions (e.g., shareable assertions or waiting-to-be-acquired assertions). This ensures that Q 1 is also free from special assertions and we do not create the problematic nesting of special assertions by putting Q 1 into . . . s . The formal definition for the normality check is normal(P) P ⇒ false ∨ P ⇒ false. This is not the only occasion where the normality check is used. Allowing special assertions to be transmitted across threads also raises problems, therefore we require state assertions to be normal as well to prevent special assertions from being included.
The [RELAXED-STORE-2] rule illustrate how a release write works in a release write's release-sequence. With the restricted-shareable assertion P 2 s o created by a release write and passed down to the relaxed write, the relaxed write knows it may be in a release-sequence created at state s o . The validity of the release-sequence needs to be checked using the second premise (recall §IV-A) then P 2 can be used to imply the target state interpretation (the first premise).
Our reasoning framework is compatible with the rules developed in GPS+ for reasoning about the synchronisation initiated by a relaxed write with the help from a prior release fence. Therefore we inherit these rules as our [RELAXED-STORE-1] and [RELEASE-FENCE] rules. They state that a release fence can turn some resource into a (unrestricted) shareable resource and then being used by any relaxed write that follows. Intuitively, these tow rules are sound for C11 release-based synchronisation mechanism because every relaxed write after a release fence is a (hypothetical) release head and is allowed to share the observations established at point where the release fence took place (recall §II-C2).
On the other side, if the reader is an acquire read, the [ACQUIRE-LOAD] rule applies. It states that when observing the location at a certain state s , some knowledge Q can be learnt from the state interpretation. Similarly, as shown in the [RELAXED-LOAD] rule, a relaxed read can also retrieve some knowledge from the state interpretation, but this knowledge Q is not instantly useable and is waiting-to-beacquired by a following acquire fence that may transfer it to a normal knowledge according to the [ACQUIRE-FENCE] rule. These three rules are adopted from GPS+ with minor changes, as our extension with release-sequence is still compatible with the principles working on the reader's side.
Compare-and-swap (CAS) plays an important role in C11 concurrent programming. It is the foundation to the implementation of many locks and non-blocking algorithms. It can join in a release-sequence without being in the same thread as the release head. Therefore, sophisticated concurrent algorithms like the atomic reference counter [11] can use CAS operations to create synchronisations between many different threads. GPS+ provides some basic support to CASes without user specified memory orders. In this work, we devise a set of rules to cover CAS operations with all possible memory order specifications. We first take a close look at the [ACQ-REL-CAS] rule. The first premise corresponds to the case of success where 's value is same v o as expected. In this case, the acquire-release CAS performs as a release store However, unlike normal release write which can only use the resource P in its precondition to imply its target state's interpretation, a successful CAS can also use the resource from the state interpretation of 's current state (τ (s , v o , −, −)). In this way, the CAS can retransmit the information passed down in its release-sequence. Moreover, a successful CAS can retrieve non-knowledge resources from the state interpretation of 's current state. The second premise corresponds to the case of failure where is found to have some value other than v o . In this case, the acquire-release CAS performs as an acquire read and some knowledge R can be retrieved from the actual state observed.
The ideas for the other CAS rules are similar. However, when a CAS has relaxed memory order for its read-

C. DEALING WITH FRACTIONAL PERMISSIONS
As discussed in §II-E, while atomic locations are designed for concurrent accesses, concurrent accesses (i.e., the accesses not ordered in hb) to a non-atomic location with at least one of them being a store operation lead to data-races. To ensure the verified programs are data-race-free, previous work in GPS family models each non-atomic location as a resource that could only be exclusively held by one thread at a time, which means these logics can not support the reasoning about programs with concurrent non-atomic reads (though they would not result in any race-condition). To verify real-world concurrent programs with concurrent non-atomic reads (e.g. the readers-writer-lock algorithm), we introduce fractional permissions for non-atomic locations.
Fractional permissions technique is an example of partial permissions [12], [13]. In our setting, a fraction in the interval [0, 1] is used to represent the portion of the ownership to a non-atomic location. The full permission 1 → − is needed for a thread to write to ; while for a non-atomic read, only a fraction of the permission will be sufficient: The empty permission 0 → − is semantically equivalent to emp. Permissions can also be combined or separated as defined below: According to the composition rules, a full permission (writing permission) is not compatible with another full permission or any other non-zero permissions. As a result, a program verified by our logic would not have any race condition where a write goes in parallel with other accesses to the same non-atomic location.

D. OTHER RULES
Besides the rules highlighted in previous subsections, we also have the following rules that make our reasoning system complete. We gather them into groups for the convenience of discussion.
The following inference rules depict properties of knowledge assertions. That is, knowledge can be transformed back to its normal form; knowledge symbol can be safely nested; a piece of knowledge acts like pure information and thus the separation assertion is equivalent to the logical conjunction; a picked escrow, an assertion about atomic location and a pure term are all knowledge; and a duplicable ghost term is also a form of knowledge.
The first inference rule below states that ghost terms can be composed or separated according to their PCM definitions. The second inference rule states that two atomic assertions about the same location only coherence if the protocols are same and the states are reachable from one to another or the other way around.
Following rules are about possible ghost moves. Particularly, similar to the [UNSHARE-R] rule we have discussed before, the fifth rule allows us to change an unrestricted shareable assertion to its normal form. The seventh rule states that a new ghost term can popup from thin air with a fresh identifier. The eighth rule states that a ghost variable can be updated to a new value as long as the new value is compatible with the environment. The last two rules are inherited from GPS/GPS+ to cope escrows.
Q Note that, following the GPS/GPS+ logic for PCM terms with type µ we use the shorthand notation t 1 # µ t 2 to indicate that t 1 ⊕ t 2 is defined. The type declaration can be omitted when it is obvious.
The following rule is for the memory allocation. Starting with any valid precondition, alloc(n) allocates n fresh and continuous locations, which are marked as uninitialised, and uses the leading location as its return value. [ALLOCATION] The following tow rules are for atomic initialisation. In the precondition P must hold as changing an atomic location to a particular state requires the state interpretation to be satisfied.
Essentially, the following rules states that the special assertions are not to be nested. Nesting special assertions is problematic as it may introduce things violate the exquisite design of the whole system. For instance, assuming we allow an assertion in the form of P , it immediately becomes shareable, P , after an acquire fence which does not have the releasing semantics. Therefore, we prevent such nesting from the resource model level and these inference rules are corollaries of our resource model design. Note that the annotation (e.g. a) used in these rules can be any valid label (for restricted shareable assertions) or nothing (for unrestricted shareable assertions).
We also have the following rules for conditional statements, let-binding, fork expression, and the repeat loop. The fork rule states that given e can be safely executed from the precondition Q, we can fork a new thread with the precondition {P * Q} to execute e and leaving only P to the parent thread. [CONDITIONAL] In this section, we first demonstrate our logic with an illustrative example using a release-sequence to pass messages between three threads. Then, we further illustrate the power of our logic by using it to verify a readers-writer-lock implementation where both the release-sequence and concurrent reads are involved.

A. AN ILLUSTRATIVE EXAMPLE
In Fig. 11 we show a message passing program. In this example, the initial values for x and y are both 0. In the first thread, the message x is set to be 42 then y is set to be 1. As the write operation to y is a release write, it initiates a releasesequence that contains the following relaxed write and may contain the CAS in the second thread. In the third thread, y is repeatedly checked until a non-zero value is observed. Then the message x is examined. Note that, for readability we use x = e 1 ; e 2 as an equivalent expression for the command let x = e 1 in e 2 (or simply e 1 ; e 2 if the evaluation result of e 1 is not used in e 2 ). For the same reason, we use || to separate the threads forked.
We assert that at the end of the execution, the reading of x must return the new value 42. Intuitively, this is because for the third thread to exit the loop, a non-zero value y must be observed, which can only be the result from one of the writes in the release-sequence led by the release write to y in the first thread. Therefore a synchronisation is formed between the release write to y and the acquire read of y, ensuring the information about x = 42 is available when the their thread reads the value of x. To formally reason about this procedure, the protocols for x and y must be defined first. We call x's states x o (the initial state) and x n (the new state). Its protocol P x allows one possible state transition: x o P x x n . The state interpretations can be defined as: which states that thread 1 is allowed to change x to state x n by writing 42 to it and it is not necessary to be a CAS.
There are four states for y: y 0 , y 1 , y 2 and y 3 and the following transitions are permitted: y 0 P y y 1 , y 1 P y y 2 , y 1 P y y 3 , and y 2 P y y 3 .
The state interpretations are defined as: which indicates what values, threads, and the CAS indicators are needed to move y to a corresponding state. Most importantly, the interpretations also specify that the stores must have the knowledge x : x n P x at hand before the actions can be taken. Therefore, when the acquire load in the third thread reads from any one of them, the knowledge about x can be retrieved.
The proof of the program is illustrated in Fig. 12. As the threads start with observing x and y in their initial states. In the first thread, the relaxed store to x moves x to its new state thus we have x : x n P x in (1.2). This resource is essential for the next command to be performed as it is required to know x : x n P x in the state interpretation of y 1 . With x : x n P x at hand, the release write to y can be performed and moves y to the state y 1 . Moreover, according  to the [RELEASE-STORE] rule and rules about knowledge it can make a restricted-shareable cope of x : x n P x , which can be used by the relaxed store that follows. When processing the relaxed store to y, the [RELAXED-STORE-2] rule is applied. The release-sequence validity check will success as the only state that can be in the middle of the release head y 1 and the target state y 3 is y 2 , a state can only be reached with a CAS operation, and CAS does not interrupt a release-sequence.
In different scheduling, the CAS from the second thread may find y to be in state y 0 , y 1 , or y 3 before its execution. The CAS only success if it observes y 1 . But even when it fails, the protocol still holds. According to the [ACQ-REL-CAS] rule, the CAS operation's postcondition can be derived as shown in (2.2).
In the third thread, first y is repeatedly read. According to the [REPEAT] rule and the definitions of P y , exiting the loop needs y is at least at state y 1 as that is denoted in (3.2). According to the [ACQUIRE-LOAD] rule, some common knowledge can be retrieved from the state interpretation, which is x : x n P x in this case. Therefore, when x is read in the last step, it is guaranteed to return the latest value 42.
Our verification system can also detect possible interruptions in a release-sequences and will not allow the verification to go through. This is illustrated in the following example shown in Fig. 13, where the CAS operation in the second thread is changed to a relaxed store.
For the new program, state transitions and interpretations for y have to be changed to: y 0 P y y 1 ∧ y 0 P y y 2 ∧ y 1 P y y 2 ∧ y 1 P y y 3 ∧ y 2 P y y 1 ∧ y 2 P y y 3 ∧ y 3 P y y 2 P y (s, v, t, c) If we attempt to apply [RELAXED-STORE-2] to the command [y] rlx := 3 and change y to state y 3 using the restricted-shareable resource obtained from release head y 1 , the validity check for the release-sequence (the second premise) will fail as according y's protocol definition, a non-CAS state y 2 from a different thread may be interrupting. The verification will fail as we would have expected.

B. VERIFYING THE READERS-WRITER-LOCK
In this section, we use our reasoning system to verify the readers-writer-lock implementation shown in Fig. 14. Note that, this lock has a bounded capacity N, i.e. it allows at most N readers (or one writer) to access the protected non-atomic data field at a time. Note also that, for readability we use the following field offsets: x.data x + 0, which is the location of the data field; and x.count x + 1, which refers to a counter that keeps track of the number of active players (a reader is counted as 1, while a writer is solely counted as N). Once the lock is created and initialised by the new() function, a reader can atomically increase the counter by 1 (when there are vacancies available, i.e. r 1 = N in Fig. 14 2 ) to inform other players that there is an active reader, which will prevent a writer from obtaining the lock. After using the shared resource, the reader relinquishes the reader's lock by atomically decrease the counter by 1. A writer waits until the counter is 0 (which indicates that there is no other reader nor writer); then it atomically set the counter to N indicating that the shared resource is fully occupied; then it can safely modify the non-atomic data. When finishing, the writer releases the lock by setting the counter back to 0.
Our readers-writer-lock allows concurrent reads. To verify such an algorithm, we use fractional permissions. The idea is to divide the permission to access x.data into N pieces (1/N each). Correspondingly, the value of the counter represents how many pieces of the fractional permissions have been distributed. Atomically increasing the counter by 1, a reader gains one piece of 1/N permission, which is sufficient for it to perform the read action. However, a writer will have to update the counter from 0 to N to retrieve the full permission that consists of all of the N pieces. When releasing the lock, the permissions go back to the invariant (or protocol, in our terminology). This design is demonstrated in the execution graph shown in Fig. 15, which is annotated with the permissions transferred along the execution. In this particular execution, Writer 1 first sets x.data to 42 after obtaining the full permission. Then this information is released together with the full ownership of the protected data by the release write c. In fact, c initiates a release-sequence, from which the two readers both retrieve one piece of the 1/N permission to access x.data and read the value 42. The rest of the permission goes to Writer 2 when j reads from the release-sequence (which is under- Now we embed this idea into the definitions of the counter's protocol P c and prove that our algorithm works as intended while the protocol is preserved. Firstly, we choose c i,j as the counter's states, where i tracks how many pieces of the fractional permissions have been issued so far and j repre- sents the number of the fractional permissions that have been returned. As the capacity of our lock is N, we require that for any valid state i ∈ [j, j + N] holds. For valid states, the state transitions are defined as c i,j P c c i+1,j (when the counter is increased and new permission is issued) and c i,j P c c i,j+1 (when the counter is decreased and some permission is returned). The state interpretation is defined as below: This definition specifies that at state c i,j , we have x.count = i − j. Both CASes and atomic writes can change x.count to 0 (i = j); however, we must use a CAS (u = 1) to change x.count to other states (where i < j). Most importantly, at state c i,j we must ensure that there is (N − (i − j))/N permission under the guard of the protocol. This enables a player to retrieve some permission when it increases the counter (move i forward) and enforces a player to return permission when it decrease the counter (move j forward). With these preparations, we can verify our readers-writerlock algorithm. Firstly, we demonstrate in Fig. 16 that the new() function prepares the lock invariant.
Then, as shown in Fig. 17, a reader begins with some (maybe dated) knowledge of the counter. It repeatedly reads from the counter until it reads some value that is not equal to N, which indicates that the lock is not fully occupied. According to the protocol, we can deduce that at state (2) r 2 is actually smaller than N. This is critical for our reasoning, as when the reader increases the counter in the next step, we will have to know it would not bring the counter over the bound and break the protocol. Therefore, after a successful CAS that increases the counter by 1, the reader exits the loop knowing that the protocol is preserved and a fraction of the ownership of x.data is retrieved as shown in state (4). At this stage, the resource retrieved is waitingto-be-acquired, as the CAS itself has only relaxed memory order for loading. An acquire fence turns the resource to its normal form at (5). Then x.date can be read according to the [NON-ATOMIC-LOAD] rule. When unlocking, the reader first gets the latest value of the counter (in state (7)). As it have a fractional ownership of x.data at hand, we can deduce that the environment cannot change the counter to 0, which requires that all the fractions of x.data's ownership to be returned. This idea is also formalised in the [RELAXED-LOAD] rule, according to which we can only read states whose interpretation is compatible with the resource we currently hold. Thus, we know that the counter's latest value must be greater than 0 and can be safely decreased by 1 using a release CAS when we return the fractional permission (state (9)). At last, we return the value read from x.data.
The verification of the writer's program is shown in Fig. 18. A writer's lock can only be acquired when the value of the counter is 0. When it reads 0 from the counter, it starts attempting to update the counter to N using CAS. When the CAS successes, the full ownership of x.data can be retrieved according the protocol and the [RELAXED-LOAD] rule (in state (3)). Then, an acquire fence makes the waiting-to-be-acquired resource locally available before it can be changed to the new value v that is given in the parameters. Releasing the writer's lock is easier than releasing a reader's lock. As the writer owns the full permissions to the protected data (state (6)), it knows that the environment cannot change the counter to another state (which requires to add or remove fractional permissions from the protocol) during the time it holes the lock. Therefore, the writer can simply use a release write to change the counter back to 0 and release the full ownership of the data.

VI. THE RESOURCE BASED SEMANTIC MODEL
With memory weakening behaviours, it is difficult to model the semantics of C11 programs based on a single piece of sequentially consistent heap shared by all threads. Instead, GPS and GPS+ use resources and resource triples respectively to depict the computational states of the threads and, based on the concept of resource, GPS and GPS+ develop an instrumented semantics to bridge the program logics and the event/machine level semantics similar to the one we have defined in §II. In this section we first give a brief introduction to our predecessors' semantic models, on top of which we can introduce our new resource-map model that is much more expressive and enables us to depict the behaviours of C11 release-sequences.

A. RESOURCES AND RESOURCE TRIPLES
In the GPS logic, resources are used to logically describe computational states. A resource r ∈ Resource is a triple combined with a physical location map, a ghost identity map, and a set of known escrows: ( , g, ). For a non-atomic location, the physical location map maps it to some value na(V ); for an atomic location, maps it to a trace of states governed by the corresponding protocol at(τ, S); and there are also infinite uninitialised locations are mapped to ⊥. Similarly, the ghost identity map tracks the ghost values for our auxiliary variables. All established escrows are recorded in the known escrow set. Resources form a PCM with composition ⊕. Some useful definitions are: With resources defined, the semantics for a GPS proposition can be defined as a set of resources, i.e., P ρ ⊆ Resource, where ρ is a term interpretation assumed for protocol states and other PCM terms. Note that, GPS propositions depict the lower bound of the states, that is: To support the reasoning about C11 fences, in GPS+ we introduced two new types of assertions, i.e. shareable assertions and waiting-to-be-acquired assertions. Correspondingly, its semantic representation is lifted from the resource based model to a model based on resource triples. A resource triple (r L , r S , r A ) combines three resources to represent the locally available resource, shareable resource, and the resource retrieved from other threads that is waiting for an acquire action to merge it into the local resource.

B. NEW RESOURCE MAP BASED MODEL
In this work, to deal with the even subtler restricted sharable assertions, we extend the underlying resource model in GPS/GPS+ logic to a more expressive label indexed resource map: where Label {L, S, A} ∪ S and S is the domain of the atomic locations' states. There are three special labels, R(L), R(S), and R(A), which respectively represent the local, (unrestricted) shareable and the waiting-tobe-acquired resources. For a resource indexed by a state, R(s) (s ∈ S), it represents the resource that is made shareable at state s. The idea behind resource maps is to partition the resource available to a thread into fragments and label them for easier manipulation. When putting the resources under all the different labels together, we should get a meaningful resource back. Therefore, we define that a resource map R is well-formed if the sum of all its components, i.e. ⊕ l∈Label R(l) (or ⊕ R for short), is defined.
Similar to the resources introduced in the GPS logic, the ResMap is also a PCM. Its composition operation ⊕ is point-wisely lifted from the resource composition operations. We say two ResMaps are compatible R#R if we have R ⊕ R defined. There is an identity element EMP, which represents empty for all labels: ∀l. EMP(l) = emp. Like that in the GPS logic, propositions in GPS++ are lower bounds of the described states: The interpretations for GPS++ propositions are also lifted to the ResMap-based model. To check if a resource map R satisfies a ''basic'' proposition P (an assertion that does not contain knowledge, shareable, or waiting-to-be-acquired parts) only its local component is concerned. For instance, R ∈ : s τ ρ ⇔ ∃S. R(L). ( ) = at(τ, S) ∧ s ∈ S. For knowledge, (restricted/unrestricted) shareable, and waiting-to-be-acquired assertions, the resources under particular labels are picked out and checked: Note that the stripping operation on a resource map |R| is a point-wise lifted GPS stripping, that is: Note also that, R[l → r] represents a new resource map that is generated from R by updating R(l) to r. The third definition gives the semantics for our newly introduced restrictedshareable-assertions. Intuitively, it states that R satisfies P s if the resource indexed by its s label contains the information needed by P. The semantics for other special assertions is defined in a similar way. By defining the semantics like this, we can securely rule out the undesirable nesting of special assertions. For instance, one can not construct a R that satisfies P where P is not emp.
Composed propositions like the separating conjunction are straightly lifted to the resource map based model: The semantics for other types of assertions is left in appendix.

1) MODELLING PHYSICAL LOCATIONS
In GPS/GPS+ na(V ) is used to represent a non-atomic resource with value V assigned to a non-atomic location in the physical location map . A na(V ) resource is not duplicable as it is only compatible with the empty resource ⊥. As we now support fractional permissions to non-atomic locations, we use na(V , f ) to represent a non-atomic resource where f ∈ [0, 1]. We have the composition of non-atomic resource defined as: Following GPS/GPS+, an atomic location's value is modelled as at(τ, S) instead of some concrete values. The τ is the protocol the location follows, and S is a trace (totally ordered set) of states it has gone through. One atomic value is compatible with another if they follow the same protocol and the union of their traces remains to be a well-formed trace.
For atomic values, we have following shorthand definitions: at(τ, S) τ at(τ, S ) ∀s ∈ S. ∃s ∈ S . s τ s π ≡ τ π π τ π ∧ π τ π VOLUME 8, 2020 Intuitively, the first definition depicts the fact that the atomic value at(τ, S ) is newer than at(τ, S). In practice, if a thread holding at(τ, S) for an atomic location discovers that the environment has changed their copy of to at(τ, S ); then it may update to the new value as well. The second definition depicts the situation that two states under the same protocol are mutually transferable. This usually happens when two unsynchronised threads are going to change a same atomic location to different states. Therefore, the two states must be defined as mutually transferable to cope the unpredictable scheduling.
A physical location can also be uninitialised uninit or unallocated ⊥.

2) GHOST MOVES
Similar to that in GPS/GPS+, the semantics for our ghost moves are given by resource-level ghost moves: The difference is that resource maps are now used at the resource-level for greater expressiveness. For example, our new ghost move [UNSHARE-R] P s P is validated by the following resource-level rule: Intuitively, it states that a resource map R can move some resource r from one of its shareable components (unrestricted shareable component L or restricted shareable component indexed by one of the labels in S) back to its local component.
The resource-level ghost move rules are designed to avoid modifying physical states; therefore, the ghost moves are guaranteed to only change auxiliary/logical computation states. The rest of the resource-level ghost move rules are left in appendix.

3) RELY/GUARANTEE DEFINITIONS
Following GPS/GPS+, we provide an instrumented semantics for all actions allowed in our model in a rely/guarantee style. But unlike GPS/GPS+ instrumented semantics which are built on resources or resource triples, our actions manipulate more expressive resource maps, which gives us the flexibility to depict the subtle differences between all kinds of actions including their interactions in release-sequences. A full definition of the rely and guarantee conditions are presented in Fig. 19 and Fig. 20.
First we introduce the definition of environment moves envMv(R, , V ), which depicts a set of resources that could be acquired 4 by reading the location with value V .
The resource that could be acquired is depicted by interp(τ )(s, V ), which is described by the state interpretation of the state read s, i.e. τ (s, V ) ρ . The R in the definition is the resource map the current thread holds. It is used to limit the values can be read as in a well-behaving environment it is impossible to perform a write operation that requires resources incompatible with R.
For an action α and its precondition represented by R, the rely condition rely(R, α) describes which kind of resource maps R rely (with potential environment changes taken under consideration) can be accepted for α to be safely executed. To help the readers understand the rely conditions defined in Fig. 19, we interpret them in an intuitive way below. First, a non-atomic read relies on its current resource map's local component to have the expect value to read and the permission for the designated memory location is greater than zero. A relaxed read relies on the condition that there is some environment move to be read from and then the resource retrieved can be put into the local resource map's waiting-to-be-acquired component. Meanwhile, an acquire read can put the retrieved resource directly into the resource map's local component. Note that only knowledge can be retrieved for read operations. The rely conditions for the atomic update operations are similar to the read operations with corresponding memory order, except that they can retrieve non-knowledge resource.
A guarantee condition guar(R pre , R, α) signifies that the action α guarantees to generate some resources (R sb , r rf ), in which the resource map R sb is left for its sb successors and the resource r rf could be passed to its potential readers. Note that the action's precondition is represented by R pre ; however the action is actually executed with R due to the possible environment moves. We use at to represent atomic memory orders (rel or rlx for writing orders; acq or rlx for reading orders), when it is unnecessary to specify which particular order is concerned. Intuitively, a skip action guarantees that it gives nothing if some action tries to read from it; and leaves everything to its sb successor. An allocation action leaves its sb successor a resource map with newly allocated locations. The read actions guarantee that the resource map left for their sb successor contains some non-trivial information about the location read. A non-atomic write requires full permission for the target location (or the location is uninitialised) in R and leaves the location with updated value in the resource map for its sb successor. The guarantee conditions for relaxed and release write will be compared below. Atomic update operations have the same guarantee conditions with the write operations having the same memory order. For release fence, it can move resource between the resource map's local and shareable components; and the acquire fence may move resource between the resource map's local and waiting-to-beacquired components.
With the support from resource map based model, our new rely/guarantee definitions can depict the subtleness of the C11 release-sequence behaviours. For instance, both relaxed and release write can send some information to their potential readers; but their guarantee definitions are very different. A relaxed write who changes the target location to state s can only send out the information made shareable by previous release fences or valid release heads, which is represented using s in the following definition: Therefore, from R (the resource map after the writing takes effect), a relaxed write can take a r rf that satisfies its state interpretation from the labels valid for it to share (r rf ≤ ⊕ l∈validS(s) R (l)), and leave everything else (R sb ) to its sb successor. Note that we ensure that the internal participation of R sb is consistent with R (no fragment of resources is misplaced under a different label) by requiring: ∀l. R sb (l) ≤ R (l). On the other hand, a release write can directly use the resource under its local label, 5 i.e. r rf ≤ R (L). In addition, a release write can make some resource (r 2 ) restricted shareable to the following writes in its release-sequence. The relaxed and release atomic updates are similar to the corresponding writing actions only that they can use the resource from their reading sources (r in ) to fulfil their target states' interpretations, as they can be always considered as a part of release-sequences.

VII. SOUNDNESS
In this section, we formulate the soundness of our proposed program logic. As in GPS/GPS+, our reasoning framework is compositional. That is, triples can be proved individually and then a bigger proof can be generated by connecting the proved triples with the let and fork rules provided. To bridge the gap between the localised reasoning and the threads' global interactions and non-sequential-consistent behaviours, we formulate the notions of local safety and global safety and provide the soundness proof in both layers.

A. LOCAL SAFETY
The rely-guarantee reasoning [15], [29] is deeply rooted in the soundness of GPS++. As GPS/GPS+, we formulate local safety to indicate that given a thread's rely-condition respected by other threads' guarantee-conditions, it confirms to its own guarantee. However, resource maps are used as the base model in our proofs to capture the subtle C11 synchronisation features such as release-sequences.
Based on the rely and guarantee definitions we have introduced in the previous section, we define LSafe n (e, ) as the set of resource maps on which the command e can safely execute for n steps and end up with , which is the interpretation of triple's postcondition with the return value filled in place holders, being satisfied: If e α − → e then ∀R F #R. ∀R pre rely(R ⊕ R F , α).∃P .
It is worth noting that with the possible environment moves taken under consideration, the expression e actually works on some R that follows the action's rely condition. Note also that the wpe provides a sanity check to rule out the obvious problematic environment changes.
Intuitively, the definitions above state that a memory allocation action will only allocation fresh locations; an atomic write may observe its target location at a state other than the state in its precondition, while this is not allowed for an atomic update action.  As that in GPS and GPS+, we formulate the local soundness definition as: ρ {P} e {x.Q} ∀n, R ∈ P ρ . R LSafe n (e, λx. Q ρ ).
The local soundness provides semantics for our Hoare triples. It states that starting from any computation state R in the triple's precondition P, it is safe for the expression e to execute as many steps as necessary; and when e terminates, we can expect that all its possible result states satisfies the triple's postcondition λx. Q ρ , where x is e's return value.
Ghost moves and corollary inference rules also play an important role in our reasoning system. To validate the (local) soundness of our reasoning system, we first demonstrate the correctness of our ghost move and corollary inference rules introduced in §IV.
Our reasoning system is featured with new corollary inference rules (in the form of P ⇒ Q), namely

Corollary 1 (Soundness of Corollary Inference Rules):
Our corollary inference rules are semantically sound. That is, given an inference rule allowing P ⇒ Q, we have ∃R. R ∩ P ρ ⊆ Q ρ In our reasoning system we support ghost moves depicted by rules [UNSHARE-R] and [GHOST-MOVE-1. . . 8]. A ghost move is a transition that only modifies auxiliary/logical computation states. This is ensured by the resource-level ghost moves and formalised in Corollary 2 (whose proof is left in the appendix).
Corollary 2 (Soundness of Corollary Inference Rules): Our ghost move rules are semantically sound. That is, given a ghost move rule allowing P Q, we have ∀R ∈ P ρ . R Q ρ . Then we formalise the two of our structural rules below. Theorem 1 (Consequence Rule): Given ρ P P, ρ {P} e {x. Q}, and ∀x. ρ Q Q , we can prove that ρ P e x. Q . Proof: From the first premise of the theorem, we have the following property ∀R ∈ P ρ . R P ρ . From the second premise of the theorem, we have the following property ∀n, R ∈ P ρ . R LSafe n (e, λx. Q ρ ). According to [GHOST-MOVE-3] rule (ghost transitive rule), we have the proof obligation transformed to the form (1) ∀n, R ∈ P ρ . R LSafe n (e, λx. Q ρ ). So far, the precondition strenthning is proven.
In (1), we choose an arbitrarily large n, and unfold LSafe by its definition. For an e that is terminating, the proof obligation can be reduced to ∀n, R ∈ P ρ . R λx. Q ρ . From the third premise, we have ∀x. ∀R ∈ Q ρ . R Q ρ . By putting them together the consequence rule is proven. Proof: From the premise of the theorem, we have the following property: ∀n, R ∈ P ρ . R LSafe n (e, λx. Q ρ ).
With this, we are going to prove the term that ∀n, R ∈ P * R ρ . R LSafe n (e, λx. Q ρ ) * R ρ . According to the definition of separation assertions, the proof obligation can be transformed into: By simplification, we can translate the formula above into the form ∀n, R 1 ∈ P ρ . R 1 LSafe n (e, λx. Q ρ ), which matches the premise.
The frame rules is proven. Finally, we formalise the local soundness of our reasoning system as shown below.

Theorem 3 (Local Soundness): Our verification logic is locally sound. That is, if {P} e {x. Q} is provable, then for all closing ρ we have ρ {P} e {x. Q}.
Proof: The expression e may be a single expression or a series of expressions connected by let-binding. We first prove that given a single expression e, our reasoning rules are locally sound. Then we prove by structural induction that our reasoning system is locally sound for e with arbitrary layers of let-binding.
For the rule [PURE- , where e is a value v (or an arithmetic term that results in v), we are going to prove that ∀n, R ∈ true ρ . R LSafe n (v, λx. x = v ρ ). The case n = 0 holds trivially. In the case that n > 0, as e ∈ Val we have: which can be derived from R ∈ true ρ that is given by the precondition. The proof for [PURE-REDUCTION-1] is finished.
For the rule [PURE- , where e is a relational statement v == v , we are going to prove that for all n and R ∈ true ρ : . According to the event-step rules in our semantics, the expression v == v will be evaluated as 1 if v = v and 0 otherwise. Therefore, in the case v = v we have that the term , which can be further reduced to R ∈ true ρ that is given by the precondition. Similarly, in the case v = v , we have that the term is semantically equivalent to R ∈ 0 = 1 ⇔ false ρ ) which can be derived from R ∈ true ρ that is given by the precondition.

The proof for [PURE-REDUCTION-2] is finished.
For the [FORK] rule, where e = fork e , we are going to prove that ∀n, R ∈ P * Q ρ . R LSafe n ((fork e ), P ρ ), with the premise ∀n, R ∈ Q ρ . R LSafe n (e , true ρ ). The case n = 0 is trivial. In the case n > 0, according to the definition of local safety, the proof obligation R ∈ LSafe n ((fork e ), P ρ ) is equivalent to the R ∈ LSafe n−1 (0, P ρ ) * LSafe n−1 (e , true ρ ), and this formula can be further reduced to the following form according to the definitions of the local safety: R ∈ P ρ * LSafe n−1 (e , true ρ ). According to the definition of separation assertions we have: By putting together with the premise, we have , where e is allocation, initialisation, read, write, CASes, or fence. The event-step used would be e α − → v, where α could be A, R, W, U, or F. We prove the soundness of the triple by unfolding the rely (Fig. 19), guarantee (Fig. 20), and wpe definitions corresponding to action α; then it is trivial to check that We have also discussed that when n = 0, the local safety holds by definition. Therefore the aforementioned rules are locally sound.
For the case e = if v then e 1 else e 2 in the rule of [CONDITIONAL], we prove that: LSafe n ((if v then e 1 else e 2 ), λx. Q ρ ). VOLUME 8, 2020 In the case v = 0, we can add the pure assertion to triple's precondition according to the semantics for assertions, i.e.
∀R. R ∈ P ρ ⇒ R ∈ P ∧ t = 0 ρ = P * v = 0 ρ ; then the triple is validated by the first premise. Similarly, in the case of v = 0, the triple is validated by the second premise. The proof for [REPEAT] is finished.
For the [REPEAT] rule, where e = repeat e end, we prove that ∀n, R ∈ P ρ . R LSafe n ((repeat e end), λx. Q ρ ). In the case that e is evaluated as some non-zero value v, The proof obligation is reduced to ∀n, R ∈ P ρ . R λx. Q ρ , which is validated by the premise. Otherwise according to the event-step semantics for repeat and conditional expressions, the definition of local safety, the rely/guarantee conditions for S action, this proof obligation can be reduced to that for all n > 0 and R ∈ P ρ R LSafe n−1 ((repeat e end), λx. Q ρ ) This transformation can be recursively performed until e is evaluated as non-zero or it reaches LSafe 0 , which holds trivially. The proof for [REPEAT] is finished.
For the [LET-BINDING] rule, where e = (let x = e in e ), we prove that: by using structural induction. We first prove triples with single layer let-binding, that is e is one of the aforementioned expresses and does not contain let-binding, 6  We are going to prove that ρ {P * Q} e [0/x] y. P . From the first premise, we have: ∀n, R ∈ P * Q ρ . R ∈ LSafe n (fork e , x. P ρ ), which can be unfolded to the following from according to the definitions of local safety: ∀n, R ∈ P * Q ρ . R ∈ LSafe n ( P[0/x] ρ ) * LSafe n (e , true).
For other single expressions let us assume that e can be reduced to numerical value v. According to the event-step definition for let-binding and the corresponding rely/guarantee definitions, the proof obligation can be transformed into ∀n, R ∈ P ρ . R LSafe n (e [v/x], λy. R ρ ). At the same time the first premise can be simplified as ∀R ∈ P ρ . R ∈ Q ρ ; together with the second premise, the proof obligation is met.
Then we move on to the inductive case. Let us assume ρ {P} e {x. Q}, where e = (let x = e 1 in e 2 ), and prove ρ {P} let x = e in e {x. Q}. According to the event-step definition for evaluation context, we need to evaluate e first. According to the assumption, e can be savely executed as many steps as possible until it is reduced to a numerical value v. Then we have ∀R ∈ P ρ . R ∈ Q ρ ; together with the second premise ∀n, v, R ∈ Q ρ . R ∈ LSafe n (e , λy. R ρ ), the soundness of the triples: is proven.

B. GLOBAL SAFETY AND THE FINAL SOUNDNESS THEOREM
As our target programs assume a concurrent environment, in addition to their local safety, it is also necessary to demonstrate that given the triple {P}e{x.Q} provable the executions of e are free from data races, memory errors, nor dangling reads under all possible threads interleaving. Therefore, we formulate the global soundness of the proposed program logic similar to its predecessors GPS/GPS+. However the new logic provides full support to C11 release-sequences, which makes it much trickier to prove some critical properties such as data-race-freedom.
Before we can formally define global soundness, we first provide definition for program execution (with an arbitrary number of steps) execs(e) and the semantics for C11 programs e in Fig. 21 on top of the machine-step semantics discussed earlier in §II.
The definitions indicate that the result of a program e is either some value that can be validated by a legal execution or an error state if e allows race conditions or memory errors in its execution.
With these preparations, we define the global soundness as: Intuitively, this definition requires that a provable Hoare triple about a close program e must precisely predict the result of e regarding to its executions under the C11 memory model. To demonstrate the global soundness of our proposed Hoare triples, a property called global safety is defined as below:  We annotate/label the edges in our execution graphs with the computation resources they carry from one node to another and a labelling maps L is used to record that information. The T ins is an instrumented thread pool, in which all threads are depicted in tuples like (a, e, R, ). We have a as a thread's last generated event in the graph, e as the thread's continuation, R as the resource map the thread currently holds (representing the thread's computation state), and the postcondition expected after the execution of the thread is depicted by . The instrumented thread pool T ins can be down casted to a machine thread pool T (recall §II-B) using erase(T ins ), where ∀i. T ins (i) = (a, e, R, ) ⇒ erase(T )(i) = (a, e). The predicate valid signifies that a set of nodes and with their edges properly labelled. By requesting N dom(G.A), the global safety definition requires all nodes in the graph are properly labelled. The compat(G) indicates that for any group of hb-independent edges in the event graph G, the sum of resources they carried is defined. We call a group of edges are hb-independent if for any pair of the edges (a, a ) and (b, b ) we have ¬hb = (a , b). Note that, we only consider the compatibility of the resource maps' local components, which should be sufficient as the local components are the actual resources involved in computation. We also show in our proofs that when the resources under other labels merged to local, the compatibility keeps preserved. The conform states that the mo order for all atomic writes is consistent with the predefined state transitions.
Intuitively, the global safety definition GSafe n (T , G, L) indicates that based on an event graph G and with the resource maps recorded in L, it is safe for any thread from the thread pool T to execute n steps. We aim to demonstrate that this global safe property is to be preserved during the entire executions of legal programs allowed in our logic. To achieve this, we introduce the method we used to update the labelling L for the event graph when a new node (i.e., a new event) is added. The labelling process is then formalised into five lemmas which will demonstrate the restoration of the global safety for the event graph with the new node added. In this section, we focus to convey the high-level ideas about this process leaving the lemmas' proof and the detailed definitions to the appendix.
When adding a node the the event graph, its sb incoming edge is to be labelled first. Suppose that the node to be added is b and a is its sb predecessor in the event graph. Initially, node a's sb outgoing edge points to a sink node, i.e., sb(a, ⊥), and is labelled with the resource map R sb which will be passed to a's sb successor. If a is followed by a fork command and b is the first event in the forked thread, part of the R sb , namely R, is taken and used to label the sb(a, b) edge, while the remaining resource R rem is left in a's sb sink edge for a's local thread. If there is no new thread involved and b is from the same thread as a, the entire R sb should be used to label sb(a, b). Note that we assume there is a S node with all its outgoing edges labelled as empty in the initial event graph; therefore if b is the first event generated in the program, for generality it will take that skip node as its sb predecessor. We illustrate this process in Fig. 22 and formalise it as the following lemma.

Lemma 1 (Step Preparation):
if consistentC11(G) Note that the shorthand notations in(L, a, t) and out(L, a, t) correspondingly stand for the sum of resource maps labelled with a's incoming or outgoing edges of type t.
Next, the new node's rf incoming edge will be labelled. Note that this labelling process is for atomic reading actions and CASes. A non-atomic load simply returns the value recorded in its thread-local resource map. Meanwhile, an atomic load (or a CAS) is able to read from any writer with respect to the C11 memory model consistentC11. Initially, a writing event's rf outgoing resource, which can be referred to as r rf , is associated to its rf sink edge. When the new node reads from that write, their rf edge is labelled following four different approaches according to the read event's type (atomic read or CAS) and the memory order used (relaxed or acquire). If the new event is a relaxed read, its rf incoming edge is labelled with a resource map EMP[A → |r rf |], indicating that it can retrieve some knowledge from the write but the knowledge is ''waiting-to-be-acquired''. If the new event is an acquire read, the retrieved knowledge is directly put under the local label: EMP[L → |r rf |]. The labelling for the CASes is similar, but for CASes the information can be retrieved is not limited to knowledge. Note that, we always left |r rf | in the writer's rf sink edge for other readers to read. This process is illustrated in Fig. 23. By labelling the new rf edge in this way, the following lemma can be proved. When a piece of resource R is packed into an escrow by event a, R is removed from a's working resource map and put into a's esc sink edge for safe keeping. Another event b owning the resource R that is required to open the escrow may retrieve R through a new escrow edge created associating a and itself. Then R is dumped to b's escrow sink edge. This process (and other local ghost moves) is depicted in Fig. 24 and is formalised in the following lemma. ∧R after R ⊕ out(L, a, esc) ⊕ out(L, a, cond) The following lemma demonstrates that by labelling the graph in the way we have described, the new node's all incoming resource map will satisfy its wpe requirements. Finally, the new node's outgoing edges (sb and rf) will be labelled in guarantee step, using the corresponding resource  map and resource (R sb , r rf ) derived from the action's guarantee definition. These resources are initially assigned to the corresponding sink edges of the new node, until the node's future sb and rf successors are added to the graph and take the resources for the labelling of the corresponding edges. Note that, as annotation for read-from sink edge, r rf , is a resource instead of resource map, we require it to be compatible with other resource maps' local component at the compat checking.  In what follows we formulate the Theorem Instrumented Execution. Intuitively, this theorem states that is a program is globally safe to be executed for n + 1 steps from the current machine configuration, an arbitrarily scheduled move will lead to a new machine configuration, based on which the rest of the program will be global-safely for another n steps. Proof: Starting from GSafe n+1 (T ins , G, L), a machine step transforms the graph into G with a new event b and the thread pool into T , leaving n more locally safe steps for the active thread.
By applying Lemma 1, we have that there exists a labelling L 1 derived from the original labelling L with in(L 1 , b, sb) = R ∧ L 1 (sb, a, ⊥) = R rem , which ensures: By applying Lemma 2, we have that there exists L 2 updated from L 1 with the new node's rfincoming label and maintains the valid set.
By applying Lemma 3, we have that there exists L 3 updated from L 2 with escrow incoming and outgoing edges taken under consideration. With the new labelling, the compat and conform properties are recovered.
By applying Lemma 4, we have that with L 3 , the sum of new event's incoming resource maps satisfies its wpe definitions.
By applying Lemma 5, we have that there is a labelling L with the new event's outgoing edges updated. The valid, compat, and conform along with other properties are preserved for the new graph and labelling. Therefore, the new graph is GSafe n (T ins , G , L ). VOLUME 8, 2020 Now we present one more lemma, whose proof is left in the appendix, to demonstrate that all possible executions are free from data-race, memory errors, and uninitialised reads.
Ultimately we give the global soundness Theorem Proof: From {true} e {x.P}, we can derive that from true the program e is locally safe for an arbitrarily large number of steps. We assume e terminates in n steps. That is, according to the step-level semantics e will be reduced to some pure value, which can be referred to as V , after n steps. We assert LSafe n+1 (e, x.P ), based on which we construct: By repeatedly applying the Theorem Instrumented Execution for n times, we can derive: From this condition we can imply that R P[V /x] and thus we can conclude that P[V /x] = ∅.

VIII. RELATED WORK
Our work is closely related to the GPS logic [6] and the RSL logic [5]. RSL can be used to reason about release-acquire synchronisations in the style of Concurrent Separation Logic (CSL) [16]. Following up work, FSL and FSL++ [8], [11], provide support to C11 fences and part of the release-sequence feature. GPS framework integrates ghost states, protocols and separation logic, which are the most handy tools for reasoning about concurrent program advocated by the state-of-the-art literature [15], [17]- [26]. Tassarotti et al. [7] demonstrated the power of GPS by apply it to real world Linux synchronisations algorithms. Following up work GPS+ [9], [10] provides support to C11 fences and based on which our work provides the full support to C11 release-sequences and fractional permissions.
There are some recent works aiming at providing automations in the verification of C11 weak memory programs. With the Iris [26] semantics supported, [30] provides the first mechanical verification tool for a subset of C11 programs with the GPS and RSL style reasoning. [31] encodes the line of RSL works [5], [8], [11] into the Viper verification infrastructure [32]. Similar automatic implementations would be one of our future interests.
Semantics-wise, we follow the axioms-based approach like that introduced by [4]. Similar axioms-based approach is also used for the Java memory model [33]. For various hardware memory models, operational semantics are also used [34]- [36]. Some recent works about the ''promising'' semantics [36], [37] propose a relatively more economical way to eliminate the ''thin-air-read'' problem without sacrificing too many possible optimisations. Its usefulness has been demonstrated in the formalisation of the ARMv8 memory model [38]. It is yet to be proved how handy it could be in supporting weak memory program logics.

IX. CONCLUSION
To the best of our knowledge, our proposed program logic GPS++ is the first one that provides the support to the reasoning about fully featured C11 release-sequences. Built on top of the GPS+ logic, our work is extended with the powerful restricted shareable assertions P s , an enhanced per-location protocol model, and a set of new verification rules. In addition, GPS++ also has the support to fractional permission, which makes it more practical than its predecessors, as now the reasoning about concurrent non-atomic reads is allowed.
In our future work, we aim to bring more memory orders, e.g., the consume read, into our reasoning framework. We also aim to apply GPS++ to more real-world C11 programs and develop reasoning aids with certain degrees of atomisation.

APPENDIX MORE DEFINITIONS AND PROOF OF LEMMAS
In this section we present the less interesting yet indispensable definitions used in our reasoning system and semantic framework, and the proof the lemmas and corollaries we have discussed in the main text.
Our reasoning system is featured with new types of assertions and the corresponding inference rules to reason about them. We first present the semantics for our assertions; and then prove the soundness of our inference rules with the form P ⇒ Q.
[σ ] σ ∈ R(L).  (13), the term can be transformed into: which implies the right hand side term. Similarly, we can do it from right to left. The proof of this rule is finished.
For the [KNOWLEDGE-MANIPULATION-1] rule: P ⇒ P, according to definition (14) the semantic for its left hand side is R ∈ P |EMP[L → R(L)]| ∈ P ρ . As |EMP[L → R(L)]| ≤ R, R is also in P ρ . The proof of this rule is finished.
For [KNOWLEDGE-MANIPULATION-3]: P * Q ⇔ P ∧ Q, as P is knowledge, the semantic definition (8) P ρ ∩ Q ρ is equivalent to (13) P ρ * Q ρ in terms of evaluation results. Therefore, the rule is proven.
For [KNOWLEDGE-MANIPULATION-4. . . 7], they are semantically sound as according to the definition of stripping operation and their corresponding semantic definitions ((7), (5), (1), and (6)) the resource representing these assertions does not change after stripping. Therefore they are able to be transformed into knowledge form.
For [SEPARATION-1]: γ : t µ * γ : t µ ⇔ γ : t · µ t µ , starting from the rule's left hand side, we have: which is equivalent to the semantics of the rule's right hand side. The rule is proven. For the [SEPARATION-2] rule: : s τ * : s τ ⇒ τ = τ ∧ (s τ s ∨ s τ s), starting from the rule's left hand side, we have: Given R 1 #R 2 , according to the definition of protocol compositions, the right hand side is implied. The rule is proven. For [ASSERTION-PROPERTY-1. . . 7], we prove that special assertions can not be nested. According to the definition (14)(15)(16)(17), the nesting shown on the left hand side results in an empty resource map that is used to be checked with the original assertion P, which implies false unless P is emp. The proof is finished.
A ghost move is a transition that only changes auxiliary/logical computation states. This is ensured by our resource-level ghost moves. We first present our resource-level ghost moves below:

Corollary 2 (Soundness of Ghost Moves):
Our ghost move rules are semantically sound. That is, given a ghost move rule allowing P Q, we have ∀R ∈ P ρ . R Q ρ . Proof: We prove the ghost move rules one by one. For the [GHOST-MOVE-1] rule, we are going to prove that∀R ∈ P ρ . R Q ρ , with the premise that is given as ∀R. R ∩ P ρ ⊆ Q ρ . The premise can be simplified as P ρ ⊆ Q ρ . Therefore, we have ∀R ∈ P ρ . R ∈ Q ρ . By using the resource level ghost move (1), we have [GHOST-MOVE-1] is proven. For the [GHOST-MOVE-2] rule, we are going to prove that ∀R ∈ P * R ρ . R Q * R ρ . According to the definition of separation assertions, it can be transformed to: According to the premise, we have ∀R ∈ P ρ . R Q ρ . We can check that the proof obligation is valid for all possible ghost moves allowed by the resource-level ghost move rules. [GHOST-MOVE-2] is proven.
For the [GHOST-MOVE-3] rule, initially we have the following property: ∀R ∈ P ρ . R Q ρ ∧ ∀R ∈ Q ρ . R R ρ , and we are going to prove that ∀R ∈ P ρ . R R ρ . From the first premise ∀R ∈ P ρ can be transformed into some resource in Q ρ for all possible ghost moves. Together with the second premise, the rule is proven.
The [GHOST-MOVE-3] and [UNSHARE-R] can be proved by moving the resource under the shareable labels to the resource maps' local component, which is allowed by the resource level ghost move (7).
For the [GHOST-MOVE-4] rule, we are going to prove that ∀R ∈ true ρ . R ∃γ . γ : t 1 µ ρ , which can be done by applying the resource level ghost move (3). VOLUME 8, 2020 The [GHOST-MOVE-5] is a corollary of the resource level ghost move (4), while the [GHOST-MOVE-6] is a corollary of the resource level ghost move (5), and [GHOST-MOVE-7] is a corollary of the resource level ghost move (6). Now we present the proofs of the labelling lemmas we have discussed for our reasoning system's global safety with the following definitions (which has been informally discussed in the main text):  sb, a , b) = EMP ∧out(L , b, all) = EMP ∧∀a = a. L (sb, a , ⊥) = L(sb, a , ⊥) Proof: Firstly, we prove the compat property. Notice that for all edges in that are hb-independent with the edge sb(a, b), they are hb-independent with the sb(a, ⊥) edge as well. Suppose the sum of the resources carried under their local label r is incompatible with L(sb, a, b)(L), i.e., ¬r#L(sb, a, b)(L). According our labeling rule L(sb, a, b)(L) ≤ L(sb, a, ⊥)(L). That is there exists some r that makes L(sb, a, ⊥)(L) = L(sb, a, b)(L) ⊕ r . Therefore we can deduce the following property ¬r#L(sb, a, ⊥)(L) as r ⊕ L(sb, a, ⊥)(L) = r ⊕ L(sb, a, b)(L) ⊕ r which has undefined result. However ¬r#L(sb, a, ⊥)(L) contradicts with the premise where the compat(G, L) property holds. Therefore, the sum of the resources carried by all the edges hb-independent with sb(a, b) is compitable with its resource, and we can derive that compat(G , L ) To prove the conform property, notice that the atomic locations are unchanged in this step's labelling process. Therefore conform(G , L , dom(G .A)) is essentially equivalent to conform(G , L , dom(G .A)). To prove the valid property and the validity of the updated labelling, we unfold the corresponding definitions and check the requirements with our labelling results. Proof: We first focus on the compat property. For non-update reading actions, we argue that only knowledge is taken into the new node and knowledge is always compatible with the environment. For an relaxed atomic update, the resource taken in from its rf edge is left to be acquired, therefore the local resources are still compatible. For an acquire atomic update, which can take non-duplicable resource to its local resource, we notice that there must be a nearest release action b that made the resource shareable. Therefore we have b happens before a, which does not break the compat property.
We assert that conform(G , L , dom(G .A)) is essentially equivalent to conform(G , L , dom(G .A)) as there is no changes to atomic locations in this labelling step. To prove the valid property and the validity of the updated labelling, we unfold the corresponding definitions and check the requirements with our labelling results. Proof: To prove the compat property, firstly we assert that the escrowed resource a retrieved must have been put under escrow by an event that happens before a. This is because our labelling process ensures that the escrowed resource is initially attached to the creator's escrow sink edge, and can only appear in a node's local component if that node is in a chain of (sb ∪ sw) + following the creator. Then we assert that the compat property holds for the updated graph following the same argument as that used in the compat proof for the Lemma Rely Step. We also assert that the conform, valid properties and the new labelling are valid for the same reasons discussed in the proof for the previous lemma. Proof: For the new node a's sb outgoing edge, we first proved the proof for its compat property. Suppose there is an edge ξ that is hb-independent with the new node a's sboutgoing edge sb(a, ⊥) and the resource map it carries is incompatible with L(sb, a, ⊥). Supposing a is not an acquire action, i.e. the incompatibility is not caused by moving resources from the current resource map's A component to its local component, we use case analysis to demonstrate that the action's guarantee condition would not introduce new incompatibility; however if the incompatibility is not newly introduced, it would appear in one of the incoming edges, which violates the compat property in the premise. If a is an acquire action, which could move resources from the A component to L, we argue incompatibility can not be introduced in this process by contradiction. Assuming the incompatible resource originally in A is r, there must be another node, say b that moves r from L to a shareable component and thereafter r could be loaded to A in a's thread, according to our labeling method. According to the C11 memory model, we derive that b happens before a. If there exists an edge ξ that is hb-independent with L (sb, a, ⊥) and carries the incompatible resource r, it also hb-independent with one of a's incoming edges that carries r (the case that r is created by a is trivial), which violates the compat(G, L). With the same argument used for the release fence case, we argue that the compat property holds for a's rf outgoing edge.
For the new graph's conform property, we prove by exhaustion on all possible type of actions, and check unfolded conform definitions against the guarantee conditions for the corresponding type of actions. Same to that for previous lemmas the proof for the valid property and the validity of the updated labelling, can be demonstrated by unfolding the corresponding definitions and check the requirements with our labelling results.
Lemma 6 (Error Free): If GSafe n (T ins , G, L) then we have ¬dataRace(G),¬memErr(G), and all reads are initialised. Proof: We first prove that an event graph supporting safe executions is free from race conditions using proof by contradiction. Suppose event a and b in G cause a data race, by the definition of race condition we can deduce that ¬hb(a, b) ∧ ¬hb(b, a). Also, we can derive that there is a location that appears in both a and b's incoming edges that holds some non-trivial (not ⊥) non-atomic values. However, given that a's incoming edges are hb-independent with that of b's the appearance of the non-atomic resource about location in both groups violates the compatproperty in the global safety definitions. Therefore, there are no two events in G that could raise a data race.
To prove the graph is free from memory errors, i.e., there is no memory access to unallocated memory locations, first notice that ensured by our instrumented semantics to manipulate a location , an event b must have the information about in one of its incoming edge's local component. Then we define a recursive search procedure to find the action that allocates and demonstrate that the memory accesses to are error free.
Firstly, we search backwards following the sb + edges in the graph starting from b, until we reach an event a where the information about is not in one of its incoming edge's local component. In the case that a is an allocation action and it allocates , the search ends. In the case that a is an acquire fence and it moves from the waiting-to-be-acquired component in one of its incoming edge to the local component in its outgoing resource maps, we assert that there exists an read or update event a 0 with relaxed memory order prior to a in the sb + relation according to our labelling process, and the information about appears in a 0 's read-from incoming edge under the waiting-to-be-acquired label. Then we recursively perform this search procedure starting with the write event that a 0 reads from until we find the right allocation action. If it is not the cases aforementioned, we check if a's immediate sbsuccessor a is a read or update event with acquire memory order. If so, we recursively perform this search procedure starting with the write event that a reads from. We assert these are all the cases needed to be considered as any other case violates the global safety definitions according to our labelling process. Therefore, a globally safe event graph is error free.