How to block an API call without blocking server message loop?

Valery V. Sedletski _valerius at
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

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 


More information about the l4-hackers mailing list