le_fdMonitor.h

Go to the documentation of this file.
1 /**
2  * @page c_fdMonitor File Descriptor Monitor API
3  *
4  * @subpage 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", 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", 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 #if LE_CONFIG_FD_MONITOR_NAMES_ENABLED
348 //--------------------------------------------------------------------------------------------------
349 /**
350  * Creates a File Descriptor Monitor.
351  *
352  * Creates an object that will monitor a given file descriptor for events.
353  *
354  * The monitoring will be performed by the event loop of the thread that created the Monitor object.
355  * If that thread is blocked, no events will be detected for that file descriptor until that
356  * thread is unblocked and returns to its event loop.
357  *
358  * Events that can be enabled for monitoring:
359  *
360  * - @c POLLIN = Data available to read.
361  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
362  * - @c POLLOUT = Writing to the fd should accept some data now.
363  *
364  * These are bitmask values and can be combined using the bit-wise OR operator ('|').
365  *
366  * The following events are always monitored, even if not requested:
367  *
368  * - @c POLLRDHUP = Other end of stream socket closed or shutdown.
369  * - @c POLLERR = Error occurred.
370  * - @c POLLHUP = Hang up.
371  *
372  * @param[in] name Name of the object (for diagnostics).
373  * @param[in] fd File descriptor to be monitored for events.
374  * @param[in] handlerFunc Handler function.
375  * @param[in] events Initial set of events to be monitored.
376  *
377  * @return
378  * Reference to the object, which is needed for later deletion.
379  *
380  * @note Doesn't return on failure, there's no need to check the return value for errors.
381  */
382 //--------------------------------------------------------------------------------------------------
384 (
385  const char *name,
386  int fd,
387  le_fdMonitor_HandlerFunc_t handlerFunc,
388  short events
389 );
390 #else /* if not LE_CONFIG_FD_MONITOR_NAMES_ENABLED */
391 /// @cond HIDDEN_IN_USER_DOCS
392 //--------------------------------------------------------------------------------------------------
393 /**
394  * Internal function used to implement le_fdMonitor_Create().
395  */
396 //--------------------------------------------------------------------------------------------------
397 le_fdMonitor_Ref_t _le_fdMonitor_Create
398 (
399  int fd,
400  le_fdMonitor_HandlerFunc_t handlerFunc,
401  short events
402 );
403 /// @endcond
404 //--------------------------------------------------------------------------------------------------
405 /**
406  * Creates a File Descriptor Monitor.
407  *
408  * Creates an object that will monitor a given file descriptor for events.
409  *
410  * The monitoring will be performed by the event loop of the thread that created the Monitor object.
411  * If that thread is blocked, no events will be detected for that file descriptor until that
412  * thread is unblocked and returns to its event loop.
413  *
414  * Events that can be enabled for monitoring:
415  *
416  * - @c POLLIN = Data available to read.
417  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
418  * - @c POLLOUT = Writing to the fd should accept some data now.
419  *
420  * These are bitmask values and can be combined using the bit-wise OR operator ('|').
421  *
422  * The following events are always monitored, even if not requested:
423  *
424  * - @c POLLRDHUP = Other end of stream socket closed or shutdown.
425  * - @c POLLERR = Error occurred.
426  * - @c POLLHUP = Hang up.
427  *
428  * @param[in] name Name of the object (for diagnostics).
429  * @param[in] fd File descriptor to be monitored for events.
430  * @param[in] handlerFunc Handler function.
431  * @param[in] events Initial set of events to be monitored.
432  *
433  * @return
434  * Reference to the object, which is needed for later deletion.
435  *
436  * @note Doesn't return on failure, there's no need to check the return value for errors.
437  */
438 //--------------------------------------------------------------------------------------------------
440 (
441  const char *name,
442  int fd,
443  le_fdMonitor_HandlerFunc_t handlerFunc,
444  short events
445 )
446 {
447  LE_UNUSED(name);
448  return _le_fdMonitor_Create(fd, handlerFunc, events);
449 }
450 #endif /* end LE_CONFIG_FD_MONITOR_NAMES_ENABLED */
451 
452 
453 //--------------------------------------------------------------------------------------------------
454 /**
455  * Enables monitoring for events on a file descriptor.
456  *
457  * Events that can be enabled for monitoring:
458  *
459  * - @c POLLIN = Data available to read.
460  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
461  * - @c POLLOUT = Writing to the fd should accept some data now.
462  *
463  * These are bitmask values and can be combined using the bit-wise OR operator ('|').
464  */
465 //--------------------------------------------------------------------------------------------------
467 (
468  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
469  short events ///< [in] Bit map of events.
470 );
471 
472 
473 //--------------------------------------------------------------------------------------------------
474 /**
475  * Disables monitoring for events on a file descriptor.
476  *
477  * Events that can be disabled for monitoring:
478  *
479  * - @c POLLIN = Data available to read.
480  * - @c POLLPRI = Urgent data available to read (e.g., out-of-band data on a socket).
481  * - @c POLLOUT = Writing to the fd should accept some data now.
482  *
483  * These are bitmask values and can be combined using the bit-wise OR operator ('|').
484  */
485 //--------------------------------------------------------------------------------------------------
487 (
488  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
489  short events ///< [in] Bit map of events.
490 );
491 
492 
493 //--------------------------------------------------------------------------------------------------
494 /**
495  * Sets if processing of events on a given fd is deferrable (the system is allowed to go to
496  * sleep while there are monitored events pending for this fd) or urgent (the system will be kept
497  * awake until there are no monitored events waiting to be handled for this fd).
498  *
499  * If the process has @c CAP_EPOLLWAKEUP (or @c CAP_BLOCK_SUSPEND) capability, then fd events are
500  * considered urgent by default.
501  *
502  * If the process doesn't have @c CAP_EPOLLWAKEUP (or @c CAP_BLOCK_SUSPEND) capability, then fd
503  * events are always deferrable, and calls to this function have no effect.
504  */
505 //--------------------------------------------------------------------------------------------------
507 (
508  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
509  bool isDeferrable ///< [in] true (deferrable) or false (urgent).
510 );
511 
512 
513 //--------------------------------------------------------------------------------------------------
514 /**
515  * Sets the Context Pointer for File Descriptor Monitor's handler function. This can be retrieved
516  * by the handler using le_fdMonitor_GetContextPtr() (or le_event_GetContextPtr()) when the handler
517  * function is running.
518  */
519 //--------------------------------------------------------------------------------------------------
521 (
522  le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor.
523  void* contextPtr ///< [in] Opaque context pointer value.
524 );
525 
526 
527 //--------------------------------------------------------------------------------------------------
528 /**
529  * Gets the Context Pointer for File Descriptor Monitor's handler function.
530  *
531  * @return The context pointer set using le_fdMonitor_SetContextPtr(), or NULL if it hasn't been
532  * set.
533  *
534  * @note This only works inside the handler function. The difference between this function and
535  * le_event_GetContextPtr() is that le_fdMonitor_GetContextPtr() will double check that
536  * it's being called inside of a File Descriptor Monitor's handler function.
537  */
538 //--------------------------------------------------------------------------------------------------
540 (
541  void
542 );
543 
544 
545 //--------------------------------------------------------------------------------------------------
546 /**
547  * Gets the file descriptor that an FD Monitor object is monitoring.
548  *
549  * @return The fd.
550  */
551 //--------------------------------------------------------------------------------------------------
553 (
554  le_fdMonitor_Ref_t monitorRef ///< [in] Reference to the File Descriptor Monitor.
555 );
556 
557 
558 //--------------------------------------------------------------------------------------------------
559 /**
560  * Gets a reference to the File Descriptor Monitor whose handler function is currently running.
561  *
562  * @return File Descriptor Monitor reference.
563  *
564  * @note This only works inside the handler function.
565  **/
566 //--------------------------------------------------------------------------------------------------
568 (
569  void
570 );
571 
572 
573 //--------------------------------------------------------------------------------------------------
574 /**
575  * Deletes a file descriptor monitor object.
576  */
577 //--------------------------------------------------------------------------------------------------
579 (
580  le_fdMonitor_Ref_t monitorRef ///< [in] Reference to the File Descriptor Monitor object.
581 );
582 
583 
584 #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)
#define LE_UNUSED(v)
Definition: le_basics.h:379
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)
#define LE_DECLARE_INLINE
Definition: le_basics.h:330