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

Adam Lackorzynski adam at os.inf.tu-dresden.de
Mon Apr 4 20:23:43 CEST 2011


On Sat Apr 02, 2011 at 12:58:34 +1300, Valery V. Sedletski wrote:
> When an L4 server is started, its main thread goes into the server loop and blocks until a message 
> from a client is received. When a message is received, a server loop calls a dispatch function, 
> which calls functions, specific to RPC opcodes. The problem is that if one of these functions is 
> blocked, the whole server loop is blocked.
> 
> In my case, I am implementing an API, which is called by a client program. This API starts a child 
> process, and has an option to block the calling program, until the child is terminated. This API is 
> called DosExecPgm(). So, the client program calls this API, then the API call blocks, and then the 
> child must be executed, and finally, call another API, which is called DosExit(). But when 
> DosExecPgm is called, the server loop is blocked, and it cannot receive a message for calling 
> the next API, DosExit.
> 
> I tried to implement API call blocking using a semaphore. DosExecPgm from a parent process is 
> waiting on the semaphore, and DosExit from a child process reset the semaphore.
> 
> So, the problem is with server loop blocking. So, I thought to make for DosExecPgm a dedicated 
> server loop. which is blocked, but the main server loop continues to execute. But how to correctly 
> make these server loops? There are many API's which can block, so, what can I do if not to 
> dedicate a separate loop for each function? And, if there are many server loops, then there will be 
> many threads executing them, so I must to register each thread on the name server. -- Then how 
> can the calling program determine, which server thread to call for each API?
> 
> 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.


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 guess in your situation blocking on a worker thread in
server could work.



Adam
-- 
Adam                 adam at os.inf.tu-dresden.de
  Lackorzynski         http://os.inf.tu-dresden.de/~adam/




More information about the l4-hackers mailing list