зеркало из https://github.com/mozilla/pjs.git
Bug 555275: Implement a DeallocShmem() interface. r=bent
This commit is contained in:
Родитель
a2d75cb968
Коммит
9edec1c173
|
@ -52,6 +52,7 @@
|
|||
// enum in ipc_channel.h. They need to be kept in sync.
|
||||
namespace {
|
||||
enum {
|
||||
SHMEM_DESTROYED_MESSAGE_TYPE = kuint16max - 5,
|
||||
UNBLOCK_CHILD_MESSAGE_TYPE = kuint16max - 4,
|
||||
BLOCK_CHILD_MESSAGE_TYPE = kuint16max - 3,
|
||||
SHMEM_CREATED_MESSAGE_TYPE = kuint16max - 2,
|
||||
|
@ -93,6 +94,7 @@ public:
|
|||
virtual Shmem::SharedMemory* CreateSharedMemory(
|
||||
size_t, SharedMemory::SharedMemoryType, int32*) = 0;
|
||||
virtual Shmem::SharedMemory* LookupSharedMemory(int32) = 0;
|
||||
virtual bool DestroySharedMemory(Shmem&) = 0;
|
||||
|
||||
// XXX odd duck, acknowledged
|
||||
virtual ProcessHandle OtherProcess() const = 0;
|
||||
|
|
|
@ -129,6 +129,21 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class ShmemDestroyed : public IPC::Message
|
||||
{
|
||||
private:
|
||||
typedef Shmem::id_t id_t;
|
||||
|
||||
public:
|
||||
ShmemDestroyed(int32 routingId,
|
||||
const id_t& aIPDLId) :
|
||||
IPC::Message(routingId, SHMEM_DESTROYED_MESSAGE_TYPE, PRIORITY_NORMAL)
|
||||
{
|
||||
IPC::WriteParam(this, aIPDLId);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef MOZ_HAVE_SHAREDMEMORYSYSV
|
||||
static Shmem::SharedMemory*
|
||||
CreateSegment(size_t aNBytes, SharedMemorySysV::Handle aHandle)
|
||||
|
@ -598,5 +613,14 @@ Shmem::ShareTo(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
|
|||
return 0;
|
||||
}
|
||||
|
||||
IPC::Message*
|
||||
Shmem::UnshareFrom(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
|
||||
base::ProcessHandle aProcess,
|
||||
int32 routingId)
|
||||
{
|
||||
AssertInvariants();
|
||||
return new ShmemDestroyed(routingId, mId);
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -224,6 +224,15 @@ public:
|
|||
base::ProcessHandle aProcess,
|
||||
int32 routingId);
|
||||
|
||||
// Stop sharing this with |aProcess|. Return an IPC message that
|
||||
// contains enough information for the other process to unmap this
|
||||
// segment. Return a new message if successful (owned by the
|
||||
// caller), NULL if not.
|
||||
IPC::Message*
|
||||
UnshareFrom(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
|
||||
base::ProcessHandle aProcess,
|
||||
int32 routingId);
|
||||
|
||||
// Return a SharedMemory instance in this process using the
|
||||
// descriptor shared to us by the process that created the
|
||||
// underlying OS shmem resource. The contents of the descriptor
|
||||
|
|
|
@ -657,6 +657,7 @@ class StmtDecl(Node):
|
|||
def __init__(self, decl, init=None, initargs=None):
|
||||
assert not (init and initargs)
|
||||
assert not isinstance(init, str) # easy to confuse with Decl
|
||||
assert not isinstance(init, list)
|
||||
assert not isinstance(decl, tuple)
|
||||
|
||||
Node.__init__(self)
|
||||
|
|
|
@ -202,8 +202,8 @@ def _lookupActorHandle(handle, outactor, actortype, cxxactortype, errfn):
|
|||
def _lookupListener(idexpr):
|
||||
return ExprCall(ExprVar('Lookup'), args=[ idexpr ])
|
||||
|
||||
def _shmemType(ptr=0):
|
||||
return Type('Shmem', ptr=ptr)
|
||||
def _shmemType(ptr=0, ref=0):
|
||||
return Type('Shmem', ptr=ptr, ref=ref)
|
||||
|
||||
def _rawShmemType(ptr=0):
|
||||
return Type('Shmem::SharedMemory', ptr=ptr)
|
||||
|
@ -231,6 +231,10 @@ def _shmemAlloc(size, type):
|
|||
return ExprCall(ExprVar('Shmem::Alloc'),
|
||||
args=[ _shmemBackstagePass(), size, type ])
|
||||
|
||||
def _shmemDealloc(rawmemvar):
|
||||
return ExprCall(ExprVar('Shmem::Dealloc'),
|
||||
args=[ _shmemBackstagePass(), rawmemvar ])
|
||||
|
||||
def _shmemShareTo(shmemvar, processvar, route):
|
||||
return ExprCall(ExprSelect(shmemvar, '.', 'ShareTo'),
|
||||
args=[ _shmemBackstagePass(),
|
||||
|
@ -243,6 +247,11 @@ def _shmemOpenExisting(descriptor, outid):
|
|||
# true => protect
|
||||
descriptor, outid, ExprLiteral.TRUE ])
|
||||
|
||||
def _shmemUnshareFrom(shmemvar, processvar, route):
|
||||
return ExprCall(ExprSelect(shmemvar, '.', 'UnshareFrom'),
|
||||
args=[ _shmemBackstagePass(),
|
||||
processvar, route ])
|
||||
|
||||
def _shmemForget(shmemexpr):
|
||||
return ExprCall(ExprSelect(shmemexpr, '.', 'forget'),
|
||||
args=[ _shmemBackstagePass() ])
|
||||
|
@ -1360,6 +1369,9 @@ class Protocol(ipdl.ast.Protocol):
|
|||
def lookupSharedMemory(self):
|
||||
return ExprVar('LookupSharedMemory')
|
||||
|
||||
def destroySharedMemory(self):
|
||||
return ExprVar('DestroySharedMemory')
|
||||
|
||||
def otherProcessMethod(self):
|
||||
return ExprVar('OtherProcess')
|
||||
|
||||
|
@ -1481,6 +1493,10 @@ class Protocol(ipdl.ast.Protocol):
|
|||
elif side is 'child': op = '--'
|
||||
return ExprPrefixUnop(self.lastShmemIdVar(), op)
|
||||
|
||||
def removeShmemId(self, idexpr):
|
||||
return ExprCall(ExprSelect(self.shmemMapVar(), '.', 'Remove'),
|
||||
args=[ idexpr ])
|
||||
|
||||
def usesShmem(self):
|
||||
for md in self.messageDecls:
|
||||
for param in md.inParams:
|
||||
|
@ -3142,6 +3158,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
p = self.protocol
|
||||
routedvar = ExprVar('aRouted')
|
||||
idvar = ExprVar('aId')
|
||||
shmemvar = ExprVar('aShmem')
|
||||
sizevar = ExprVar('aSize')
|
||||
typevar = ExprVar('type')
|
||||
listenertype = Type('ChannelListener', ptr=1)
|
||||
|
@ -3177,7 +3194,12 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
ret=_rawShmemType(ptr=1),
|
||||
params=[ Decl(_shmemIdType(), idvar.name) ],
|
||||
virtual=1))
|
||||
|
||||
destroyshmem = MethodDefn(MethodDecl(
|
||||
p.destroySharedMemory().name,
|
||||
ret=Type.BOOL,
|
||||
params=[ Decl(_shmemType(ref=1), shmemvar.name) ],
|
||||
virtual=1))
|
||||
|
||||
otherprocess = MethodDefn(MethodDecl(
|
||||
p.otherProcessMethod().name,
|
||||
ret=Type('ProcessHandle'),
|
||||
|
@ -3214,9 +3236,8 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
# return false
|
||||
# Shmem s(seg, [nextshmemid]);
|
||||
# Message descriptor;
|
||||
# if (!s->ShareTo(subprocess, mId, descriptor))
|
||||
# return false;
|
||||
# if (!Send(descriptor))
|
||||
# if (!s->ShareTo(subprocess, mId, descriptor) ||
|
||||
# !Send(descriptor))
|
||||
# return false;
|
||||
# mShmemMap.Add(seg, id);
|
||||
# return shmem.forget();
|
||||
|
@ -3229,7 +3250,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
failif.addifstmt(StmtReturn(ExprLiteral.FALSE))
|
||||
createshmem.addstmt(failif)
|
||||
|
||||
shmemvar = ExprVar('shmem')
|
||||
descriptorvar = ExprVar('descriptor')
|
||||
createshmem.addstmts([
|
||||
StmtDecl(
|
||||
|
@ -3264,12 +3284,62 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
ExprSelect(p.shmemMapVar(), '.', 'Lookup'),
|
||||
args=[ idvar ])))
|
||||
|
||||
# bool DestroySharedMemory(shmem):
|
||||
# id = shmem.Id()
|
||||
# SharedMemory* rawmem = Lookup(id)
|
||||
# if (!rawmem)
|
||||
# return false;
|
||||
# Message descriptor = UnShare(subprocess, mId, descriptor)
|
||||
# mShmemMap.Remove(id)
|
||||
# Shmem::Dealloc(rawmem)
|
||||
# return descriptor && Send(descriptor)
|
||||
destroyshmem.addstmts([
|
||||
StmtDecl(Decl(_shmemIdType(), idvar.name),
|
||||
init=_shmemId(shmemvar)),
|
||||
StmtDecl(Decl(_rawShmemType(ptr=1), rawvar.name),
|
||||
init=_lookupShmem(idvar))
|
||||
])
|
||||
|
||||
failif = StmtIf(ExprNot(rawvar))
|
||||
failif.addifstmt(StmtReturn(ExprLiteral.FALSE))
|
||||
destroyshmem.addstmts([
|
||||
failif,
|
||||
StmtDecl(Decl(Type('Message', ptr=1), descriptorvar.name),
|
||||
init=_shmemUnshareFrom(
|
||||
shmemvar,
|
||||
ExprCall(p.otherProcessMethod()),
|
||||
p.routingId())),
|
||||
Whitespace.NL,
|
||||
StmtExpr(p.removeShmemId(idvar)),
|
||||
StmtExpr(_shmemDealloc(rawvar)),
|
||||
Whitespace.NL,
|
||||
StmtReturn(ExprBinary(
|
||||
descriptorvar, '&&',
|
||||
ExprCall(
|
||||
ExprSelect(p.channelVar(), p.channelSel(), 'Send'),
|
||||
args=[ descriptorvar ])))
|
||||
])
|
||||
|
||||
|
||||
# "private" message that passes shmem mappings from one process
|
||||
# to the other
|
||||
if p.usesShmem():
|
||||
self.asyncSwitch.addcase(
|
||||
CaseLabel('SHMEM_CREATED_MESSAGE_TYPE'),
|
||||
self.genShmemCreatedHandler())
|
||||
self.asyncSwitch.addcase(
|
||||
CaseLabel('SHMEM_DESTROYED_MESSAGE_TYPE'),
|
||||
self.genShmemDestroyedHandler())
|
||||
else:
|
||||
abort = StmtBlock()
|
||||
abort.addstmts([
|
||||
_runtimeAbort('this protocol tree does not use shmem'),
|
||||
StmtReturn(_Result.NotKnown)
|
||||
])
|
||||
self.asyncSwitch.addcase(
|
||||
CaseLabel('SHMEM_CREATED_MESSAGE_TYPE'), abort)
|
||||
self.asyncSwitch.addcase(
|
||||
CaseLabel('SHMEM_DESTROYED_MESSAGE_TYPE'), abort)
|
||||
|
||||
otherprocess.addstmt(StmtReturn(p.otherProcessVar()))
|
||||
else:
|
||||
|
@ -3292,6 +3362,9 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
lookupshmem.addstmt(StmtReturn(ExprCall(
|
||||
ExprSelect(p.managerVar(), '->', p.lookupSharedMemory().name),
|
||||
[ idvar ])))
|
||||
destroyshmem.addstmt(StmtReturn(ExprCall(
|
||||
ExprSelect(p.managerVar(), '->', p.destroySharedMemory().name),
|
||||
[ shmemvar ])))
|
||||
otherprocess.addstmt(StmtReturn(ExprCall(
|
||||
ExprSelect(p.managerVar(), '->',
|
||||
p.otherProcessMethod().name))))
|
||||
|
@ -3342,6 +3415,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
removemanagee,
|
||||
createshmem,
|
||||
lookupshmem,
|
||||
destroyshmem,
|
||||
otherprocess,
|
||||
Whitespace.NL ]
|
||||
|
||||
|
@ -3383,9 +3457,29 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
ExprDeref(memvar), _shmemCtor(_autoptrForget(rawvar), idvar))),
|
||||
StmtReturn(ExprLiteral.TRUE)
|
||||
])
|
||||
|
||||
|
||||
# bool DeallocShmem(Shmem& mem):
|
||||
# bool ok = DestroySharedMemory(mem);
|
||||
# mem.forget();
|
||||
# return ok;
|
||||
deallocShmem = MethodDefn(MethodDecl(
|
||||
'DeallocShmem',
|
||||
params=[ Decl(_shmemType(ref=1), memvar.name) ],
|
||||
ret=Type.BOOL))
|
||||
okvar = ExprVar('ok')
|
||||
|
||||
deallocShmem.addstmts([
|
||||
StmtDecl(Decl(Type.BOOL, okvar.name),
|
||||
init=ExprCall(p.destroySharedMemory(),
|
||||
args=[ memvar ])),
|
||||
StmtExpr(_shmemForget(memvar)),
|
||||
StmtReturn(okvar)
|
||||
])
|
||||
|
||||
return [ Whitespace('// Methods for managing shmem\n', indent=1),
|
||||
allocShmem,
|
||||
Whitespace.NL,
|
||||
deallocShmem,
|
||||
Whitespace.NL ]
|
||||
|
||||
def genShmemCreatedHandler(self):
|
||||
|
@ -3416,6 +3510,47 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
|
||||
return case
|
||||
|
||||
def genShmemDestroyedHandler(self):
|
||||
p = self.protocol
|
||||
assert p.decl.type.isToplevel()
|
||||
|
||||
case = StmtBlock()
|
||||
|
||||
rawvar = ExprVar('rawmem')
|
||||
idvar = ExprVar('id')
|
||||
itervar = ExprVar('iter')
|
||||
case.addstmts([
|
||||
StmtDecl(Decl(_shmemIdType(), idvar.name)),
|
||||
StmtDecl(Decl(Type.VOIDPTR, itervar.name), init=ExprLiteral.NULL)
|
||||
])
|
||||
|
||||
failif = StmtIf(ExprNot(
|
||||
ExprCall(ExprVar('IPC::ReadParam'),
|
||||
args=[ ExprAddrOf(self.msgvar), ExprAddrOf(itervar),
|
||||
ExprAddrOf(idvar) ])))
|
||||
failif.addifstmt(StmtReturn(_Result.PayloadError))
|
||||
|
||||
case.addstmts([
|
||||
failif,
|
||||
StmtExpr(ExprCall(ExprSelect(self.msgvar, '.', 'EndRead'),
|
||||
args=[ itervar ])),
|
||||
Whitespace.NL,
|
||||
StmtDecl(Decl(_rawShmemType(ptr=1), rawvar.name),
|
||||
init=ExprCall(p.lookupSharedMemory(), args=[ idvar ]))
|
||||
])
|
||||
|
||||
failif = StmtIf(ExprNot(rawvar))
|
||||
failif.addifstmt(StmtReturn(_Result.ValuError))
|
||||
|
||||
case.addstmts([
|
||||
failif,
|
||||
StmtExpr(p.removeShmemId(idvar)),
|
||||
StmtExpr(_shmemDealloc(rawvar)),
|
||||
StmtReturn(_Result.Processed)
|
||||
])
|
||||
|
||||
return case
|
||||
|
||||
|
||||
##-------------------------------------------------------------------------
|
||||
## The next few functions are the crux of the IPDL code generator.
|
||||
|
|
|
@ -44,6 +44,9 @@ TestShmemParent::RecvTake(Shmem& mem, const size_t& expectedSize)
|
|||
if (strcmp(mem.get<char>(), "And yourself!"))
|
||||
fail("expected message was not written");
|
||||
|
||||
if (!DeallocShmem(mem))
|
||||
fail("DeallocShmem");
|
||||
|
||||
Close();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -17,6 +17,9 @@ TestSysVShmemParent::Main()
|
|||
if (!AllocShmem(size, SharedMemory::TYPE_SYSV, &mem))
|
||||
fail("can't alloc shmem");
|
||||
|
||||
if (0 > mem.GetSysVID())
|
||||
fail("invalid shmem ID");
|
||||
|
||||
if (mem.Size<char>() != size)
|
||||
fail("shmem is wrong size: expected %lu, got %lu",
|
||||
size, mem.Size<char>());
|
||||
|
@ -44,6 +47,9 @@ TestSysVShmemParent::RecvTake(Shmem& mem, const size_t& expectedSize)
|
|||
if (strcmp(mem.get<char>(), "And yourself!"))
|
||||
fail("expected message was not written");
|
||||
|
||||
if (!DeallocShmem(mem))
|
||||
fail("DeallocShmem");
|
||||
|
||||
Close();
|
||||
|
||||
return true;
|
||||
|
|
Загрузка…
Ссылка в новой задаче