Hi everybody,
I am currently playing with flexpages. I have written simple client/server
application which sends data to each other using flexpages. I have written a
simple IDL file for the server interface. The first version was the
following :
library test_server
{
interface worker
{
int send_data([in] flexpage page,
[out, max_is(4096)] char reply[]);
};
};
The client sends data through the flexpage, and the server replies using
string ipc. This way the DICE generated code compiles without error, and my
application works. Then I wanted the server to reply also through a
flexpage, but another one than the page provided by the client application.
So I modify my IDL this way :
library test_server
{
interface worker
{
int send_data([in] flexpage page,
[out, in] flexpage reply);
};
};
I use [out, in] because this way the client can first assign the snd_base
before sending the request.
Note, that the "reply" parameter will be sent as a flexpage to the
server, that is, the page described by "reply" will be mapped. If you
just want to tell the server the send-base it should use, write smething
like this:
int send_data([in] flexpage page,
[in] unsigned long send_base,
[out] flexpage *reply);
After modifying my client lib and the component
function accordingly, I get a compile error in a DICE generated file :
/home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s
erver.c: In function `test_server_worker_wait_any':
/home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s
erver.c:91: error: `_dice_tmp_offset' undeclared (first use in this
function)
/home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s
erver.c:91: error: (Each undeclared identifier is reported only once
/home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s
erver.c:91: error: for each function it appears in.)
/home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s
erver.c: In function `test_server_worker_reply_and_wait':
/home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s
erver.c:172: error: `_dice_tmp_offset' undeclared (first use in this
function)
What I see in the generated file :
filter_server_worker_wait_any (...)
{
...
if (l4_ipc_fpage_received(_dice_result))
{
_dice_tmp_offset = 0;
while ((_dice_msg_buffer->_word._word[0][_dice_tmp_offset++] !=
0) && (_dice_msg_buffer->_word._word[0][_dice_tmp_offset++] != 0)) /* empty
*/;
/* skip zero fpage */
_dice_tmp_offset += 2;
_dice_opcode = _dice_msg_buffer->_word._word[0];
}
else
_dice_opcode = _dice_msg_buffer->_word._word[0];
return _dice_opcode;
}
The _dice_tmp_offset is not declared, the second error (line 172) is about
the same thing (it is exactly the same code in reply_and_wait()). So I have
tried to declare _dice_tmp_offset as an unsigned int, then I have :
/home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_
worker-server.c: In function `filter_server_worker_wait_any':
/home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_
worker-server.c:92: error: subscripted value is neither array nor pointer
/home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_
worker-server.c:92: error: subscripted value is neither array nor pointer
(The line 92 is the one with while(...)). Indeed after looking the code I
find it really strange, as _word[0] is a register.... More _dice_tmp_offset
is incremented by two after the while loop and never used after... I really
don't understand this code...
If I only set the reply flexpage as [in], I have the same behavior...
Am I doing something wrong ?
No.
Yes. Fix attached. Should be in public repository tomorrow.
Yes.
If you want to receive a flexpage from the server, you will have to set
the IPC flexpage receive window in the client. The Dice generated code
uses the rcv_fpage member in the CORBA_Environment parameter of the
*_call functions to do this. Thus, you have to set this member
appropriately. Per default this member is set to L4_WHOLE_ADDRESS_SPACE
(dice_default_environment).
Thanks for the bug-report, Ron.
--
Mit freundlichen Gruessen / with regards
ra3 @ inf.tu-dresden.de
http://os.inf.tu-dresden.de/~ra3/
Index: be/BEMsgBuffer.cpp
===================================================================
--- be/BEMsgBuffer.cpp (revision 29459)
+++ be/BEMsgBuffer.cpp (working copy)
@@ -1176,6 +1176,42 @@ CBEMsgBuffer::WriteMemberAccess(CBEFile&
}
}
+/** \brief writes the access to a member of a specific type
+ * \param pFile the file to write to
+ * \param pFunction the function to write the member for
+ * \param nType the type of the message buffer struct
+ * \param nFEType the type of the member
+ * \param sIndex the string used as index into the array, not used if empty
+ *
+ * First we look for the specific member and then call the WriteAccess method
+ * with the member.
+ */
+void
+CBEMsgBuffer::WriteMemberAccess(CBEFile& pFile,
+ CBEFunction *pFunction,
+ CMsgStructType nType,
+ int nFEType,
+ string sIndex)
+{
+ // get struct
+ CBEStructType *pStruct = GetStruct(pFunction, nType);
+ assert(pStruct);
+ // iterate members and count to the wanted type (remember: 0-based)
+ vector<CBETypedDeclarator*>::iterator iter;
+ for (iter = pStruct->m_Members.begin();
+ iter != pStruct->m_Members.end();
+ iter++)
+ {
+ if ((*iter)->GetType()->GetFEType() != nFEType)
+ continue;
+
+ WriteAccess(pFile, pFunction, nType, *iter);
+ if (!sIndex.empty())
+ pFile << "[" << sIndex << "]";
+ return;
+ }
+}
+
/** \brief write the access to a member of the generic struct
* \param pFile the file to write to
* \param nIndex the index into the word array of the generic struct
Index: be/l4/L4BEWaitAnyFunction.cpp
===================================================================
--- be/l4/L4BEWaitAnyFunction.cpp (revision 29459)
+++ be/l4/L4BEWaitAnyFunction.cpp (working copy)
@@ -78,6 +78,16 @@ CL4BEWaitAnyFunction::CreateBackEnd(CFEI
string sCurr = sResult;
AddLocalVariable(sDope, sResult, 0, string("{ msgdope: 0 }"));
+
+ // if we have flexible number of flexpages, we need a temporary variable
+ bool bFixedNumberOfFlexpages = true;
+ m_pClass->GetParameterCount(TYPE_FLEXPAGE, bFixedNumberOfFlexpages, DIRECTION_INOUT);
+ if (!bFixedNumberOfFlexpages)
+ {
+ string sTempVar = pNF->GetTempOffsetVariable();
+ string sTempType = pNF->GetTypeName(TYPE_MWORD, false);
+ AddLocalVariable(sTempType, sTempVar, 0);
+ }
}
/** \brief initializes the variables
@@ -561,14 +571,14 @@ void CL4BEWaitAnyFunction::WriteFlexpage
CBESizes *pSizes = CCompiler::GetSizes();
int nSizeFpage = pSizes->GetSizeOfType(TYPE_FLEXPAGE) /
pSizes->GetSizeOfType(TYPE_MWORD);
+ CBETypedDeclarator *pReturn = GetReturnVariable();
+ if (!pReturn)
+ return;
// if fixed number (should be true for only one flexpage as well)
if (bFixedNumberOfFlexpages)
{
// the fixed offset (where to find the opcode) is:
// offset = 8*nMaxNumberOfFlexpages + 8
- CBETypedDeclarator *pReturn = GetReturnVariable();
- if (!pReturn)
- return;
CL4BEMarshaller *pMarshaller =
dynamic_cast<CL4BEMarshaller*>(GetMarshaller());
assert(pMarshaller);
@@ -588,10 +598,10 @@ void CL4BEWaitAnyFunction::WriteFlexpage
// init temp var
++pFile << "\t" << sTempVar << " = 0;\n";
pFile << "\twhile ((";
- pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, 0);
- pFile << "[" << sTempVar << "++] != 0) && (";
- pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, 0);
- pFile << "[" << sTempVar << "++] != 0)) /* empty */;\n";
+ pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, sTempVar);
+ pFile << " != 0) && (";
+ pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, sTempVar + "+1");
+ pFile << " != 0)) " << sTempVar << " += 2;\n";
// now sTempVar points to the delimiter flexpage
// we have to add another 8 bytes to find the opcode, because
@@ -599,7 +609,9 @@ void CL4BEWaitAnyFunction::WriteFlexpage
pFile << "\t/* skip zero fpage */\n";
pFile << "\t" << sTempVar << " += 2;\n";
// now unmarshal opcode
- WriteMarshalReturn(pFile, false);
+ pFile << "\t" << pReturn->m_Declarators.First()->GetName() << " = ";
+ pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, sTempVar);
+ pFile << ";\n";
--pFile << "\t}\n";
}
}
Index: be/BEClass.cpp
===================================================================
--- be/BEClass.cpp (revision 29459)
+++ be/BEClass.cpp (working copy)
@@ -881,26 +881,35 @@ CBEClass::GetParameterCount(int nFEType,
bool& bSameCount,
DIRECTION_TYPE nDirection)
{
- if (nDirection == 0)
+ if (nDirection == DIRECTION_INOUT)
{
// count both and return max
int nCountIn = GetParameterCount(nFEType, bSameCount, DIRECTION_IN);
int nCountOut = GetParameterCount(nFEType, bSameCount, DIRECTION_OUT);
- return (nCountIn > nCountOut) ? nCountIn : nCountOut;
+ return std::max(nCountIn, nCountOut);
}
int nCount = 0, nCurr;
+ CCompiler::Verbose(PROGRAM_VERBOSE_DEBUG,
+ "%s(%d, %s, %d) called: max is %d\n", __func__,
+ nFEType, bSameCount ? "true" : "false", nDirection, nCount);
vector<CBEFunction*>::iterator iter;
for (iter = m_Functions.begin();
iter != m_Functions.end();
iter++)
{
- nCurr = (*iter)->GetParameterCount(nFEType, nDirection);
- if ((nCount > 0) && (nCurr != nCount) && (nCurr > 0))
- bSameCount = false;
- if (nCurr > nCount) nCount = nCurr;
+ nCurr = (*iter)->GetParameterCount(nFEType, nDirection);
+ CCompiler::Verbose(PROGRAM_VERBOSE_DEBUG,
+ "%s: checking %s: has %d parameter of type %d, max is %d\n", __func__,
+ (*iter)->GetName().c_str(), nCurr, nFEType, nCount);
+ if ((nCount > 0) && (nCurr != nCount) && (nCurr > 0))
+ bSameCount = false;
+ nCount = std::max(nCurr, nCount);
}
+ CCompiler::Verbose(PROGRAM_VERBOSE_DEBUG,
+ "%s: returns %d (same %s)\n", __func__,
+ nCount, bSameCount ? "true" : "false");
return nCount;
}
@@ -915,7 +924,7 @@ CBEClass::GetStringParameterCount(DIRECT
ATTR_TYPE nMustAttrs,
ATTR_TYPE nMustNotAttrs)
{
- if (nDirection == 0)
+ if (nDirection == DIRECTION_INOUT)
{
int nStringsIn = GetStringParameterCount(DIRECTION_IN, nMustAttrs,
nMustNotAttrs);
@@ -953,7 +962,7 @@ CBEClass::GetStringParameterCount(DIRECT
*/
int CBEClass::GetSize(DIRECTION_TYPE nDirection)
{
- if (nDirection == 0)
+ if (nDirection == DIRECTION_INOUT)
{
int nSizeIn = GetSize(DIRECTION_IN);
int nSizeOut = GetSize(DIRECTION_OUT);
@@ -2349,7 +2358,7 @@ CBEClass::GetParameterCount(ATTR_TYPE nM
ATTR_TYPE nMustNotAttrs,
DIRECTION_TYPE nDirection)
{
- if (nDirection == 0)
+ if (nDirection == DIRECTION_INOUT)
{
int nCountIn = GetParameterCount(nMustAttrs, nMustNotAttrs,
DIRECTION_IN);
Index: be/BEFunction.cpp
===================================================================
--- be/BEFunction.cpp (revision 29459)
+++ be/BEFunction.cpp (working copy)
@@ -1609,7 +1609,7 @@ CBEFunction::HasVariableSizedParameters(
*/
int CBEFunction::GetParameterCount(int nFEType, DIRECTION_TYPE nDirection)
{
- if (nDirection == 0)
+ if (nDirection == DIRECTION_INOUT)
{
int nCountIn = GetParameterCount(nFEType, DIRECTION_IN);
int nCountOut = GetParameterCount(nFEType, DIRECTION_OUT);
@@ -1630,8 +1630,22 @@ int CBEFunction::GetParameterCount(int n
pType = (*iter)->GetType();
if ((pAttr = (*iter)->m_Attributes.Find(ATTR_TRANSMIT_AS)) != 0)
pType = pAttr->GetAttrType();
- if (pType->IsOfType(nFEType))
- nCount++;
+ if (!pType->IsOfType(nFEType))
+ continue;
+
+ // to catch array parameters, we have to get the maximum size and
+ // divide by the size of the type
+ int nParamSize = 0;
+ CBESizes *pSizes = CCompiler::GetSizes();
+ int nTypeSize = pSizes->GetSizeOfType(nFEType);
+ if ((*iter)->GetMaxSize(nParamSize))
+ nParamSize /= nTypeSize;
+ else
+ nParamSize = 1; // it's variable size, so count it at least once
+ if (nParamSize > 0)
+ nCount += nParamSize;
+ else
+ nCount++;
}
return nCount;
@@ -1648,7 +1662,7 @@ CBEFunction::GetParameterCount(ATTR_TYPE
ATTR_TYPE nMustNotAttrs,
DIRECTION_TYPE nDirection)
{
- if (nDirection == 0)
+ if (nDirection == DIRECTION_INOUT)
{
int nCountIn = GetParameterCount(nMustAttrs, nMustNotAttrs,
DIRECTION_IN);
Index: be/BEMsgBuffer.h
===================================================================
--- be/BEMsgBuffer.h (revision 29459)
+++ be/BEMsgBuffer.h (working copy)
@@ -80,6 +80,8 @@ public: // public methods
CMsgStructType nType, CDeclStack* pStack);
virtual void WriteMemberAccess(CBEFile& pFile, CBEFunction *pFunction,
CMsgStructType nType, int nFEType, int nIndex);
+ virtual void WriteMemberAccess(CBEFile& pFile, CBEFunction *pFunction,
+ CMsgStructType nType, int nFEType, string sIndex);
virtual void WriteGenericMemberAccess(CBEFile& pFile, int nIndex);
void WriteAccessToStruct(CBEFile& pFile, CBEFunction *pFunction,
CMsgStructType nType);