How to block an API call without blocking server message loop?
Valery V. Sedletski
_valerius at mail.ru
Tue Apr 5 05:45:12 CEST 2011
On Mon, 4 Apr 2011 20:23:43 +0200, Adam Lackorzynski wrote:
>
>On Sat Apr 02, 2011 at 12:58:34 +1300, Valery V. Sedletski wrote:
>>
....
>> I feel that these problems have common solutions, but i'm in trouble -- maybe, someone will help
>> with finding these common solutions?
>
>I think the generic solution is to maintain a couple of worker threads
>inside the server and delegate work to them, keeping the main server
>thread responsive. Another solution could be to have a thread per
>client.
>
So, I could imagine, that the server thread, when receiving a message from a client, starts a child, then sends a message to
one of its worker threads, then it blocks on a semaphore (which is local to the server). Then the server loop must continue, but
not respond to the 1st client (which started the 2nd task) until the worker thread unblocks. -- The worker thread unblocks, and answers
to the 1st client (which has been blocked), then it continues.
But how can I tell DICE to not immediately answer the 1st task? -- I checked my IDL methods, and see one of them having the
short *dice_reply;
parameter. -- I found that if it is equal to DICE_REPLY, then the server loop calls marshal function and replies to the client. But if it is
equal to the DICE_NEVER_REPLY, then it doesn't reply. -- Maybe, I can use this feature, but how to force DICE to generate such a
parameter? -- My other IDL methods haven't one... Can I specify some attribute to the method?
>
>On Mon Apr 04, 2011 at 09:22:07 +1300, Valery V. Sedletski wrote:
>> On Sat, 02 Apr 2011 12:58:34 +1300 (MSD), Valery V. Sedletski wrote:
>>
>> >Hi all.
>> >
>> ...
>>
>> I have rethought the problem and, it seems, found the solution -- still block on a semaphore, but not in server stub, but
>> in the client routine which calls the RPC to the server.
>>
>> But the problem remains -- the semaphore is in the server, but need to share it with the client for it to reset it. -- So the next
>> question arises -- how to tell DICE to map the semaphore to the client? -- I have the semaphore in the server, and trying
>> to return it from the RPC to the server. But DICE returns a copy of the semaphore, and not maps it to the client. I try to use
>> the following IDL declaration:
>>
>> APIRET dos_ExecPgm ([out, string,
>> prealloc_client,
>> prealloc_server] char **pObjname,
>> [in] long cbObjname,
>> [in] unsigned long execFlag,
>> [in, string] char *pArg,
>> [in, string] char *pEnv,
>> [in, out] struct _RESULTCODES *pRes,
>> [out, size_is(len), ref,
>> prealloc_client,
>> prealloc_server] l4semaphore_t **tSem,
>> [out] int *len,
>> [in, string] char *pName);
>>
>> -- so, I'm trying to use 'ref' attribute for tSem. But in that case, DICE requires me to specify the array with 'len' parameter. Can I avoid
>> this length parameter? (I must return one l4semaphore_t * value from the IDL method, and get the mapping of original semaphore,
>> not its copy).
>
>I think the l4semaphore was never intented to be used between two
>different tasks. Also, if you would do so, l4semaphore_t must be in
>shared memory between the two tasks, as the structure is for example
>maintaining a counter that is used in the up and down implementations.
>Thus you'd need to map the memory to the task, and have it placed on a
>separate page.
I supposed that DICE can establish a temporary shared memory area around the semaphore, and the counters will update
accordingly. (I used 'ref' attribute beside the semaphore).
> I guess in your situation blocking on a worker thread in
>server could work.
>
But the situation 'out of worker threads' can occur, so 'Denial of service' can occur. -- I heard, L4 has a limitation of 127 threads per task, is it
true?
WBR,
valery
More information about the l4-hackers
mailing list