convenience.c

Go to the documentation of this file.
00001 /* $Id: convenience.c 23331 2005-11-21 09:35:18Z fm3 $ */
00002 /*****************************************************************************/
00003 /**
00004  * \file        dsi/lib/src/convenience.c
00005  *
00006  * \brief       Convinience functions for our poor users.
00007  *
00008  * \date        05/15/2001
00009  * \author      Jork Loeser <jork.loeser@inf.tu-dresden.de>
00010  * 
00011  */
00012 /*****************************************************************************/
00013 
00014 #include <l4/env/errno.h>
00015 #include <l4/sys/types.h>
00016 #include <l4/sys/ipc.h>
00017 #include <l4/thread/thread.h>
00018 #include <l4/log/l4log.h>
00019 
00020 #include <l4/dsi/dsi.h>
00021 #include "__debug.h"
00022 #include "__config.h"
00023 
00024 /****************************************************************************
00025  *
00026  * Threading issues
00027  *
00028  ****************************************************************************/
00029 
00030 /*!
00031  * \brief   Send start message to work thread and wait for ready-notification.
00032  * \ingroup thread
00033  *
00034  * We start the work-thread and wait until it gives an ok..
00035  *
00036  * \param  socket       socket descriptor
00037  * \param  ret_code     (optional) pointer to the return-code provided
00038  *                      by the worker-thread with dsi_thread_worker_started()
00039  * \retval 0            on success
00040  * \retval -DROPS_EIPC  error sending start IPC
00041  *
00042  * The intention of this function is to be used by the creator of a
00043  * socket in conjunction with dsi_thread_worker_wait() used by the
00044  * worker thread. If the creator creates a worker-thread that handles
00045  * the socket, it cannot create the socket prior to the worker-thread,
00046  * because the worker-id is needed for socket-creation. Thus, the
00047  * worker-thread must be created and wait to be notified about the
00048  * socket then.
00049  */
00050 int dsi_thread_start_worker(dsi_socket_t * socket,
00051                             l4_umword_t * ret_code){
00052     int ret;
00053     l4_msgdope_t result;
00054     l4_umword_t d1, *dp;
00055 
00056     dp=ret_code?ret_code:&d1;
00057 
00058     /* send start IPC */
00059     ret = l4_ipc_send(socket->work_th,L4_IPC_SHORT_MSG,(l4_umword_t)socket,0,
00060                            L4_IPC_NEVER,&result);
00061     if (ret) return -L4_EIPC;
00062 
00063     ret = l4_ipc_receive(socket->work_th, L4_IPC_SHORT_MSG,
00064                               dp, &d1, L4_IPC_NEVER, &result);
00065     if(ret) return -L4_EIPC;
00066 
00067     return 0;
00068 }
00069 
00070 
00071 /*!
00072  * \brief   Wait until our parent sends the socket.
00073  * \ingroup thread
00074  *
00075  * \param  socket       will be filled with the socket descriptor
00076  * \retval 0            on success, IPC-error otherwise
00077  *
00078  * This function should be called by a worker-thread after it was created
00079  * by its parent. It informs the caller about the socket to use.
00080  *
00081  * \note This function is only useful in conjunction with
00082  *       dsi_thread_start_worker().
00083  */
00084 int dsi_thread_worker_wait(dsi_socket_t ** socket){
00085     int                 ret;
00086     l4_msgdope_t        result;
00087     l4_umword_t         dw1;
00088     l4_threadid_t       parentid;
00089 
00090     parentid = l4thread_l4_id (l4thread_get_parent ());
00091 
00092     /* wait for start notification */
00093     ret = l4_ipc_receive(parentid,L4_IPC_SHORT_MSG,
00094                               (l4_umword_t *)socket,&dw1,
00095                               L4_IPC_NEVER,&result);
00096     return ret;
00097 }
00098 
00099 /*!
00100  * \brief   Send ready-notification to parent thread.
00101  * \ingroup thread
00102  *
00103  * \param  ret_code     code to be send to the parent
00104  * \retval 0            on success
00105  * \retval -DROPS_EIPC  error sending start IPC
00106  *
00107  * This function should be used by a worker thread to indicate that it
00108  * started. An error-code can be passed to the parent.
00109  */
00110 int dsi_thread_worker_started(int ret_code){
00111     int ret;
00112     l4_msgdope_t result;
00113     l4_threadid_t       parentid;
00114 
00115     parentid = l4thread_l4_id (l4thread_get_parent ());
00116 
00117     /* send start IPC */
00118     ret = l4_ipc_send(parentid,L4_IPC_SHORT_MSG,ret_code,0,
00119                            L4_IPC_NEVER,&result);
00120     if (ret) return -L4_EIPC;
00121     return 0;
00122 }
00123 
00124 
00125 
00126 /****************************************************************************
00127  *
00128  * Default Handlers
00129  *
00130  ****************************************************************************/
00131 
00132 /*!\brief Open-function for use with local sockets
00133  * \ingroup socket
00134  *
00135  * \param cfg           low level stream configuration
00136  * \param ctrl_ds       control area (if invalid, allocate new area)
00137  * \param data_ds       data area
00138  * \param work_id       work thread id
00139  * \param flags         socket flags, see dsi_socket_create()
00140  * \param socket        ptr to a #dsi_socket_t pointer, that will be set to
00141  *                      the newly created socket. Ignored if 0.
00142  * \param comp          ptr to a #dsi_component_t structure, that will be
00143  *                      filled in
00144  *
00145  * This function can be used to create a component with a local socket in it.
00146  * Use this function if your application is endpoint of a communication as
00147  * well.
00148  *
00149  * The start and stop entries in comp will be set to 0. If you want a
00150  * notification of this events, set your own callbacks after calling.
00151  *
00152  * \see dsi_socket_create().
00153  */
00154 int dsi_socket_local_create(dsi_stream_cfg_t cfg,
00155                             l4dm_dataspace_t *ctrl_ds,
00156                             l4dm_dataspace_t *data_ds,
00157                             l4_threadid_t work_id,
00158                             l4_uint32_t flags,
00159                             dsi_socket_t **socket,
00160                             dsi_component_t *comp){
00161 
00162     l4_threadid_t sync= L4_INVALID_ID;
00163     int err;
00164     dsi_socket_t *s;
00165     
00166     if(!socket)socket=&s;
00167     if((err = dsi_socket_create((dsi_jcp_stream_t){}, cfg,
00168                                 ctrl_ds, data_ds, work_id,
00169                                 &sync, flags,
00170                                 socket))!=0){
00171         return err;
00172     }
00173     if((err = dsi_socket_get_ref(*socket, &comp->socketref))!=0){
00174         dsi_socket_close(*socket);
00175         return err;
00176     }
00177     comp->connect = dsi_socket_local_connect;
00178     comp->start = 0;
00179     comp->stop  = dsi_socket_local_stop;
00180     comp->close = dsi_socket_local_close;
00181     return 0;
00182 }
00183 
00184 /*!\brief Close-function for use with local socket refs
00185  * \ingroup socket
00186  *
00187  * This callback can be used for the close-callback in a DSI
00188  * component descriptor (#dsi_component_t) if the socket is a socket in
00189  * the local address space, and no other actions must be performed on
00190  * connecting a socket than to call dsi_socket_close().
00191  *
00192  * \see dsi_socket_connect().
00193  */
00194 int dsi_socket_local_close(dsi_component_t *comp){
00195     int err;
00196     dsi_socket_t *socket;
00197 
00198     if((err = dsi_socket_get_descriptor(comp->socketref.socket,
00199                                         &socket))!=0){
00200         return err;
00201     }
00202     return dsi_socket_close(socket);
00203 }
00204 
00205 /*!\brief Stop-function for use with local socket refs
00206  * \ingroup socket
00207  *
00208  * This callback can be used for the stop-callback in a DSI
00209  * component descriptor (#dsi_component_t) if the socket is a socket in
00210  * the local address space, and no other actions must be performed on
00211  * connecting a socket than to call dsi_socket_stop().
00212  *
00213  * \see dsi_socket_connect().
00214  */
00215 int dsi_socket_local_stop(dsi_component_t *comp){
00216     int err;
00217     dsi_socket_t *socket;
00218 
00219     if((err = dsi_socket_get_descriptor(comp->socketref.socket,
00220                                         &socket))!=0){
00221         return err;
00222     }
00223     return dsi_socket_stop(socket);
00224 }
00225 
00226 /*!\brief Connect-function for use with local socket refs
00227  * \ingroup socket
00228  *
00229  * This callback can be used for the connect-callback in a DSI
00230  * component descriptor (#dsi_component_t) if the socket is a socket in
00231  * the local address space, and no other actions must be performed on
00232  * connecting a socket than to call dsi_socket_connect().
00233  *
00234  * \see dsi_socket_connect().
00235  */
00236 int dsi_socket_local_connect(dsi_component_t *comp,
00237                              dsi_socket_ref_t *remote){
00238     dsi_socket_t *socket;
00239     int ret;
00240 
00241     LOGd_Enter(DEBUG_CONNECT, "id %d -> id %d", comp->socketref.socket,
00242                remote->socket);
00243     if((ret=dsi_socket_get_descriptor(comp->socketref.socket,&socket))!=0)
00244         return ret;
00245     return dsi_socket_connect(socket, remote);
00246 }
00247 

Generated on Wed Apr 11 06:40:13 2012 for DSI - Drops Streaming Interface by  doxygen 1.5.6