2

So, I was looking for random linux manual pages, when I encountered this weird one, you can see it by executing "man unlocked_stdio", or you can view it in your browser by going to this page

So, what is this for? It has weird functions like getc_unlocked, getchar_unlocked, putc_unlocked, putchar_unlocked, and etc, all those functions have one thing in common, they have a FILE stream parameter, I know that all those functions are normal IO functions with a "_unlocked" appended to them, but what does that mean?

Lundin
  • 195,001
  • 40
  • 254
  • 396
dfmaaa1
  • 67
  • 6

1 Answers1

2

It has to do with thread safety.

From your link

Each of these functions has the same behavior as its counterpart without the "_unlocked" suffix, except that they do not use locking (they do not set locks themselves, and do not test for the presence of locks set by others) and hence are thread-unsafe. See flockfile(3).

And from flockfile:

The stdio functions are thread-safe. This is achieved by assigning to each FILE object a lockcount and (if the lockcount is nonzero) an owning thread. For each library call, these functions wait until the FILE object is no longer locked by a different thread, then lock it, do the requested I/O, and unlock the object again.

Some pseudocode that shows how it works. This is not necessarily exactly how it is implemented in reality, but it demonstrates the idea, and clearly shows the difference with the unlocked version. Functionalitywise, the locked version is essentially a wrapper around the unlocked version.

int getchar(void) {

    // Wait until stdinlock is unlocked and then lock it
    // This is an atomic operation
    wait_until_unlocked_and_then_lock(stdinlock);

    // Get the character from stdin
    int ret = getchar_unlocked();

    // Release the lock to make the input stream available to other threads
    unlock(stdinlock);

    // And return the value
    return ret;
}
klutt
  • 30,332
  • 17
  • 55
  • 95
  • So, does that mean two or more threads can't access the same thread, unless the thread currently using it finished its IO operations? So, basically, stdio.h is thread safe, and unlocked_stdio.h isn't? – dfmaaa1 Jun 16 '22 at 09:36
  • @dfmaaa1 Something like that. Your last statement is true. stdio.h is thread safe, and unlocked_stdio.h isn't. – klutt Jun 16 '22 at 09:43
  • I would assume these are used for a minor performance boost in case you know that your program is single-threaded anyway. – Lundin Jun 16 '22 at 09:46
  • @dfmaaa1 I added an example – klutt Jun 16 '22 at 10:01
  • Note that the time to take an uncontested lock is tiny compared to most I/O times. – stark Jun 16 '22 at 11:21
  • @klutt thanks! So, what happens if a function forgets to unlock stdinlock? Other threads will keep waiting? forever? – dfmaaa1 Jun 17 '22 at 08:59
  • @dfmaaa1 Yes. As far as I know that is what will happen. Unless the other thread has implemented a timeout and it skips caring about the lock when the timeout has run out. But the library functions does not have that. It would be very dangerous. – klutt Jun 17 '22 at 09:12
  • @klutt how would you implement a timeout? do something with wait_until_unlocked_and_then_lock(stdinlock)? – dfmaaa1 Jun 17 '22 at 09:16
  • @dfmaaa1 Not sure. Maybe a separate waiting thread or something. But it does not sound like a good idea. At least not if you're going to force access to the resource. But if you just want to output an error message, it's totally fine. – klutt Jun 17 '22 at 09:22
  • I guess one option is to create two threads. One is waiting for unlocking and the other is just a sleep. Then wait until one of those threads has finished and act depending on which one it is. – klutt Jun 17 '22 at 09:23