5

I am writing some code around libgpiod's interface. For example, I want to set a line to output high. Under the hood, libgpiod opens an fd provided by the kernel for the line, and then calls ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, ...).

My questions are:

  • Is this particular ioctl() call (with the GPIO_V2... argument) theoretically (potentially) blocking in the same way that writing to an arbitrary file descriptor can be?

  • Are ioctl() calls in general theoretically blocking? For example, requesting the line in the first place also involves an ioctl() on a fd for the chip. What about I2C ioctl()s?

  • If it is blocking, is the underlying fd in the line struct (line->fd_handle->fd) the one I need to wait on in an event loop (eg. epoll() or an abstracted event library like libuv)?

I have tried to answer this question through research, but (a) searching for any combination of "ioctl" and "blocking" just gives results for setting a fd to be blocking or not and (b) it's not in the man pages or kernel docs that I can find.

5
  • 2
    This question leaves me wondering "blocking on what?". Many, or perhaps all, calls to ioctl will use a lock to complete safely. This will usually only make a difference when multiple concurrent calls to ioctl occur from different threads. But typically we don't call that blocking. Usually the term "blocking" means waiting on a particular condition. For example read and recv block until data is available in the buffer. send and write block until enough space is available in the buffer. They don't block until data is sent. What might GPIO_V2_LINE_SET_VALUES_IOCTL block on? Commented Jul 27, 2021 at 21:48
  • 2
    ... hint many types of calls to ioctl don't block because there's nothing for them logically wait for. Commented Jul 27, 2021 at 21:49
  • @PhilipCouling whether they block in practical terms is good to know, but I am looking for something that is more of a documented "contract", if you get my drift. Many calls to write() won't block even with a file open in blocking mode, provided the underlying "thing" is a file on a local filesystem. But I wouldn't put such a write call in an epoll() loop, because it could, theoretically, block the entire loop under some circumstances. This is the contract of eg. epoll() and write() and O_NONBLOCK — I can guarantee that I won't block an event loop if I use them correctly. Commented Jul 28, 2021 at 0:47
  • But I cannot find anything about ioctl() either way: either a documented way to use it that guarantees I won't block an event loop, OR documentation that it may block an event loop so that I can account for this. Commented Jul 28, 2021 at 0:49
  • 2
    Yeah, ioctl is not generally well documented. Effectively each different type of request (different value in request parameter) is a different function. Some better documented than others. Commented Jul 28, 2021 at 8:29

2 Answers 2

3
+25
  1. GPIO_V2_LINE_SET_VALUES_IOCTL seems safe enough; it matches the expected use of ioctl, “manipulat[ing] the underlying device parameters of special files”. It is implemented in linereq_set_values, which acquires a lock, but I don’t think that lock can block for an indefinite amount of time (its users are all non-blocking).

  2. Theoretically, one might expect ioctls to be non-blocking, since they are mostly intended to configure drivers. However, some ioctls do much more than that: for example, FICLONERANGE and FICLONE involve actual I/O, and worse than that, they are supported by some networked file systems such as NFS v4.2, so they could conceivably block indefinitely.

  3. See point 1 above.

1
  • ioctl over NFS. Oh my gods. How is it even possible to write functioning code when such a thing exists. Commented Aug 3, 2021 at 2:45
1

Firstly, the GPIO uAPI ioctl()s are synchronous, that is they will not return until the operation is complete. They are not asynchronous, such that you initiate the operation and wait for a completion notification.

So in response to your third question, there is no fd to wait on for a GPIO uAPI ioctl() to complete - the calling thread will not return from the ioctl() until the operation has completed.

(The readability of the fds in the uAPI is not related to the ioctl()s, but indicates an asynchronous event has occurred, and that the event details can be read from the file. For line request fds that is an edge event. For chip fds it is a change to a line's requested state - has it been requested or released or reconfigured.)

My initial reaction to your first question was that the GPIO uAPI ioctl()s, such as GPIO_V2_LINE_SET_VALUES_IOCTL, are effectively nonblocking. While they may involve mutexes covering shared state, at the end of the day they protect writes to registers controlling the hardware, and those would return almost immediately, so any contention would be fleeting and any overheads would be less than context switching between threads in userspace. Given that, you may as well just call it - even from within an epoll() loop.

For GPIOs hosted directly on SOCs and microcontrollers that is probably true, however for GPIO extender chips connected via I2C, or SPI, or what have you, the ioctl() will not return until the corresponding transaction completes. How long that takes depends on the bus etc, and whether that delay is significant to you depends on your application. It wouldn't block your event loop indefinitely, but it may stall it longer than you would like.

So in response to your first question, if you mean blocking indefinitely then, no they should not block indefinitely. But under some circumstances they could take an appreciable time to complete, and that may be significant to you.

I think that applies to the second question as well. Generally they can be assumed to be nonblocking, but it depends on the specific ioctl() and your application.

1
  • Yeah, there is a kind of "middle level" of blocking vs. non-blocking that we often disregard, where operations might not take an indefinite amount of time (like a network socket read), but can still exhibit a variable delay. I think this falls into that area. Excellent answer, thank you. Commented May 3, 2023 at 2:06

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.