select.c

Go to the documentation of this file.
00001 /* $Id: select.c 22311 2005-09-23 12:42:39Z fm3 $ */
00002 /*****************************************************************************/
00003 /**
00004  * \file   dsi/lib/src/select.c
00005  * \brief  Event select implementation.
00006  *
00007  * \date   02/04/2001
00008  * \author Lars Reuther <reuther@os.inf.tu-dresden.de>
00009  */
00010 /*****************************************************************************/
00011 
00012 /* L4/DROPS includes */
00013 #include <l4/sys/types.h>
00014 #include <l4/env/errno.h>
00015 #include <l4/util/macros.h>
00016 #include <l4/thread/thread.h>
00017 #include <l4/semaphore/semaphore.h>
00018 
00019 /* library includes */
00020 #include <l4/dsi/dsi.h>
00021 #include "__event.h"
00022 #include "__stream.h"
00023 #include "__thread.h"
00024 #include "__debug.h"
00025 
00026 /*****************************************************************************
00027  *** global stuff
00028  *****************************************************************************/
00029 
00030 /**
00031  * Select thread arguments 
00032  */
00033 typedef struct dsi_select_thread_arg
00034 {
00035   /* in */
00036   l4_uint32_t         events;  ///< event mask (wait request)
00037   dsi_socket_ref_t *  socket;  ///< component socket reference
00038   l4semaphore_t *     sem;     ///< select semaphore
00039 
00040   /* out */
00041   l4_uint32_t         mask;    ///< event mask set by the component
00042   int                 error;   ///< error code 
00043 } dsi_select_thread_arg_t;
00044 
00045 /*****************************************************************************/
00046 /**
00047  * \brief Select thread 
00048  * \ingroup internal
00049  *
00050  * \param  data          Thread data, pointer to dsi_select_thread_arg struct
00051  */
00052 /*****************************************************************************/ 
00053 static void
00054 __select_thread(void * data)
00055 {
00056   dsi_select_thread_arg_t * args = (dsi_select_thread_arg_t *)data;
00057   l4_int32_t mask;
00058   
00059   LOGdL(DEBUG_SELECT,"signalling thread "l4util_idfmt,
00060         l4util_idstr(args->socket->event_th));
00061   LOGdL(DEBUG_SELECT,"socket %d, events 0x%08x",
00062         args->socket->socket,args->events);
00063 
00064   /* wait for event notification */
00065   mask = dsi_event_wait(args->socket->event_th,args->socket->socket,
00066                         args->events);
00067 
00068   LOGdL(DEBUG_SELECT,"mask = 0x%08x",mask);
00069 
00070   if (mask < 0)
00071     args->error = mask;
00072   else
00073     {
00074       args->mask = mask;
00075       args->error = 0;
00076     }
00077 
00078   /* wakeup client thread */
00079   l4semaphore_up(args->sem);
00080 
00081   /* sleep
00082    * FIXME: implement sleep never in thread lib, for now we just sleep 
00083    *        5 minutes an hope we are destroyed by the client thread 
00084    *        during that time.
00085    */
00086   l4thread_sleep(300000);
00087 }
00088 
00089 /*****************************************************************************/
00090 /**
00091  * \brief Wait for component events.
00092  * \ingroup stream
00093  * 
00094  * \param  sockets       Socket list, the struct must contain:
00095  *                       - \c stream Stream descriptor
00096  *                       - \c component Component (either 
00097  *                                      \c DSI_SEND_COMPONENT or
00098  *                                      \c DSI_RECEIVE_COMPONENT)
00099  *                       - \c event Event mask
00100  * \param  num_sockets   Number of sockets
00101  * \retval events        Event list, it contains all sockets for which an 
00102  *                       event was received, the elements are:
00103  *                       - \c stream    Stream descriptor
00104  *                       - \c component Component
00105  *                       - \c mask      Event mask set by the component
00106  * \retval num_events    Number of sockets for which an event was received.
00107  *      
00108  * \return 0 if one of the events was set by the component, 
00109  *         error code otherwise:
00110  *         - \c -L4_EINVAL     invalid stream descriptor
00111  *         - \c -L4_ENOTHREAD  create select thread failed
00112  *         - \c -L4_EBUSY      someone else already waiting for one of the
00113  *                             events
00114  *         - \c -L4_EIPC       IPC error calling component
00115  *
00116  * Wait for component events. \a sockets contains a list of sockets and
00117  * events masks. For each of these sockets a thread is created with
00118  * dsi_create_select_thread(), which calls the components event signalling
00119  * thread to wait for an event notification.  If the first notification is
00120  * received (it can be immediately if one of the events is already set by
00121  * the component), the event is marked in the socket list, all threads are
00122  * destroyed and the function returns.
00123  */
00124 /*****************************************************************************/ 
00125 int
00126 dsi_stream_select(dsi_select_socket_t *sockets, const int num_sockets,
00127                   dsi_select_socket_t *events, int * num_events)
00128 {
00129   dsi_select_thread_arg_t args[num_sockets];
00130   l4thread_t threads[num_sockets];
00131   l4semaphore_t sem = L4SEMAPHORE_LOCKED;
00132   int i,j,error,ret;
00133   l4thread_t me = l4thread_myself();
00134 
00135   /* setup thread arguments */
00136   for (i = 0; i < num_sockets; i++)
00137     {
00138       if (!dsi_is_valid_stream(sockets[i].stream))
00139         return -L4_EINVAL;
00140 
00141       args[i].events = sockets[i].events;
00142       if (sockets[i].component & DSI_SEND_COMPONENT)    
00143         args[i].socket = &sockets[i].stream->sender.socketref;
00144       else
00145         args[i].socket = &sockets[i].stream->receiver.socketref;
00146       args[i].sem = &sem;
00147       args[i].mask = 0;
00148       args[i].error = 0;
00149     }
00150 
00151   /* start threads */
00152   for (i = 0; i < num_sockets; i++)
00153     {
00154       threads[i] = dsi_create_select_thread(__select_thread, &args[i],
00155                                             me ,i);
00156       if (threads[i] == L4THREAD_INVALID_ID)
00157         {
00158           /* start thread failed, cleanup */
00159           for (j = 0; j < i; j++)
00160             dsi_shutdown_select_thread(threads[j]);
00161           return -L4_ENOTHREAD;
00162         }
00163     }
00164 
00165   /* wait until an event is set by a component */
00166   l4semaphore_down(&sem);
00167 
00168   /* stop all threads, check error codes */
00169   error = 0;
00170   for (i = 0; i < num_sockets; i++)
00171     {
00172       /* shutdown thread */
00173       dsi_shutdown_select_thread(threads[i]);
00174       
00175       /* check error */
00176       error = args[i].error;
00177     }
00178 
00179   if (error)
00180     {
00181       LOG_Error("DSI: select error %d",error);
00182       return error;
00183     }
00184 
00185   /* setup return */
00186   j = 0;
00187   for (i = 0; i < num_sockets; i++)
00188     {
00189       LOGdL(DEBUG_SELECT,"%d, mask=0x%08x, error = %d", 
00190             i, args[i].mask, args[i].error);
00191 
00192       if (args[i].mask)
00193         {
00194           /* create entry in event list */
00195           events[j].stream = sockets[i].stream;
00196           events[j].component = sockets[i].component;
00197           events[j].events = args[i].mask;
00198 
00199           LOGdL(DEBUG_SELECT,"events %08x <= %08x", events[j].events, args[i].mask);
00200           LOGdL(DEBUG_SELECT,"reset 0x%08x at "l4util_idfmt,
00201                 args[i].mask, l4util_idstr(args[i].socket->event_th));
00202           
00203           /* reset events */
00204           ret = dsi_event_reset(args[i].socket->event_th,
00205                                 args[i].socket->socket,args[i].mask);
00206           if (ret)
00207             {
00208               LOG_Error("DSI: reset events failed: %s (%d)",
00209                         l4env_errstr(ret),ret);
00210             }
00211           j++;    
00212         }         
00213     }
00214 
00215   *num_events = j;
00216 
00217   /* done */
00218   return error;
00219 }

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