HAL Id: hal-01905136
https://hal.archives-ouvertes.fr/hal-01905136
Submitted on 13 Nov 2018
HAL is a multi-disciplinary open access
archive for the deposit and dissemination of
sci-entific research documents, whether they are
pub-lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.
L’archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d’enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.
Contents lists available atScienceDirect
Science
of
Computer
Programming
www.elsevier.com/locate/scico
Shared
contract-obedient
channels
Étienne Lozes
a,∗
,
Jules Villard
b aUniversitätKassel,GermanybUniversityCollegeLondon,UK
a
r
t
i
c
l
e
i
n
f
o
a
b
s
t
r
a
c
t
Articlehistory:
Received15January2013
Receivedinrevisedform24May2014 Accepted22September2014 Availableonline2October2014 Keywords:
Programverification Messagepassing Linearchannels Separationlogic
Recent advances in the formal verification of message-passing programs are based on provingthat programs correctlyimplement agiven protocol.Many existing verification techniquesformessage-passingprograms assume thatatmostone thread mayattempt tosendorreceiveonachannelendpointatanygivenpointintime,andexpresslyforbid endpointsharing.Approachesthatdoallowsuchsharingoftendonotprovethatchannels obeytheirprotocols.Inthispaper,weidentifytwoprinciplesthatcanguaranteeobedience toacommunicationprotocoleveninthepresenceofendpointsharing.Firstly,threadsmay concurrentlyuseanendpointinanywaythatdoesnotadvancethestateoftheprotocol. Secondly,threadsmaycompeteforreceivingonanendpointprovidedthatthesuccessful reception of the message grants them ownership of that endpoint retrospectively. We developaprogramlogicbasedonseparationlogicthatunifiestheseprinciplesandallows fine-grainedreasoningaboutendpoint-sharingprograms.Wedemonstrateitsapplicability on a number of examples. The program logic is shown sound against an operational semanticsofprograms,andprovedprogramsareguaranteedtofollowthegivenprotocols andtobefreeofdataraces,memoryleaks,andcommunicationerrors.
©2014PublishedbyElsevierB.V.
0. Introduction
Message-passingidiomsappeareverywhereintoday’ssoftware:fromtheMessagePassingInterface(MPI)usedin high-performancecomputing,totheinter-processcommunicationlayerinAndroidapps,andtoWebservices.Asforotherforms of concurrency, naively checkingthe correctness of a message-passing systemis severely impaired by the combinatorial explosion ofthe numberofpossibleinteractions betweenthecomponents ofthesystem. One waytotacklethisissueis todevelopformalverificationtechniquesformessage-passingprograms,suchthatreasoningaboutasystemistantamount to reasoningabouteach componentin isolation.Apromising avenueinthisrespect istoseparate thestudyofprograms from thestudyofthe protocolsthey are meant toimplement, i.e.prove that aprogram correctlyimplements aprotocol on theonehand,andreasonaboutthat protocolindependentlyofitsimplementationon theother hand.In thiscontext, protocols act bothasspecificationsof whata programis allowed todoandasdescriptions ofthe actionsthat programs must expectfromtheenvironment.Twomainapproachescoexist fordescribingsuch protocols:sessiontypesontheone hand[30],usedtopoliceinteractionsinprogramsexpressedeitherinthe
π
-calculus[20]orinamessage-passingvariantof Java[21],andchannelcontracts ontheotherhand[7],usedforinstancetodescribetheprotocolsintheSingprogramming language [13]developedfortheSingularityoperatingsystem[22].High-levelprotocoldescriptionssuchastheseallowthe program verificationefforttobe splitbetweencheckingpropertiesattheleveloftheprotocolitselfontheone hand,and checkingobedienceofeachthreadoftheprogramtoitspartintheprotocolontheotherhand. Ifallthreadsplaytheirparts
*
Correspondingauthor.http://dx.doi.org/10.1016/j.scico.2014.09.008 0167-6423/©2014PublishedbyElsevierB.V.
leakage.Theprogramlogicallowstwoformsofsharingonchannelendpoints.
Thefirstformofsharingallowsthreadstouseendpointsconcurrentlyaslongastheydonotadvancetheprotocolstate. Thisensuresthataconsistentviewofthecontractstateismaintainedamongstallsharersofagivenendpoint.Thisformof sharingisusefulwhensharedendpointsexchangeonlyonekindofmessages,andunidirectionally, aslong asthesharing subsides. Thisis thecase forinstancewhen one or severalproducers sendthe same kindofmessage repeatedly over a channel,tobereceivedbyoneorseveralconsumers.
Thesecondformofsharingallowsseveralthreadstocompeteforreceptionofamessageonasharedendpoint.Exclusive access to this very endpoint is granted to the winner, who can then use it to realise the rest of the communication. Meanwhile, the other threads are kept waiting forthe initial message until the protocolcomes back to the initial state and theownership of the endpointis released by the winning thread. This formof sharing is typical of two situations occurringinexisting message-passingapplications.First,itcan occur whenseveralworkerthreads orprocesseslisten for thesamekindofevent,eachindividualeventbeingpickedupbyoneworkeronly.Thisisthecaseforinstanceforimplicit intents intheAndroidframework[1],wherecomponentscanregisterasabletoprovidecertainservices,latertobecalledby applicationsinneedoftheseservices.Forinstance,webbrowsersregisterasbeingabletoprocessintentsofthe“browsable” category.Clickingonaweblinkinanemailemitsan implicitintentofthatcategory,whichcanbepickedup bytheweb browser.In thecaseofAndroid,such sharingresultsin simpleprotocols:eithera single intentissent asintheexample above,ortheintentawaits aresponse.Weshowthat,infact,anyprotocolcanbe realisedonthesharedendpointonceit hasbeenacquiredinsuchaway.Surprisingly,sharinginthiswaydoesnotcontradictlinearchannelusage:eachendpoint is effectively used by at mostone thread ata time even though several threads compete forthe initial message.More generally,thisworkshowshowlinearitycanberelaxedtogetbothexpressiveprotocolsandsharing.Indoingso,weopen thewayforbringingmoreformsofsharingtonewmessage-passingrun-timelibrariesbasedonformalmethodsingeneral, suchassessiontypesorSing
,whicharecurrentlymorestrictintheirenforcingoflinearity.
This work builds on a previous approach based on a marriage of separation logic andchannel contracts[33],which forbadeanyactivesharingofendpoints.Asinpreviouswork [26],weconsiderasimpleimperativelanguage thatfeatures primitivesfordynamicallycreatinganddestroyingbi-directional,asynchronouschannels,eachmadeoftwoendpoints,and forsending andreceivingmessages onindividual endpoints.Eachmessageis composedofa user-defined tag(which can beusedtodescribethekindofpayloadsupposedtobetransferred,asinSing
orMPI)andzeroormorevalues.Crucially, values may be references to other endpoints, and thus sending a message may create sharing of resources and foster concurrency errors.In theabsence ofendpointsharing, previous workwas able toprove obedience to channelcontracts andabsenceofdataraces,andfromthattodeducetheabsenceofmessagereceptionerrorsandoforphanmessages.Akey ingredient oftheprogram logic,whichwe haveretained,is tologically reflectthetransfer ofa messagethat isattached toaresourcebythetransferoftheownershipofthat resource(the message’sfootprint inmemory)totherecipientofthe message.Contrarilytosimilartransferdisciplinessuch assessiontypes,footprintsneednotbesyntacticallydeterminedby thevaluesent:sendingtheaddressofanendpointoverachanneldoesnotequatesendingtheownershipofthatendpoint. Rather,anyfootprintmaybeattachedtothemessage.Thismakesourapproachmorepowerfulintermsofwhichprograms canbeprovedcorrect,asitallowsmorecomplexownershiptransferdisciplines.
Thecontributionsofthepresentpaperareasfollows:
•
Weidentifytwopatternsforsharingendpointswhileretainingtheabilitytodescribetheir interactionsviameaningful protocols.•
Weintroduceanewprogramlogicabletoproveprogramsthatabidebythesepatterns.Thepresentationoftheprogram logicunifiesbothsharingparadigms.•
We justify the soundness of our program logic by proving it sound with respect to an operational semantics. Our soundnessproofisable toexpressthefact thatproved programsobey their contractsandarefree ofcommunication errors,bylinkingthesemanticsofprogramstothatofthechannelcontractstheyimplement.Outline In the first section we define our programming language featuring bi-directional, dynamically allocated, asyn-chronous channels, andintroducethe syntaxof contracts.We illustratecontract obedience inthe presenceofsharing on examples.Inthesecond section,wegivean overviewofseparationlogicandcontractsasusedinourownprogramlogic, introducedinthethirdsection.Wesketchtheverificationofafewtellingexamplesinafourthsection.Inthefifthsection, we provide an operational semantics for channel contracts and forour programming language. In the sixth section, we establishthesoundnessofourprogramlogicwithrespecttothissemantics.Weconcludewithrelatedworks.
1. Programminglanguage
1.1. Syntax
We consider an idealised imperative programming language with support for message-passing concurrency. Threads shareaglobalmemoryandmayallocate,deallocate,andmanipulateheapobjectsinthissharedmemory.Forthepurpose ofthiswork,itisenoughtolimitheapobjectstochannels.Communicationchannelsareasynchronous,bi-directional,and each madeoftwo channelendpoints (or simplyendpoints):each endpointcanbe used forsendingto andreceiving from the other endpoint.A channelcanhencebe implementedasa pairofFIFO buffersallocatedontheheap: each endpoint receivesmessagesbydequeuingthemfromoneofthebuffers,andsendsmessagesbyenqueuingthemintotheother.This communicationmodelisclosetothatofSing
[13].Twoendpointsofthesamechannelarecalledpeers.
Weassumeinfinitesets
Var
= {e,
f
,
x
,
y
,
. . .
}
,Σ
= {
m,
. . .
}
,andVal
= {
v,
. . .
}
ofrespectivelyvariables,message identi-fiers(ortags),andvalues.Thegrammarofexpressions,booleanexpressions,atomiccommandsandprogramsisasfollows:E
::= x |
v|
E1+
E2| · · ·
expressionsB
::=
E=
E|
Band
B| not
B boolean expressionsc
::= skip | assume(
B)
| x = E
atomic commands| (e, f) = open() | close(e, f) | send(m, e,
E1, . . . ,
En)
| (x
1, . . . , x
n) = receive(m, e)
cases
::= | (x
1, . . . , x
n) = receive(m, e)
:
p casesp
::=
c|
p;
p|
p p|
p+
p|
p∗| local x in
p| switch {
cases}
programsThe
skip
commanddoesnothing;assume(
B)
doesnothingifB holdsandblocksotherwise(thusskip
isequivalent toassume(
true));
x
=
E evaluatestheexpressionE andstorestheresultinthevariablex;
(e,f) = open()
createsa newchannelandallocatesbothofitsassociatedendpointse
andf
intheheapwithemptybuffers;close(e,f)
disposes the endpointsataddressese
andf;
send(m,e,
E1,
. . . ,
En)
sends amessageover theendpointe
toits peerendpoint;the messagehasa tag
m,
andatuple E1,
. . . ,
En ofn message values(n≥
0);(x
1,
. . .,x
n)
=
receive(m,e)
receivesthefirstavailable messageonendpoint
e,
whichmusthavetagm
andarityn,andsetsthevariablesx
1,. . .
,x
n accordingto thepayload ofthemessage.Ifnomessageisavailable, orifthefirstavailable messagehasa tagdifferentthan
m,
the commandblocks;thesequentialcompositionofcommandsiswritten p1; p2;p1p2istheparallelcomposition;p1+
p2is theinternalchoice; p∗ istheKleeneiteration;local x in
pisthecreationofalocalvariable.Theswitch
constructis usedtowaitforseveralmessagesonseveralendpointsatonce.Theconstructselectsabranchcorrespondingtoanavailable message ifpossible. Ifthe message buffersofall the endpoints in theswitch
construct are empty, then it blocks.Ifa messageisavailableononeoftheseendpoints,butwithatagthathasnocorrespondingreceive
branch,thenittriggers anerror.Letusillustratethebehaviourofswitch
withanexample.Example1.Considerthefollowingcodesnippet:
switch {
x = receive(bool, e): {
p1}
x = receive(int, e): {
p2}
(y,z) = receive(pair, d): {
p3} }
Thefollowingscenariosarepossibleresultsofexecutingthecodeabove:
•
Nomessageeverarrivesone,
andthisthreadisstuck.•
Themessage(int,
n)
isnextinlineatendpointe:
themessageisdequeued,x
issetton,andp2 isexecuted.•
Themessages(int,
n)
and(pair,
v1,
v2)
areavailableonrespectivelye
andd:
eitherofthemcanbepickedupand,accordingly,eitherp2 orp3 isrunnext(withrespectively
x
=
n ory
=
v1 andz
=
v2).•
Amessagethatistaggedwithneitherbool
norint
isavailableone,
forinstanceamessage(float,
4.
52)
:anerror israised.One can define the usual
if
andwhile
constructs ofprogramminglanguages usingassume
andnon-deterministic choiceinastandardway.Thus,wewriteif
(
B)
p1else
p2 for}
}
}
Inmostofourexamplesincludingthisone,we useprocedures forbetter readabilityofthecode.Procedurescould be added to the language andthe program logic using standard techniques. Moreover, ourexamples will not use recursive procedures,soprocedurescanalwaysbeinlined.
1.2. Contracts
In this section, we introduce contracts. Contracts are used to describe the protocol followed by each communication channel inprograms. Acontract isafinite automatonwhosetransitionsare labelledeitherwithsend
!
m orwithreceive ?m actions.Thepathsintheautomatondescribetheadmissiblesequencesofemissionsandreceptions(lookingonlyatthe tagm ofeach message)onachannel. Thefinalstatesrepresentpointsintheprotocolwhenthechannelisallowed tobe closed.Weassumeaninfiniteset
Control
ofcontrolstates.RecallthatΣ
isthesetofmessageidentifiers.Definition3(Contracts). Acontract isa tupleC
= (
Q,
δ,
q0,
F)
such that Q⊆ Control
isa finite set of control states,δ
:
Q× {!,
?}
× Σ
Q apartialtransitionfunction,1q0
∈
Q aninitialstate,andF⊆
Q asetoffinalstates.Alabel
λ
∈ {!,
?}
× Σ
inthecontract automatoniswritten eitherasasendlabel!
m orasareceivelabel?m.Givena contractC= (
Q,
Σ,
δ,
q0,
F)
,wewriteinit(
C)
forq0,finals(
C)
forF ,andqλ
→
q∈
C ifδ(
q,
λ)
isdefinedandequaltoq. In this work, we consider bi-partite channels made of two endpoints that follow dual contracts. We describe their interactionasasinglecontractC writtenfromthepointofviewofthefirstendpoint;theotherendpointimplicitlyfollows thedualcontractC ,¯
wheresends!
andreceives? havebeenswapped.Definition4(Dualofacontract).The dual
λ
ofa labelλ
is definedasthe involution!
m=
?m and?m= !
m. The dualofa contract C= (
Q,
Σ,
δ,
q0,
F)
isthecontract C¯
= (
Q,
Σ,
¯δ,
q0,
F)
such that¯δ(
q,
λ)
isdefinedwhenδ(
q,
¯λ)
is,and¯δ(
q,
λ)
=
δ(
q,
¯λ).
Acontract andits dualdescribe thebehaviour ofa channelin aprogram,abstracting away fromtheexactvalues ex-changed to focussolely on thetags of messages. Weare interested inestablishing the absenceof two kindsof errorin the interaction between a contract and its dual: (1) unspecifiedreceptions,where a message carrying an unexpected tag is received,and(2) orphanmessages, i.e.messages that havebeen sentbut not receivedat thetime a channel is closed. Contracts C thatexhibitneitheroftheseerrorsinallthepossibleexecutionsofC togetherwithitsdualC are
¯
calledvalid.WedelaytheformaldefinitionofthesemanticsofcontractsandthusthedefinitionofvalidityuntilSection5.1.Fornow, itsufficestoknowthatsufficient,syntacticconditionsexistthat ensurethatacontract isvalid[18,25].Letusrecallthem here.
Definition5(Well-formedcontracts). Acontract ispolarised ifthereare noq
,
q1,
q2,
m1,
m2 such thatq! m1→
q1 andq ?m2→
q2. A cycleisasequenceq0 λ1→
q1 λ2→ . . .
λk→
qksuchthatk≥
1 andqk=
q0.Astateissynchronising ifallcyclesgoingthroughthis 1 Wecouldallownon-deterministicautomataaswell,i.e.allowδtobeofthetype Q× {!,?}× Σ P(Q),atthecostofcomplicatingtheformalism. Moreover,determinismcanalwaysbeassumedbystandardautomatondeterminisation.state containatleastasendandareceivetransition.Acontractthatispolarisedandwhosefinal statesare synchronising iswell-formed.
Allthecontractswewilluseasprogramspecificationinourexamplesarewell-formed. 1.3. Contract-obedientcommunicationsandsharing
Inthissection, weinformallyintroduce thenotionofcontractobedience viaseveralexamples(withandwithout end-pointsharing)andtheirassociatedcontracts.
Contractsnaturallydescribetheallowedsequencesofsendandreceiveactionsonagivenchannel,abstractingawayfrom the actualvaluescarriedbymessagestoretain onlytags.Upon creation,endpointsareassignedacontractintheformof an annotationtothe
open()
command.Inourprogramlogic,introducedformally inSection3,the(e,f)
=
open(
C)
instruction createsendpoints pointedtobye
andf,
whichfollowcontracts C and C respectively,¯
andstartinthe initial state q0 ofC .Toasend(m,e,v)
instructionmustcorresponda!
m transitioninthecontract,andsimilarlyforreceive
instructions. Aswitch/receive
blockmustaccountforallpossibletagsthatmaybereceivedinthecurrentstateofthe contract (foreachreceiving endpoint).Theclose(e,f)
instructionmustonlybecalledwhenbothendpointsare inthe same final state of the contract. Followingsuch a discipline ensures the absence ofcommunications errors inprograms, providedthatcontractsarewell-formed.Forinstance,onecaneasilycheckthattheprograminExample 2obeysthefollowingtwo-statecontract:
C2: 1 2
!int
!bool
Now,consider C2: 1!int
2 C2: 1 2!int
!bool
!float
The
put
thread(andthusthewholeprogram)violatescontract C2 sinceput
mayalsosendabool
messagewhichisnot avalidtransitioninC2.Conversely,theget
threadviolatescontractC2 sinceitsswitch/receive
blockisnotreadyforfloat
messagesthatC2prescribes.Ontheotherhand,put
obeysC2,sincenotallsendingtransitionsofthecontracthave to berealisedbytheprogram,andget
obeysC2,sincebeingreadyformoretagsthannecessarydoesnotimpactsafety. Thereisthusanasymmetrictreatmentofwhatitmeanstoobeythecontractwhensendingandwhenreceiving.Example6. The following program implements a classic producer/consumer scenario: the
main()
function allocates a channel andspawns two threads,producer
andconsumer.
The former sends objects tothe latter forsome time viaobject-tagged
messages.Tosignify theendof thecommunication, afin-tagged
messageis sent.Upon receivingfin,
consumer
closesthechannel.main() {
(e,f) = open();
producer() || consumer();
}
producer() {
while (*) {
... /* produce an object x */
send(object,e,x);
}
send(fin,e);
}
consumer() {
done = 0;
while(not done) {
switch {
y = receive(object, f):
{ ... /* do something with y */ }
receive(fin, f): { done = 1; }
}
}
close(e,f);
}
Thisprogramimplementsthefollowingcontract:
C6: 1 2
!object
producer ( ) | | . . . | | producer ( ) ; send ( f i n , e ) ; } } } c l o s e ( e , f ) ; }
ThisprogramalsoobeysthecontractC6,essentiallythankstotheself-loopatstate1,whichallowsthemultiplesendersto usetheendpointwithoutinvalidatingeachother’sviewoftheendpoint’scontractstate.
Example8.The followingexampleshowcases anotherscenariowhere endpointsharingarisesnaturally. Considera seller andseveralbuyersrunninginparallel.Theselleradvertisesitsproductusingendpoint
e
viaaproduct_descr
message to several buyers. The buyers concurrently accessthe peerf
ofe
andmake offers. The first buyer to make a suitable offerwins the auction.Tokeep things simple,wedo notinclude amechanismforclosingthe channel attheendofthe interactionbetweenthesellerandthebuyers.Thus,thechannelisneverclosed.seller(e) {
local price = 0;
while (!good(price)) {
send(product_descr,e);
price = receive(offer,e);
}
}
buyer(f) {
local x;
receive(product_descr,f);
x = think_about_it();
send(offer,f,x);
}
main {
(e,f) = open();
seller(e) ||
buyer(f) ||
... ||
buyer(f);
}
Anaturalcontractforthecommunicationchannel
(e,
f
)
isC8
=
1 2!product_descr
?offerRemarkably, noneof the buyers makes any assumption on the contract state of
f
when they simultaneously try to receiveproduct_desc.
Inparticular, they attempttoreceivea product descriptiononf
without theknowledge thatf
is in a contract state that ensures that such a message will be available next. The crucial argument that validates this program is that the received message justifies inhindsight the buyerwaiting for aproduct_descr
message. In other words,the knowledge ofthecontract state off
isestablished afterreceiving onf.
The threadthat successfullyreceives the endpointhasto followthrough withtherestof that endpoint’sprotocol. In thisexample,itwill sendback an offer, therebycompletingtheloopintheprotocol.Thisformofsharingdifferssignificantlyfromthatofthepreviousexamplein theargumentsthatjustifycontractobedience.1.4. Programsafety
Our program logic will establish the absence of the following kinds of run-time errors in programs, which we will formaliseinSection6.2:
Ownership errors Theyoccurwhenathreadtriestodeallocateanendpointatthesametimeanotherthreaddoesanyother operationonthissameendpoint(asend,areceive,oradeallocation).
Memory leaks They occur whenthe memory state becomes such that no continuation of the program candeallocate all resources,inourcaseallchannelendpoints.
Orphan messages Theyoccurwhenachannelwithpendingmessagesisclosed.
Unspecified receptions They occurwhen athread entersa
switch/receive
constructandthebuffer ofone oftheend-pointsitscansstartswithamessagewhosetagisnotlistedasapossiblecaseinthe
switch/receive.
Contract violation Theyoccurwhenaprogramdoesn’tabidebyoneofitschannelcontracts:amessagewithanunexpectedtagissent,ornotenoughtagsareaccountedforina
switch/receive
accordingtothecontract,orthechannel isclosedwhenendpointsarenotinthesamefinalstate.Example9.Theprogram
P0
send(m
1, e) || switch
{ receive(m
2, f)
: skip; }
triggers anunspecifiedreception.Replacing
get()
byskip
inExample 2wouldcauseacontractviolation(theendpointf
isstillintheinitial,non-finalstatewhenthechannelisclosed)aswell asan orphanmessage.Replacingconsumer()
byskip
inExample 6wouldleakbothendpointsofthecommunicationchannel.Note that all oftheerrors we listedare incomparable, although itis possibleforsingle program toexhibit several of them.Inparticular,orphanmessagesarenotaspecialcaseofmemoryleaks:itmaybethecasethatlostmessagescarried noheapdata(e.g.messagesthatconsistofscalarvaluessuchasintegersorbooleans).
2. Proofprinciplesforcontract-obedientsharingofendpoints
In thissection,we introducethe mainideas that underpinournewprogram logic.Thislogic marriesseparation logic on theone handandchannelcontractsonthe otherhand,andestablishes theabsenceoftheerrors listedinSection 1.4 inprograms,aswellascontractobedience.ProgramspecificationsestablishedbyourprogramlogictaketheformofHoare triples
{
ϕ
}
p{ψ}
.Hoaretriplesareunderstoodintermsofpartialcorrectness,thatis,aprovedprogramisnotguaranteedto terminate.Separationlogicnaturallyenforcessomepropertiessuchasdataracefreedomandlinearusageofendpoints,as wewillseeinSection2.1.Thechallengeistouseseparationlogictocheckcontractobedienceinthepresenceofendpoint sharing,andfromthattodeducetheabsenceoforphanmessagesandunspecifiedreceptionsinprovedprograms.Anotableproperty notguaranteedbyourprogramlogicisdeadlock-freedom.Webelievethat deadlocksare aconcern orthogonal tothemainaimofthispaper,whichistoverifycontractobedienceofchannel-sharingprograms,andthat our programlogiccanbeextendedtopreventdeadlocksbyborrowingfromexistingtechniques,forinstancesessiontypes[20] orLeinoet al.[24].
2.1. Ownershipandseparation
Separation logic enforces and exploits locality principlesin programs. As a first approximation (before we introduce permissions),theselocalityprinciplescanbesummarisedasfollows.
Ownership hypothesis Eachthreadownsaregionoftheheap:itcanonlyreadandupdatethatpartoftheheap.Thelimits oftheheapregionownedbyathreadmayhoweverevolveduringtheexecution.
Separation property At any point in time, each heap objectis owned by at most one thread. In the context of message
passing,eachallocated endpointisownedeitherbyexactlyonethreadorbyamessagecurrentlystoredinanother endpoint’squeue.
Before we introduce our assertion language and program logic formally, let us illustrate these principles with proof sketchesoftheprograms ofExamples 2 and 6.Onceourprogramlogichasbeenintroduced,thereaderisinvitedtocome backtotheseproofsketchesandcheckthattheyareindeedderivableinourframework.
The proof sketches, shown in Fig. 1, consist of annotating programs with ownership information. An annotations is written inbrackets
[
ϕ
]
anddenotesthefactthatϕ
holdsatthatprogrampoint (e.g.inthecaseofaloop,ϕ
istheloop invariant).WegivetheformalsyntaxofformulasinSection3.1.Inthemeantime,letusbrieflyandincompletelydescribeit. Apredicatex→ (
Cq,
y)
denotestheownershipoftheendpointataddressx,whosepeeris y,andwhichfollowscontract C andiscurrentlyinthestateq ofthatcontract.Thepredicateempdenotestheemptyheap.Theconnectivesthatcanbe seeninFig. 1arethoseofclassicallogic,exceptfortheseparatingconjunction∗
ofseparationlogic:ϕ
∗ ψ
istrueofastate ifitsresources(the endpointsinourcase)canbesplitintotwodisjoint setsofresources,suchthatonesub-statesatisfiesϕ
andtheothersatisfiesψ
.In both programs shown in Fig. 1, the precondition of
main,
emp, indicates that nothing is known to be allocated (or, alternatively, that nothingis owned) atthe beginning ofthe execution. The main thread firstopens a newchannel, after whichit owns bothofits endpoints, whoseaddresseshavebeen storedinvariablese
andf
respectively.Here the separatingconjunction∗
isusedtoaddtogetherthetwodisjointpiecesofownedheap,eachconsistingofasingleendpoint. Eachthreadthengetsadifferentendpoint(inaccordancewiththeseparationproperty).Fig. 1. Ownership annotations forExamples 2 and 6.
InExample 2,
put
startswithpreconditione→ (
C21,
f)
andget
startswithf( ¯
C21e)
.Eachthreadretainsownership ofits endpointforits entireexecution. Theput
thread sends eitheranint
orabool
message; whateverbranchends up beingexecuted, theendpointwillbe instate 2 attheend. Conversely,theget
threadhastobe readyforanyofthe possibilities indicated by C¯
2, lestan unexpectedreception occurs, andfinishes withf
instate 2 of C¯
2.The mainthread continuesby collectingthe postconditionsofeach threadafterthey havebothfinished executing.In thiscase, thisyields thetwoendpointsinstate2ofC2andC¯
2,respectively.Since2 isafinalstateofC2,thechannelcanbesafelyclosed.Behindthe scenes,the proof ofthe parallel composition of
put
andget
in themain thread usesthe followingrule of concurrent separation logic, which justifies distributing disjoint pieces of the heap to each thread and merging the correspondingpostconditionsattheend:Atfirstglance,thisruleseemstopreventtwothreadsfromusingthesameresources.However,asweareabouttoseewith theproof sketch ofExample 6,sending andreceiving messagesallow pieces ofheaptobe logicallytransferred fromone threadtoanother.
The proof sketchof Example 6issimilar to that ofExample 2,exceptforthe treatment ofthe
fin
message.Indeed, theownershipofendpointe
istransferred fromtheproducerthreadtotheconsumerwhenthefin
messageisexchanged. Thisjustifies whyconsumer
cansafelyclosethechannel,even thoughproducer
initiallyowns theendpointe.
Inthe program logic, each messagetag isassigned a separation logic formula, called its footprint, which is logically lost upon sendingmessages withthat tag,andgaineduponreceiving.Inthiscase, thefootprintofthemessageisdescribed bythe formulae
→ (
C62,
f
)
:whentheproducer
threadgivesupownershipofe,
fin
hasbeensentandthuse
isinstate2 ofC6,whichisthestateinwhichconsumer
receivesittoclosethechannel.2.2. Beyondlinearitywithpermissions
At first glance, the separation property andthe Parallel rule seem at odds withendpoint sharing: for two threads to be usingthe sameendpoint concurrently,both haveto ownit. However, theformula e
→ (
Cq,
f)
∗
e→ (
Cq,
f)
is inconsistent,asitimpliese.g. e=
e,thus preventingan obviousapplicationofthe Parallel rule.A first wayaround that apparent limitation isto introducefractionalpermissions[6,5].The permissionofan ownedpiece ofheap isanyquantityFig. 2. Fractionalsharesforendpointsharing:proofsketchofExample 7.Theproofsofthemainandconsumerfunctionsareidenticaltothoseshownin Fig. 1andarenotrepeatedhere.
π
∈ (
0,
1]
.2Thepermission1 isthe“full”permissionwhileapermissionπ
<
1 isa“partial”permission.Todenotefractional ownershipofan endpoint,we adda subscript tothepredicate:eZ⇒
π(
Cq,
f)
denotes theownershipofafractionπ
of the endpoint e. We omit the subscript when it is 1 (thus, eZ⇒
1(
Cq,
f)
⇔
e→ (
Cq,
f)
). Crucially, an endpoint with permissionπ
such that 0<
π
=
π
1+
π
2≤
1 can be split into two disjoint pieces of ownership with permissionsπ
1 andπ
2,as expressed by the followinglogical equivalence (where⊕
isthe addition operation on thereals defined only whenthesumislessorequalto 1):e
Z⇒
π1⊕π2 Cq,
f⇔
eZ⇒
π1 Cq,
f∗
eZ⇒
π2 Cq,
fHoldinganendpointwiththefull permissionmeansthatnootherthreadiscurrentlyusingthat endpoint.Hence,thefull permission grantsunrestrictedaccesstotheendpoint,forsending,receiving,orclosingthechannel.Holdingonlyapartial permission meansthatotherthreadsmightbeaccessingtheendpointconcurrently.Hence,inordernottoinvalidatetheir viewoftheendpoint’sstate,apartiallyownedendpointcanonlybeusedforcommunicationsthatdonotupdate thecontract state,andclosingachannelwithpartiallyownedendpointsisforbidden.
This additionalexpressive powerallows ustoprove themultipleproducers programfromExample 7. A sketchofthe proof isshown inFig. 2.Note that allocatinga newchannel creates endpoints withthe full permission.The permission is splitatthelevelofthe parallelcomposition in
producers
todistributefractionsofthe endpointe
toeach producer thread. Each producer is then allowed to sendobject
messages thanks to the self-loop on state 1 of C7, but not thefin
message,asthiswouldupdate thecontract stateto 2,whichisforbidden bythepermission discipline.Afterall the producers havefinishedrunning,all partialpermissionsarecollected backintothefull permission,allowingputters
to sendthefin
messagewithfootprinte
→ (
C2,
f
)
totheconsumerthread,whichcombinesitwithitsowntoclosethe channel.2.3. Linearityinhindsight
Oursecondsharingparadigm reliesona specificdisciplineofownershiptransfer,wherebytheentireownershipofthe receivingendpointistransferredduringthemessageinitiatingthecommunication.Inparticular,thereceiverthreadinitially holdsnoownershiponthatendpoint.Receivingtheinitialmessagegrantsitboththeaposteriori knowledgeofthestateof theendpointandtherighttocontinuethecommunicationinaccordancetothecontract.
Thisprinciple isillustratedinformally intheproof sketchofExample 8showninFig. 3.Inthisexample,thefootprint associated to the
product_descr
message isf
→ ( ¯
C81,
e
)
(note, andthe one associated to theoffer
message isf
→ ( ¯
C81,
e
)
). Notethat thesefootprints bearno syntacticrelationship withthevaluesof thecorresponding messages, illustratingtheexpressivityoffootprint-basedownershiptransfer.Althoughstraightforward initsapplication, thereasonwhylinearity cansoundlybeestablished inhindsightisall but immediate. Onecouldimagine abuyerreceiving
f
whileanotherbuyerisinthemiddleofrealisingits interactiononthe samef,
thusviolatingbothcontractobedience(fromthepointofviewoftheseller,whodoesnotexpecttwo“sessions”to be runningconcurrently),andlinearity.Inthisexample,itisclearwhythiscannothappen:product_descr
messageis onlysentatthebeginningofeachsession.Moregenerally,toguaranteethatmessagesthatgrantownershipoftherecipient endpointaposterioricanonlybesentoncepersession,weneedacarefullycraftedsemanticsofprogramsthatkeepstrack ofwhatisownedbyeachthread(seeSection5.3).3. Programlogic
In thissection, weformally introducethesyntax andsemantics ofthe assertionsoftheprogram logic,followedbyits proofrules.
2 Forsimplicity,werestrictourattentiontofractionalpermissions,butanyotherpermissionmodelcouldbeusedinstead,suchastokens[5]ortree shares[12].
Fig. 3. Linearity in hindsight: proof ofExample 8.
3.1. Syntaxandsemanticsofassertions
Syntax Assertionsconveyinformation aboutthevaluesof theprogram variablesandthe resources that areownedby a
thread at a given point in time, and the values that are transmitted and the resources whose ownership is transferred alongsidemessages(the messagefootprints).Weassume aninfiniteset
LVar
= {
x,
y,
. . .
}
oflogicalvariables,distinct from programvariablesinVar.
Expressionsinformulasarethesameasprogramexpressions(fromSection1.1),exceptthatthey areallowedtomentionlogicalvariables.Definition10.Thegrammaroflogicalexpressions(alsowrittenE)andformulasisasfollows:
E
::=
x| x |
v|
E1+
E2| · · ·
logical expressionsϕ
::=
E1=
E2|
emp|
E1→
π1 Cqπ2,
E2|
E1→
π C,
E2 predicates| ¬
ϕ
|
ϕ
1∧
ϕ
2| ∃
x.
ϕ
|
ϕ
1∗
ϕ
2 connectivesThe predicateE1
=
E2 asserts thatthe two expressions E1 and E2 evaluate tothe samevalue. Theempty resourceis denoted bythe emp predicate. Theconnectivesare those ofclassicallogic, except∗
whichisthe separatingconjunction. Otherclassicalconnectivessuchas∨
,⇒
,∀
canbedefinedasusual.The assertion E1
→
π1(
Cqπ2,
E2)
representsa heapwhere a single endpoint E1 is owned withpermissionπ
1. TheendpointfollowscontractC ,iscurrentlyisstateq of C ,anditspeerisE2.Moreover,afractionalpermission
π
2isassigned to q. A contractstate ownedwithpermissionlessthan thetotal permission 1cannot be updated by aprogram. Seethe exampleinFig. 2andtheaxiomsofSection 3.3formoredetails.The assertion E1Z⇒
π(
Cq,
E2)
describedinSection 2.2 (andusedinFig. 2)issimplesyntacticsugarthatdistributesequalpermissionstotheendpointanditscontractstate(this isintroducedpurelytosimplifynotationsasonlyonepermissionhastobespecifiedinthiscase):E1
Z⇒
π Cq,
E2 E1→
π Cqπ,
E2Insomecases,wewillneedtotalkaboutendpointswhosecontractstateisnotknown(orowned)atallbytheprogram, i.e.the permission on the contract state is “empty”. This isdenoted by assertions of the form E1
→
π(
C,
E2)
,3 whose other parametershavethe samemeaningasfor E1→
π(
Cqπ,
E2)
.Anemptypermission onthecontract state prevents allcommunicationonthatendpoint;onlytheknowledgethattheendpointexistsisretained.AswewillseeinSection3.5, weneedthissecondformofendpointownershipfortechnicalreasons,tobeabletodescribesomefootprintsinawaythat guaranteesleakfreedom.Asusual,wemayomitpermissionsubscriptswhentheyareequalto1.
Semantics Weassumeadditionalinfinitesets
Endpoint
= {
ε
,
. . .
}
,Ctt
= {
C,
. . .
}
,andControl
= {
q,
. . .
}
ofrespectively endpointlocations,contracts,andcontractstates.RememberthatΠ
= (
0,
1]
isthesetoffractionalpermissionsintroduced inSection 2.2.An endpointis associatedto atupleof oneof two forms:either(
ε
,
π
,
C)
or(
ε
,
π
,
C,
π
,
q)
,recordingits peerendpointε
,thefractionoftheendpointthatisowned,itscontract C ,andpossiblyitscurrentstateinthecontractq3 Notethatpermissionmodelsdonotconsidertheemptypermissiontobeavalidpermission;inparticular,0∈ Π/ .Thisandthefactthatspecifyingthe contractstatewouldberedundantwhenitisnotknownjustifytheneedforasecondnotation.
andthe permission
π
held onthat controlstate. Intuitively,anendpointrecord(
ε
,
π
,
C)
correspondsto thesituationin whichthepermissiononthecontractstateis0 (but0 isnotavalidpermission),henceisbasicallyunconstrained.Endpointsareallocatedinasharedheaprepresentedbyapartialfunctionfromlocationstoendpointsrecords.Remember that
Val
isthesetofallvaluesintroducedinSection1.1.ThesetofvaluesVal
containsallvaluesofinterest,forexampleEndpoint
∪ N
⊆ Val
.Definition11(Localstates).Localstates arepairs
(
s,
h)
ofastacks∈ Stack
,mappingprogramvariablestotheirvalues,and aheaph∈ Heap
,recordingthecurrentlyownedendpoints:Stack
Var Val
Heap
Endpoint
finΠ
× Endpoint × Ctt × (∅ + Π × Control)
Notethat localstatesdonottracktheprecise contentsoftheendpointqueues,onlythe contractstate ofeach owned endpoint.Thisisenoughtointerpretthestatementsofourlogic,butnotforgivingafaithfuloperationalsemanticstoour programming language. Section 5extends local stateswithqueue contents anddefinesan operationalsemantics for the language.
We definethe peerfunctionmate
(
h)
: Endpoint Endpoint
asthe functionwiththesamedomainash andsuch that mate(
h)(
ε
)
=
ε
ifh(
ε
)
= (−,
ε
,
−,
−,
−)
orh(
−,
ε
,
−)
.Similarly, wedefine thefunctionscontract(
h)
andcstate(
h)
as follows: ifh(
ε
)
= (−,
−,
C,
−,
q)
,then contract(
h)
=
C and cstate(
h)
=
q,andifh(
ε
)
= (−,
−,
C)
then contract(
h)
=
C , the functionsbeingundefinedelsewhere.Definition12(Well-formedheap).Aheaph issaidtobewell-formed if,forallallocated
ε
suchthatmate(
h)(
ε
)
=
ε
∈
dom(
h)
,•
contract(
h)(
ε
)
andcontract(
h)(
ε
)
aredual•
mate(
h)(
ε
)
=
ε
We nowdefineapartialcomposition operationonlocalstates.Intuitively,thecomposition oftwo statesaddstogether the permissionsofthe heapobjects ofthesestates.Inparticular, thecomposition oftwo stateswithdisjoint domainsis theirdisjointunion.
Definition13(Compositionofheaps).Leth1,h2 betwoheaps.Recallthat
⊕
istheadditionoperatoroverrealnumbers,and considerthetotalfunction f definedoneveryendpointlocationε
as:•
ifε
∈
/
dom(
h1)
∪
dom(
h2)
,then f(
ε
)
=
undef•
ifε
∈
dom(
h1)
\
dom(
h2)
,then f(
ε
)
=
h1(
ε
)
•
ifε
∈
dom(
h2)
\
dom(
h1)
,then f(
ε
)
=
h2(
ε
)
•
ifh1(
ε
)
= (
π
1,
ε
,
C)
,h2(
ε
)
= (
π
2,
ε
,
C)
,andπ
1⊕
π
2≤
1,then f(
ε
)
= (
π
1⊕
π
2,
ε
,
C)
•
ifh1(
ε
)
= (
π
1,
ε
,
C,
π
1,
q)
,h2(
ε
)
= (
π
2,
ε
,
C)
,andπ
1⊕
π
2≤
1,then f(
ε
)
= (
π
1⊕
π
2,
ε
,
C,
π
1,
q)
•
ifh1(
ε
)
= (
π
1,
ε
,
C)
,h2(
ε
)
= (
π
2,
ε
,
C,
π
2,
q)
,andπ
1⊕
π
2≤
1,then f(
ε
)
= (
π
1⊕
π
2,
ε
,
C,
π
2,
q)
•
if h1(
ε
)
= (
π
1,
ε
,
C,
π
1,
q)
, h2(
ε
)
= (
π
2,
ε
,
C,
π
2,
q)
,π
1⊕
π
2≤
1, andπ
1⊕
π
2≤
1, then f(
ε
)
= (
π
1⊕
π
2,
ε
,
C,
π
1⊕
π
2,
q)
•
otherwise, f(
ε
)
=
errorLeth betheheapdefinedby restricting f toendpointlocations
ε
such that f(
ε
)
∈ {
/
undef,
error}.
Wesaythat h1 andh2 arecompatible,writtenh1⊥
h2,ifh isawell-formedheapand,forallε
, f(
ε
)
=
error.Whenthisisthecase,wesaythath isthecomposition ofh1 andh2,andwriteh=
h1•
h2.In thedefinitionabove, error isused torepresentincompatibility betweentwo heapsata givenlocation, forinstance because thecombined permissionsatthatlocation are greater than1, orbecausethe heapsdisagree onthe peerorthe contract ofthat location. Onecan checkthat
•
isassociativeandcommutativewithunit∅
,thefunction withtheempty domain.We interpretformulasusinga forcingrelationon well-formedlocalstatestogether withan interpretation
ι
forlogical variables:ι
: LVar → Val
Definition14(Semanticsofformulas).Let
J
EK
s,ι denotethe semanticsoftheexpression E withrespect tothestack s and interpretationι
,i.e.J
xK
s,ι=
s(
x)
,J
vK
s,ι=
v,J
E1+
E2K
s,ι= J
E1K
s,ι+ J
E2K
s,ι,etc.e
→
Cq,
f∗
e→
Cq,
f(
e=
f)
⇔ (
e=
f)
e→
Cq,
f∗
f→
Cq,
f C= ¯
C e→
Cq,
f eZ⇒
Cq,
f e→
Cq,
f eZ⇒
.5 Cq,
f∗
eZ⇒
.5 Cq,
f e→
Cq,
f e→
.5 Cq,
f∗
e→
.5 C,
f 3.2. FootprintsOur program logic achieves thread-modularreasoning: each thread can be proved in isolation of other threads. There aretwo mechanismsatworktoachieve this:first,contractsallow athreadtoknowwhatmessages toexpectfromother threads;second,messagefootprintsallowthreadstoagreeonwhatresourcesaretransferredalongsidemessages.
Thefootprint of amessageisthe pieceofheapthatislost whensendingthismessageandgainedwhenreceivingit.4 Thecorrectnessoftheinteractionbetween
producer
andconsumer
inExample 6isbasedontheassumptionthatthe footprintofthefin
messageistheendpointf,
representedbytheformulaf
→ (
C62,
e
)
.Moregenerally,givenaprogram toprove,wewillassociateafootprinttoeverymessagetagm usedintheprogramandassumethatevery timem issent (respectivelyreceived)thesamefootprintisassertedandlost(respectivelyassumedandadded).Definition16(Footprints).Footprintsare formulas
φ (
src,
val1,
. . . ,
valn)
whereonlythevariablessrc,val1,
. . . ,
valn mayap-pearfree.Thefirstfreevariablesrcisaparameterthatstandsfortheendpointthatsendsthemessage,andthenextn free variablesaretheparametersthataretobeinstantiatedwiththemessage’svalues(assumingthatitisofarityn).
Definition17(Footprintenvironments).Afootprintenvironment
Φ
isamappingfrommessageidentifiers tofootprints,such thatmessagesofarityn aremappedtofootprintsofarityn+
1.Example18. InExample 6,we mentionedthatthefootprint ofthe
fin
messagecouldbe describedby theformulae
→
(
C62,
f
)
, butthis is not quite accurate. Indeed, the footprint offin,
a message of arityzero, can have only one free variable,whichrepresentsthesourceendpoint.Acorrectfootprintforthisexample(whichallowsthesameproofsketchto gothrough)isφ
fin(
src)
∃
f.
src→ (
C62,f)
.Givenafootprint
φ (
src,
val1,
. . . ,
valn)
,wewriteφ (
E,
E1,
. . . ,
En)
forφ
[
src,
val1, . . . ,
valn<
−
E,
E1, . . . ,
En]
3.3. Proofrulesformessagepassing
Forthissection,weassumeafixedfootprintenvironment
Φ
.Channelallocationanddeallocation The rules forallocation anddisposal aresymmetric:
open
produces twofully owned endpoints that are each other’s peer, whileclose
consumes them. Endpoints are allocated in the initial state of their contracts,andclosingthemisonlyvalidiftheyareinthesamestateofthecontract,andthatstateisafinalstate.Sendandreceive Communicationinstructionsperformownershiptransfer ofthemessagefootprint,andadvancethecontrol state ofthecommunicationendpointaccordingtothecontract.Moreprecisely,
send
firstupdatesthecontrolstateofthe endpoint, then releases ownership of the footprint corresponding to the exchanged message.Conversely,receive
first acquiresthefootprintofthemessage,thenupdatesthecontrolstateoftheendpoint.Toaccountforallcasesuniformly,weuseapseudo-instruction
skip
eλ,f,whereλ
denoteseither!
m or?m.Itsroleisto updatethecontractstateofe
(withpeerf)
accordingtotheactionλ
.Thenameskip
stressesthefactthatthese instruc-tionshavenooperationaleffectsincetheunderlyingsemanticsofprogramsisindependentofcontracts(seeSection6.2).The
skip
eλ,f instruction modifies thecontract state of e withrespect to theactionλ
andchecks that the transitionis indeed authorised by the contract. Updating a contract state requires only a partial read permission if the state is left unchanged,andatotalpermissionotherwise.Thepseudo-instruction
skip
eλ,f isusedintherulesforcommunications,whichadditionallyperformsownership trans-fersaccordingtothemessagefootprint.Note thatthe orderinwhich theownershiptransferandthe controlstate update areperformedis notimportant unless the footprint contains theownership ofthe communicating endpoint itself. Receivingassigns the messagevalues to the variables
x
1 tox
n (which can alsobe mentioned inthe footprint), hencewe need toreplace their previous occurrenceswithfreshvariables y1 to yn.
Switch/receive Finally,two newrulesaddress the
switch/receive
construct:the firstrule dispatchesswitches on dif-ferent endpointsindifferentsubproofs,thesecondaddressesswitch/receive
ona uniqueendpointonly:inthatcase, this endpointmustbe owned(at leastpartially),andthe switch ischeckedto be exhaustivewithrespectto allpossible incomingmessagesaccordingtothecurrentcontractstate.Originalproofruleswithoutsharing[33] Itisinterestingtorecallherethefirstproofrulesthatwereintroducedfor contract-obedientmessagepassingby[33](formessagesofarityoneonly).Whilethespecificationsforopeningandclosingchannels aresimilartothiswork,bothsendingandreceivingrequirefullownershipofthecommunicatingendpoint,whichprevents fractional-shares-basedsharing.Moreover,theendpointhastobeownedpriortoreceivingonit,contrarilytoour“linearity inhindsight”principle.
Fig. 4. Standard proof rules.
Byremarkingthatafiner-grainedtreatmentofthepermissionsrequiredforcommunicationsispossible,wehaverestored the symmetryin the treatments of
send
andreceive,
andhaveenabled theverificationof arich variety ofendpoint sharingpatterns.3.4. Proofrulesofseparationlogic
Letuspresentthe remaining rules ofour program logic,shownin Fig. 4,which are standard inseparation logic.We write reads
(
p)
(resp.writes(
p)
)forthevariables read(resp.writtento) by program p,asdefinedinTable 1.Welet fv(
p)
and fv
(
ϕ
)
denote the free variables of program p and formulaϕ
(defined asusual), respectively, andwrite fv(
p,
ϕ
)
for fv(
p)
∪
fv(
ϕ
)
.Letusbrieflyexplaineachrule.•
Skip:Theprogramthatdoesnothingdoesnotneedanyresourcestodoso(emp).Usingtheframerule,onecanderive{
ϕ
}
skip
{
ϕ
}
foranyϕ
(usingthefactthatempistheunitof∗
:ϕ
∗
emp⇔
ϕ
).•
Assume:Ifthetestissuccessful,theprogramterminates.•
Assign:Thepreconditionisupdatedtoreflectthenewvalueofx
inthepostcondition.•
Sequence: Thisis the classical Floyd–Hoarerule for composingprograms sequentially:the postcondition ofthe first programmustbeavalidpreconditionofthesecondone.•
Parallel: Theruleforparallelcomposition accountsfordisjoint concurrency:one hastobeableto partitionthe pre-condition intotwodisjointportions thatare validrespectivepreconditionsforeach ofthetwo threads.Theresulting postconditionsaregluedtogethertoformthepostconditionoftheparallelcomposition.•
Choiceand Star arestandard.•
Local:Theproofcontinueswithafreshvariabley.
•
Frame: Thisrulestatesthat,whenevertheexecutionofaprogramfromacertainheapdoesnotproducememoryfaults, itwillnotproducememoryfaultsfromabiggerheapeither(apropertycalledsafetymonotonicity),andtheextrapiece ofheapwillremainuntouchedbytheprogramthroughoutitsexecution(apropertycalledlocality).Withtheframerule,one canrestrict thespecificationofprograms tothe cellsthey actually access(their footprint[29]).Thisalso justifies givingtheaxiomsforatomiccommandsinaminimalisticway.
•
Consequence isthe standardFloyd–Hoarerule,whosesoundnessfollows directlyfromthedefinitionofwhata valid Hoaretripleis.Thenotionoflogicalentailmentissemantic(seeSection3.1).•
Conjunction, Disjunction,and Existential arestraightforward(notethat x∈
/
fv(
p)
inthe Existential rule,sincex has tobealogicalvariable).We write
Φ{
ϕ
}
p{ψ}
todenotethattheHoaretriple{
ϕ
}
p{ψ}
hasaproof inourproof systemunderthefootprint environmentΦ
,and{
ϕ
}
p{ψ}
whenΦ
isclearfromthesurroundingcontext.3.5. Validfootprintenvironments
Inthissection, weintroducetwo technicalfinepointsaboutfootprintenvironments:theymustbe valid,andtheeach footprintmustbeprecise.
Precisionisrequiredforthelocality ofthe
send
instruction(seeLemma 44anditsproofinAppendixA.2).This techni-calityisrequiredinmanyvariantsofconcurrentseparationlogic,fromitsinceptionbyO’Hearn[28]to,e.g.,extensionsto storablelocks[17].A formulaispreciseifforallstates,thereisatmostonesubstatesatisfyingit.Allthefootprintsdefined inthispaperareprecise.Definition19 (Precision). A formula
ϕ
is precise if, forall s, h,ι
,there is at mostone h such that∃
h.
h=
h•
h and(
s,
h),
ι
|
ϕ
.Validityoffootprintenvironmentsensuresthatexchangingmessagesdoesnotcreatememoryleaksthatmightbemissed by thelogic.Althoughwedelay thedefinitionofvalidityuntilSection6.3,letusdescribeithereinformally.As remarked byBonoetal.[3]andVillard[32],ifoneisnotcarefulthentheprogramlogicmaymisssomememoryleaks.Forinstance, theHoaretriple
{
emp} (e,f) = open(
C); send(channel,e,e)
{
emp}
isderivable(forsomeC )usingafootprintenvironmentthatassignstothe
channel
messagethefootprintφ
channel(
s,
x)
∃
y.
s=
x∧
s→
C
q,
y∗
y→
Cq,
seven though this program did not deallocate all the memory. The problem is that the ownershipof the endpoint
f
is passed tothe recipientofthemessage,butthe recipientofthemessageistheowner off,
whichresultsinacircularity. Theendpointf
becomes“ownerless”.Severalsufficient(butnotnecessary)conditionstopreventthissituationhavebeenexploredintheliterature:
•
àla Sing,forbiddingthemessagefootprintstocontainendpointsthatareinareceivestate;
•
àla Villard[32],allowingtosendserverendpointsonly(thefirstonesofthepairsallocatedwithopen),
andallowing onlytosendthemfromserverendpoints;•
àla Bonoetal.[3],imposingawell-foundednesscondition.We will formalise the notion of validfootprintenvironments in Section 6.3, which also forbids this situation,using a semanticcriterion.
As an example of a non-valid footprint environment, consider again the proof sketch of Fig. 3. The footprint of the message
product_descr
messageweimplicitlyusedinthisproofis∃
x.
x→ (
C81,
src)
.Thefootprintenvironmentthat contains thisfootprint isnot valid, becauseitallows to derivea proof offoratriple oftheform{
emp}
p
{
emp}
,with p leakingmemoryalongthesamelinesastheexampleabovebasedonthechannel
message.InordertoprovetheexampleofFig. 3withavalidenvironment,wecanchangetheproofslightlyandratherconsider thatthesellerlosesthefullownershipaboutthecontractstateoftheendpoint,butnotabouttheendpointitself.Thenthe footprintfor
product_descr
becomes∃
x.
x→
.5(
C81,
src)
.Thisgivesrisetothefollowingnewproof:[e
→ (
C81, f) ∗ f → ( ¯
C81, e)]
close(e,f);
} [emp]
Ourotherexamples sofarneversendtherecipientendpointalong withthe message,hencehavevalidfootprint envi-ronments.
4. Furtherexamples
4.1. Dynamiclocks
Thesharingpatternsweconsiderareexpressiveenoughtoencodedynamicallyallocatedlocks.Thespecificationswegive tothelockingprimitives followtheonesofGotsman etal.[17].Thelockintendsto protecta pieceofheapthatsatisfies a certain invariant
φ
.When thelockis acquiredtheownership ofφ
is∗
-conjoined tothe currentstate.The invariantφ
mustbe established backupon releasingthelockandisthen consumed,i.e.removed fromthecurrentlocalstate ofthe program.LikeGotsmanetal.[17],weassumethatthelockisinitiallyacquiredbythethreadthatcreatesit(henceitsnext moveshouldbetoreleaseit),andthatitcanonlybereleasedbyathreadthathasacquiredthelockfirst.Weproposethe followingencodingoflockingprimitives:
(x0,x1) = new_lock() [emp] {
(x0,x1) = open(
C);
} [locked
(x1)]
dispose_lock(x0,x1) [locked
(x1)] {
send(stop,x0); receive(stop,x1);
close(x0,x1);
} [emp]
acquire(x0,x1) [emp] {
receive(token,x0);
} [locked
(x1)
∗
ϕ
]
release(x0,x1) [locked
(x1)
∗
ϕ
] {
send(token,x1);
} [emp]
The lifetime of a lock is as follows:
new_lock
allocates a new locked lock, which can then be released withrelease
and acquired again withacquire.
Any thread can attempt to acquire the lock. The lock can be destroyedwith
dispose_lock.
Theencodingaboveisbasedontwomessages
token
andstop.
Thefirstoneisusedtotransfertheownershipofthe lockfromathreadtothenextthreadthatacquiresthelock.Thesecondonetriggersthedeallocation.1 2
!token
!stop
φ
token(
src)
locked(
src)
∗
ϕ
φ
stop(
src)
empAll messagestransit throughthe endpoints
x0 and
x1.
The ownershipofthe endpointsx0 and
x1
isshared linearly using the same form of backward reasoning as explained in Section 2.3. Thetoken
message thus transfers the write ownershipofx0 and
x1,
andgivestherighttoreceivethetoken
messageintheacquire
functioneveniftheendpointx0 is
notownedintheprestate.Themacropredicatesaredefinedasfollows:locked
(
x1)
∃
x.
x1→
C
1