Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Jul 2001 17:04:26 -0500
From:      y-carden@uniandes.edu.co
To:        hackers@FreeBSD.ORG
Subject:   Re: Invoking a userland function from kernel
Message-ID:  <M2001072617042629945@vaca.uniandes.edu.co>

next in thread | raw e-mail | index | archive | help

> On Wed, 25 Jul 2001 Terry Lambert wrote:

>>y-carden@uniandes.edu.co wrote:
>> 
>> I need pass asynchronously data from kernel
>> to a userland process, include a quantity variable of
>> data (void *opaque).

>The easiest way to do this is to have the user space process
>register a kevent, and then KNOTE() in the kernel when the
>event takes place.

Please, look the question at the bottom of this message.

>You can't; at least, you can't do exactly that.  As others
>have pointed out, you would have better luck telling us what
>problem it is you are trying to solve, and then letting
>people suggest solutions, instead of picking "the one true
>solution", and then asking us how to implement it.

OK, I'm incorporating the Real Time Protocol RTP into the
FreeBSD Kernel.

I took the RTP Lucent Technologies Library that 
provides a high level interface for 
developing applications that make use of the 
Real Time Transport Protocol (RTP) and I changed 
many of the original API library functions 
to kernel systems calls, and it works fine.

Here you look about the original library:
http://www-out.bell-labs.com/project/RTPlib/DOCS/rtp_api.hrml

Now, I need manage Timed Events:

Two RTP related events must occur which are timed. They are: 

1.RTCP (control RTP packages) reports must be sent periodically. 
2.BYE (a control RTP package) packets may be reconsidered for transmission.


To support scheduling, timed events are handled by two functions, 
RTPSchedule() and RTPExecute(). 

The first of these functions is written by the user(user process). 
It is called by the RTP kernel module (originally the library) 
to request scheduling of events at some predetermined time. 

The user is responsible for  writing the function to schedule
the event with whatever mechanism is appropriate for the application.
The second function is part of	the RTP kernel module (originally the
library),
and is to be called upon execution of the timed event. 

The specific formats of the functions are: 

void RTPSchedule(int id, void* opaque, struct timeval *tp);

rtperror RTPExecute(int id, void* opaque);

The RTP kernel module will call RTPSchedule, and pass it the context cid
and an opaque piece of data, opaque. It will also pass the time for
which the scheduled event is to occur, tp. At the appropriate time, 
tp, the application should call RTPExecute, and pass it the opaque 
token provided in the call to RTPSchedule, in addition to the identifier
id. 

This general mechanism allows for the RTP kernel module to schedule
arbitrary
timed events. All information about the nature of the events is kept
internal. The opaque data is used internally to identify particular events.



For example the following simple code would implement 
the RTP Scheduler in the userland process:

/* Maintain a simple queue of events. */

/* An element queue */
struct evt_queue_elt {
int id;
void* event_opaque;
double event_time;
struct evt_queue_elt *next;
};

/* A queue */
static struct evt_queue_elt* evt_queue = NULL;

/* An the kernel would call this RTPSchedule 
function when it needs to schedule an event.
*/
void RTPSchedule(int id, void* opaque, struct timeval *tp)
{
struct evt_queue_elt *elt;

elt = (struct evt_queue_elt *) malloc(sizeof(struct evt_queue_elt));
if (elt == NULL)
return;

elt->id = id;
elt->event_opaque = opaque;
elt->event_time = tv2dbl(*tp);

insert_in_evt_queue(elt); /* Here insert element in queue */

return;
}

/* In other place of the user program ... */

struct evt_queue_elt *next;
gettimeofday(&now_tv, NULL);
now = tv2dbl(now_tv);

while (evt_queue != NULL && evt_queue->event_time <= now) {
/* There is a pending RTP event (currently this means there's
* an RTCP packet to send), so run it. */
RTPExecute(evt_queue->id, evt_queue->event_opaque);
/* Advance the queue */
next = evt_queue->next;
free(evt_queue);
evt_queue = next;
}



/* ----- RTP systemcall RTPExecute() BEGIN ----- */  

#ifndef _SYS_SYSPROTO_H_
struct RTPExecute_args { 
int id ; 
void* opaque ; 
}; 
#endif 

rtperror RTPExecute (p,uap) 
struct proc *p; 
register struct RTPExecute_args *uap; 
{ 
int id ; 
void* opaque ; 
int rtp_error; 
int rtp_retorno;

cid = uap->cid ; 

rtp_error = copyin( uap->opaque , opaque,  sizeof( opaque )); 
if (rtp_error != RTP_OK )  
goto copyin_out; 

/* internal kernel work */  
rtp_retorno = the_RTPExecute_rtp_internal(id, opaque); 

rtp_error = copyout( opaque , uap->opaque , sizeof( opaque )); 
if (rtp_error != RTP_OK )  
goto copyout_out;  

printf("RTPExecute--> Return: %d \n", rtp_retorno );  

p->p_retval[0] = rtp_retorno; 
return rtp_retorno;

copyin_out: 
printf("RTPExecute--> Error at copyin()\n");  
goto bailout; 
copyout_out:
printf("RTPExecute--> Error at copyout()\n");	
bailout: 
p->p_retval[0] = rtp_error; 
return rtp_error;
} 
/* ----- RTP systemcall RTPExecute() END ----- */  


Other internal functions into the kernel like to 
"the_RTPExecute_rtp_internal()" needs to call 
to RTPSchedule() userland function.

So, my original question was: 
Into my kernel code, How I can call to 
RTPSchedule() userland function?

You say me that I can do with kevent() facility.

How I can do it exactly? 

I apologize perhaps the following is stupid, 
but from the user process  I can call kevent()
for a file descriptor and into kernel when I need
call to RTPSchedule() instead I would try for example to write 
to file descriptor to trigger the event.
Can I do this?	
I don't sure but into kernel it can't write 
to file descriptor.


Thanks for your help.



+------------------------------+
YONNY CARDENAS B.	      
Systems Engineer		

Student M.Sc.			
UNIVERSIDAD DE LOS ANDES     

+-------------------------------+
UNIX is BSD, and FreeBSD is an advanced 4.4BSD




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?M2001072617042629945>