le_fdMonitor.h

Go to the documentation of this file.
1 /**
2  * @page c_fdMonitor File Descriptor Monitor API
3  *
4  * @ref le_fdMonitor.h "API Reference"
5  *
6  * <HR>
7  *
8  * In a POSIX environment, like Linux, file descriptors (fds) are used for most process I/O.
9  * Many components need to be notified when one or more fds are
10  * ready to read from or write to, or if there's an error or hang-up.
11  *
12  *Although it's common to block a thread on a call to @c read(), @c write(),
13  * @c accept(), @c select(), @c poll() (or some variantion of these), if that's done in a thread
14  * shared with other components, the other components won't run when needed. To avoid this, Legato
15  * has methods to monitor fds reporting related events so they won't interfere with other software
16  * sharing the same thread.
17  *
18  * @section c_fdMonitorStartStop Start/Stop Monitoring
19  *
20  * le_fdMonitor_Create() creates a <b> File Descriptor Monitor </b> and starts monitoring an fd.
21  * A handler function and set of events is also provided to le_fdMonitor_Create().
22  *
23  * @code
24  // Monitor for data available to read.
25  le_fdMonitor_Ref_t fdMonitor = le_fdMonitor_Create("Serial Port", // Name for diagnostics
26  fd, // fd to monitor
27  SerialPortHandler, // Handler function
28  POLLIN); // Monitor readability
29  * @endcode
30  *
31  * When an fd no longer needs to be monitored, the File Descriptor Monitor object
32  * is deleted by calling le_fdMonitor_Delete().
33  *
34  * @code
35  *
36  le_fdMonitor_Delete(fdMonitor);
37 
38  * @endcode
39  *
40  * @warning Always delete the Monitor object for an fd <b> before closing the fd </b>. After an
41  * fd is closed, it could get reused for something completely different. If monitoring of
42  * the new fd incarnation is started before the old Monitor object is deleted, deleting
43  * the old Monitor will cause monitoring of the new incarnation to fail.
44  *
45  *
46  * @section c_fdMonitorEvents Event Types
47  *
48  * Events that can be handled:
49  *
50  * - @c POLLIN = Data available to read.
51  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
52  * - @c POLLOUT = Writing to the fd should accept some data now.
53  * - @c POLLRDHUP = Other end of stream socket closed or shutdown.
54  * - @c POLLERR = Error occurred.
55  * - @c POLLHUP = Hang up.
56  *
57  * These are bitmask values and can be combined using the bit-wise OR operator ('|') and tested
58  * for using the bit-wise @e and ('&') operator.
59  *
60  * @note @c POLLRDHUP, @c POLLERR and @c POLLHUP can't be disabled.
61  * Monitoring these events is always enabled as soon as the File Descriptor
62  * Monitor is created regardless of the set of events given to le_fdMonitor_Create().
63  *
64  * @section c_fdTypes FD Types
65  *
66  * The fd type affects how events are monitored:
67  *
68  * - @ref c_fdTypes_files
69  * - @ref c_fdTypes_pipes
70  * - @ref c_fdTypes_sockets
71  * - @ref c_fdTypes_terminals
72  *
73  * @subsection c_fdTypes_files Files
74  *
75  * - POLLIN and POLLOUT are always SET
76  * - NONE of the other EVENTS are ever set
77  *
78  * @subsection c_fdTypes_pipes Pipes
79  *
80  * Pipe fd events indicate two conditions for reading from a pipe and two conditions for writing to
81  * a pipe.
82  *
83  * | | Event | Condition |
84  * | ---------------------| ----------------- | ----------------------------------------------- |
85  * | READING from a pipe | POLLHUP | NO DATA in the pipe and the WRITE END is closed |
86  * | | POLLIN | DATA in the pipe and the WRITE END is open |
87  * | | POLLIN + POLLHUP | DATA in the pipe BUT the WRITE END is closed |
88  * | WRITING to the pipe | POLLERR | NO SPACE in the pipe and the READ END is closed |
89  * | | POLLOUT | SPACE in the pipe and the READ END is open |
90  * | | POLLOUT + POLLERR | SPACE in the pipe BUT the READ END is closed |
91  *
92  * @subsection c_fdTypes_sockets Sockets
93  *
94  * Socket activity (establishing/closing) is monitored for connection-orientated sockets including
95  * SOCK_STREAM and SOCK_SEQPACKET. Input and output data availability for all socket types is
96  * monitored.
97  * | Event | Condition |
98  * | ---------------------------- | ------------------------------------------------------------ |
99  * | POLLIN | Input is available from the socket |
100  * | POLLOUT | Possible to send data on the socket |
101  * | POLLIN | Incoming connection being established on the listen port |
102  * | POLLPRI | Out of band data received only on TCP |
103  * | POLLIN + POLLOUT + POLLRDHUP | Peer closed the connection in a connection-orientated socket |
104  *
105  *
106  * @subsection c_fdTypes_terminals Terminals and Pseudo-Terminals
107  *
108  * Terminals and pseudo-terminals operate in pairs. When one terminal pair closes, an event is
109  * generated to indicate the closure. POLLIN, POLLOUT and POLLPRI are the event indicators related
110  * to terminal status.
111  *
112  * | Event | Condition |
113  * | ------- | --------------------- |
114  * | POLLIN | Ready to receive data |
115  * | POLLOUT | Ready to send data |
116  * | POLLPRI | Master/pseudo terminal detects slave state has changed (in packet mode only). |
117  * | POLLHUP | Either half of the terminal pair has closed. |
118  *
119  *
120  * @section c_fdMonitorHandlers Handler Functions
121  *
122  * Parameters to the fd event handler functions are the fd and the events active for the
123  * fd. The events are passed as a bit mask; the bit-wise AND operator ('&') must be used to
124  * check for specific events.
125  *
126  * @code
127 
128 COMPONENT_INIT
129 {
130  // Open the serial port.
131  int fd = open("/dev/ttyS0", O_RDWR|O_NONBLOCK);
132  LE_FATAL_IF(fd == -1, "open failed with errno %d (%m)", errno);
133 
134  // Create a File Descriptor Monitor object for the serial port's file descriptor.
135  // Monitor for data available to read.
136  le_fdMonitor_Ref_t fdMonitor = le_fdMonitor_Create("Serial Port", // Name for diagnostics
137  fd, // fd to monitor
138  SerialPortHandler, // Handler function
139  POLLIN); // Monitor readability
140 }
141 
142 static void SerialPortHandler(int fd, short events)
143 {
144  if (events & POLLIN) // Data available to read?
145  {
146  char buff[MY_BUFF_SIZE];
147 
148  ssize_t bytesRead = read(fd, buff, sizeof(buff));
149 
150  ...
151  }
152 
153  if ((events & POLLERR) || (events & POLLHUP) || (events & POLLRDHUP)) // Error or hang-up?
154  {
155  ...
156  }
157 }
158 
159  * @endcode
160  *
161  * @section c_fdMonitorEnableDisable Enable/Disable Event Monitoring
162  *
163  * The set of fd events being monitored can be adjusted using le_fdMonitor_Enable()
164  * and le_fdMonitor_Disable(). However, @c POLLRDHUP, @c POLLERR and @c POLLHUP can't be disabled.
165  *
166  * CPU cycles (and power) can be saved by disabling monitoring when not needed.
167  * For example, @c POLLOUT monitoring should be disabled while nothing needs to be written
168  * to the fd, so that the event handler doesn't keep getting called with a @c POLLOUT event
169  * because the fd is writeable.
170  *
171  * @code
172 static void StartWriting()
173 {
174  // Enable monitoring for POLLOUT. When connection is ready, handler will be called.
175  le_fdMonitor_Enable(FdMonitorRef, POLLOUT);
176 }
177 
178 static void ConnectionEventHandler(int fd, int event)
179 {
180  if (event & POLLOUT)
181  {
182  // Connection is ready for us to send some data.
183  le_result_t result = SendWaitingData();
184  if (result == LE_NOT_FOUND)
185  {
186  // Buffer empty, stop monitoring POLLOUT so handler doesn't keep getting called.
187  le_fdMonitor_Disable(le_fdMonitor_GetMonitor(), POLLOUT);
188  }
189  ...
190  }
191  ...
192 }
193  * @endcode
194  *
195  * If an event occurs on an fd while monitoring of that event is disabled,
196  * the event will be ignored. If that event is later enabled, and that event's
197  * trigger condition is still true (e.g., the fd still has data available to be read), then the
198  * event will be reported to the handler at that time. If the event trigger condition is gone
199  * (e.g., the fd no longer has data available to read), then the event will not be reported
200  * until its trigger condition becomes true again.
201  *
202  * If events occur on different fds at the same time, the order in which the handlers
203  * are called is implementation-dependent.
204  *
205  *
206  * @section c_fdMonitorHandlerContext Handler Function Context
207  *
208  * Calling le_fdMonitor_GetMonitor() inside the handler function fetches a reference to the
209  * File Descriptor Monitor object for the event being handled. This is handy to enable and
210  * disable event monitoring from inside the handler.
211  *
212  * If additional data needs to be passed to the handler function, the context pointer can be set
213  * to use le_fdMonitor_SetContextPtr() and retrieved inside the handler function with
214  * le_fdMonitor_GetContextPtr(). le_event_GetContextPtr() can also be used, but
215  * le_fdMonitor_GetContextPtr() is preferred as it double checks it's being called inside
216  * a File Descriptor Monitor's handler function.
217  *
218  * @code
219  *
220  * static void SerialPortHandler(int fd, short events)
221  * {
222  * MyContext_t* contextPtr = le_fdMonitor_GetContextPtr();
223  *
224  * // Process the fd event(s).
225  * ...
226  * }
227  *
228  * static void StartDataTransmission(const char* port, uint8_t* txBuffPtr, size_t txBytes)
229  * {
230  * // Open the serial port.
231  * int fd = open(port, O_RDWR|O_NONBLOCK);
232  * LE_FATAL_IF(fd == -1, "open failed with errno %d (%m)", errno);
233  *
234  * // Create a File Descriptor Monitor object for the serial port's file descriptor.
235  * // Monitor for write buffer space availability.
236  * le_fdMonitor_Ref_t fdMonitor = le_fdMonitor_Create("Port", fd, SerialPortHandler, POLLOUT);
237  *
238  * // Allocate a data block and populate with stuff we need in SerialPortHandler().
239  * MyContext_t* contextPtr = le_mem_ForceAlloc(ContextMemPool);
240  * contextPtr->txBuffPtr = txBuffPtr;
241  * contextPtr->bytesRemaining = txBytes;
242  *
243  * // Make this available to SerialPortHandler() via le_fdMonitor_GetContextPtr().
244  * le_fdMonitor_SetContextPtr(fdMonitor, contextPtr);
245  * }
246  *
247  * @endcode
248  *
249  *
250  * @section c_fdMonitorPowerManagement Power Management
251  *
252  * If your process has the privilege of being able to block the system from going to sleep,
253  * whenever the fd that is being monitored has a pending event, the system will be kept
254  * awake. To allow the system to go to sleep while this fd has a pending event, you can call
255  * le_fdMonitor_SetDeferrable() with @c isDeferrable flag set to 'true'.
256  *
257  *
258  * @section c_fdMonitorThreading Threading
259  *
260  * fd monitoring is performed by the Event Loop of the thread that
261  * created the Monitor object for that fd. If that the is blocked, events
262  * won't be detected for that fd until the thread is unblocked and returns to its
263  * Event Loop. Similarly, if the thread that creates a File Descriptor Monitor object doesn't
264  * run an Event Loop at all, no events will be detected for that fd.
265  *
266  * It's not recommended to monitor the same fd in two threads at the same time, because the threads
267  * will race to handle any events on that fd.
268  *
269  *
270  * @section c_fdMonitorTroubleshooting Troubleshooting
271  *
272  * The "fdMonitor" logging keyword can be enabled to view fd monitoring activity.
273  *
274  * <hr>
275  *
276  * Copyright (C) Sierra Wireless Inc.
277  */
278 
279 //--------------------------------------------------------------------------------------------------
280 /** @file le_fdMonitor.h
281  *
282  * Legato @ref c_fdMonitor include file.
283  *
284  * Copyright (C) Sierra Wireless Inc.
285  */
286 
287 #ifndef LEGATO_FDMONITOR_INCLUDE_GUARD
288 #define LEGATO_FDMONITOR_INCLUDE_GUARD
289 
290 
291 //--------------------------------------------------------------------------------------------------
292 /**
293  * File Descriptor Monitor reference.
294  *
295  * Used to refer to File Descriptor Monitor objects.
296  */
297 //--------------------------------------------------------------------------------------------------
298 typedef struct le_fdMonitor* le_fdMonitor_Ref_t;
299 
300 
301 //--------------------------------------------------------------------------------------------------
302 /**
303  * Prototype for file descriptor event handler functions.
304  *
305  * Events that can be received:
306  *
307  * - @c POLLIN = Data available to read.
308  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
309  * - @c POLLOUT = Writing to the fd should accept some data now.
310  * - @c POLLRDHUP = Other end of stream socket closed or shutdown.
311  * - @c POLLERR = Error occurred.
312  * - @c POLLHUP = Hang up.
313  *
314  * These are bitmask values that may appear in the @c events parameter. Use the bit-wise AND
315  * operator ('&') to test for specific events.
316  *
317  * @code
318  *
319  * if (events & POLLIN)
320  * {
321  * // Data available to read.
322  * ...
323  * }
324  *
325  * if (events & POLLERR)
326  * {
327  * // An error occured.
328  * ...
329  * }
330  *
331  * ...
332  *
333  * @endcode
334  *
335  * @param fd [in] File descriptor.
336  *
337  * @param events [in] Bit map of events that occurred. Use bitwise AND ('&') to test for events.
338  */
339 //--------------------------------------------------------------------------------------------------
340 typedef void (*le_fdMonitor_HandlerFunc_t)
341 (
342  int fd,
343  short events
344 );
345 
346 
347 //--------------------------------------------------------------------------------------------------
348 /**
349  * Creates a File Descriptor Monitor.
350  *
351  * Creates an object that will monitor a given file descriptor for events.
352  *
353  * The monitoring will be performed by the event loop of the thread that created the Monitor object.
354  * If that thread is blocked, no events will be detected for that file descriptor until that
355  * thread is unblocked and returns to its event loop.
356  *
357  * Events that can be enabled for monitoring:
358  *
359  * - @c POLLIN = Data available to read.
360  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
361  * - @c POLLOUT = Writing to the fd should accept some data now.
362  *
363  * These are bitmask values and can be combined using the bit-wise OR operator ('|').
364  *
365  * The following events are always monitored, even if not requested:
366  *
367  * - @c POLLRDHUP = Other end of stream socket closed or shutdown.
368  * - @c POLLERR = Error occurred.
369  * - @c POLLHUP = Hang up.
370  *
371  * @return
372  * Reference to the object, which is needed for later deletion.
373  *
374  * @note Doesn't return on failure, there's no need to check the return value for errors.
375  */
376 //--------------------------------------------------------------------------------------------------
378 (
379  const char* name, ///< [in] Name of the object (for diagnostics).
380  int fd, ///< [in] File descriptor to be monitored for events.
381  le_fdMonitor_HandlerFunc_t handlerFunc, ///< [in] Handler function.
382  short events ///< [in] Initial set of events to be monitored.
383 );
384 
385 
386 //--------------------------------------------------------------------------------------------------
387 /**
388  * Enables monitoring for events on a file descriptor.
389  *
390  * Events that can be enabled for monitoring:
391  *
392  * - @c POLLIN = Data available to read.
393  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
394  * - @c POLLOUT = Writing to the fd should accept some data now.
395  *
396  * These are bitmask values and can be combined using the bit-wise OR operator ('|').
397  */
398 //--------------------------------------------------------------------------------------------------
400 (
401  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
402  short events ///< [in] Bit map of events.
403 );
404 
405 
406 //--------------------------------------------------------------------------------------------------
407 /**
408  * Disables monitoring for events on a file descriptor.
409  *
410  * Events that can be disabled for monitoring:
411  *
412  * - @c POLLIN = Data available to read.
413  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
414  * - @c POLLOUT = Writing to the fd should accept some data now.
415  *
416  * These are bitmask values and can be combined using the bit-wise OR operator ('|').
417  */
418 //--------------------------------------------------------------------------------------------------
420 (
421  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
422  short events ///< [in] Bit map of events.
423 );
424 
425 
426 //--------------------------------------------------------------------------------------------------
427 /**
428  * Sets if processing of events on a given fd is deferrable (the system is allowed to go to
429  * sleep while there are monitored events pending for this fd) or urgent (the system will be kept
430  * awake until there are no monitored events waiting to be handled for this fd).
431  *
432  * If the process has @c CAP_EPOLLWAKEUP (or @c CAP_BLOCK_SUSPEND) capability, then fd events are
433  * considered urgent by default.
434  *
435  * If the process doesn't have @c CAP_EPOLLWAKEUP (or @c CAP_BLOCK_SUSPEND) capability, then fd
436  * events are always deferrable, and calls to this function have no effect.
437  */
438 //--------------------------------------------------------------------------------------------------
440 (
441  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
442  bool isDeferrable ///< [in] true (deferrable) or false (urgent).
443 );
444 
445 
446 //--------------------------------------------------------------------------------------------------
447 /**
448  * Sets the Context Pointer for File Descriptor Monitor's handler function. This can be retrieved
449  * by the handler using le_fdMonitor_GetContextPtr() (or le_event_GetContextPtr()) when the handler
450  * function is running.
451  */
452 //--------------------------------------------------------------------------------------------------
454 (
455  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor.
456  void* contextPtr ///< [in] Opaque context pointer value.
457 );
458 
459 
460 //--------------------------------------------------------------------------------------------------
461 /**
462  * Gets the Context Pointer for File Descriptor Monitor's handler function.
463  *
464  * @return The context pointer set using le_fdMonitor_SetContextPtr(), or NULL if it hasn't been
465  * set.
466  *
467  * @note This only works inside the handler function. The difference between this function and
468  * le_event_GetContextPtr() is that le_fdMonitor_GetContextPtr() will double check that
469  * it's being called inside of a File Descriptor Monitor's handler function.
470  */
471 //--------------------------------------------------------------------------------------------------
473 (
474  void
475 );
476 
477 
478 //--------------------------------------------------------------------------------------------------
479 /**
480  * Gets the file descriptor that an FD Monitor object is monitoring.
481  *
482  * @return The fd.
483  */
484 //--------------------------------------------------------------------------------------------------
486 (
487  le_fdMonitor_Ref_t monitorRef ///< [in] Reference to the File Descriptor Monitor.
488 );
489 
490 
491 //--------------------------------------------------------------------------------------------------
492 /**
493  * Gets a reference to the File Descriptor Monitor whose handler function is currently running.
494  *
495  * @return File Descriptor Monitor reference.
496  *
497  * @note This only works inside the handler function.
498  **/
499 //--------------------------------------------------------------------------------------------------
501 (
502  void
503 );
504 
505 
506 //--------------------------------------------------------------------------------------------------
507 /**
508  * Deletes a file descriptor monitor object.
509  */
510 //--------------------------------------------------------------------------------------------------
512 (
513  le_fdMonitor_Ref_t monitorRef ///< [in] Reference to the File Descriptor Monitor object.
514 );
515 
516 
517 #endif // LEGATO_FDMONITOR_INCLUDE_GUARD
void le_fdMonitor_Delete(le_fdMonitor_Ref_t monitorRef)
void le_fdMonitor_SetDeferrable(le_fdMonitor_Ref_t monitorRef, bool isDeferrable)
le_fdMonitor_Ref_t le_fdMonitor_Create(const char *name, int fd, le_fdMonitor_HandlerFunc_t handlerFunc, short events)
int le_fdMonitor_GetFd(le_fdMonitor_Ref_t monitorRef)
struct le_fdMonitor * le_fdMonitor_Ref_t
Definition: le_fdMonitor.h:298
le_fdMonitor_Ref_t le_fdMonitor_GetMonitor(void)
void(* le_fdMonitor_HandlerFunc_t)(int fd, short events)
Definition: le_fdMonitor.h:341
void le_fdMonitor_SetContextPtr(le_fdMonitor_Ref_t monitorRef, void *contextPtr)
void * le_fdMonitor_GetContextPtr(void)
void le_fdMonitor_Disable(le_fdMonitor_Ref_t monitorRef, short events)
void le_fdMonitor_Enable(le_fdMonitor_Ref_t monitorRef, short events)