Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Will Thread blocking in read() leads to process blocking?

4 views
Skip to first unread message

qazmlp

unread,
Jul 16, 2003, 11:23:58 AM7/16/03
to
If one thread is blocking in read() call, can other thread in the same
process run at the same time?
I just want to know, whether blocking in read() call is actually
blocking the whole process.

Thanks!

Måns Rullgård

unread,
Jul 16, 2003, 11:27:32 AM7/16/03
to
qazml...@rediffmail.com (qazmlp) writes:

It depends on your threads implementation. What are you using? POSIX
pthreads does not block the whole process.

--
Måns Rullgård
m...@users.sf.net

Loic Domaigne

unread,
Jul 16, 2003, 6:52:05 PM7/16/03
to
Hi!

> > If one thread is blocking in read() call, can other thread in the same
> > process run at the same time?
> > I just want to know, whether blocking in read() call is actually
> > blocking the whole process.
>
> It depends on your threads implementation. What are you using? POSIX
> pthreads does not block the whole process.


Yes, the outcome depends on the threads implementation. However, it is
incorrect to believe that a POSIX conformant implementation won't
block the whole process. In fact, everything depends on "how much does
the kernel scheduler know about threads".

There is 3 common models for threads implementation:

- "M to 1" or "user space" model: The notion of threads is only known
by the threads library. The threads are scheduled by the library
itself. On the kernel side, the whole MT-process is viewed as "one
process". IOW, the kernel has no notion of "threads". Unless the
library provides some wrappers for the system calls, if one thread
issues a blocking system call, it is likely that the whole process
gets blocked.

- "1 to 1" model: to each thread in the process is a kernel thread
associated with. It that latter case, when a thread blocks in a system
call, only that particular thread goes to the "suspend state". The
other threads get scheduled as normal, and if one is runnable, it will
acquire the CPU. As a result the whole process isn't blocked.

- "M to N" aka "2 level scheduler" model: This is a mix between the
two previous models. M threads are mapped to N kernel threads, with
eventually M > N. This means that a kernel thread might be responsible
for 2 or more threads of the process. The same problem might occurred
as for the "M to 1" model. However, some implementations like Solaris
(a well known two level implementation) use some tricks, in other to
avoid that the all the LWPs mapped to one kernel thread gets blocked.

In conclusion: You can only answer that question if you know the model
implemented by the Pthreads lib, or experiment if you don't. If you
tell us the OS / Pthreads implementation used, this should be
sufficient to give you the exact answer.


HTH,
Loic.

Steve Watt

unread,
Jul 16, 2003, 7:05:28 PM7/16/03
to
In article <3e0374e6.03071...@posting.google.com>,

Loic Domaigne <loic...@gmx.net> wrote:
>Hi!
>
>> > If one thread is blocking in read() call, can other thread in the same
>> > process run at the same time?
>> > I just want to know, whether blocking in read() call is actually
>> > blocking the whole process.
>>
>> It depends on your threads implementation. What are you using? POSIX
>> pthreads does not block the whole process.
>
>
>Yes, the outcome depends on the threads implementation. However, it is
>incorrect to believe that a POSIX conformant implementation won't
>block the whole process. In fact, everything depends on "how much does
>the kernel scheduler know about threads".

Actually, if it's POSIX conformant, a thread absolutely MUST NOT be able
to block the rest of the threads by calling a POSIX API function.

>There is 3 common models for threads implementation:
>
>- "M to 1" or "user space" model: The notion of threads is only known
>by the threads library. The threads are scheduled by the library
>itself. On the kernel side, the whole MT-process is viewed as "one
>process". IOW, the kernel has no notion of "threads". Unless the
>library provides some wrappers for the system calls, if one thread
>issues a blocking system call, it is likely that the whole process
>gets blocked.

If such a library is attempting to be POSIX, it will have provided
wrappers for all such functions.

>- "1 to 1" model: to each thread in the process is a kernel thread
>associated with. It that latter case, when a thread blocks in a system
>call, only that particular thread goes to the "suspend state". The
>other threads get scheduled as normal, and if one is runnable, it will
>acquire the CPU. As a result the whole process isn't blocked.
>
>- "M to N" aka "2 level scheduler" model: This is a mix between the
>two previous models. M threads are mapped to N kernel threads, with
>eventually M > N. This means that a kernel thread might be responsible
>for 2 or more threads of the process. The same problem might occurred
>as for the "M to 1" model. However, some implementations like Solaris
>(a well known two level implementation) use some tricks, in other to
>avoid that the all the LWPs mapped to one kernel thread gets blocked.

Actually, Solaris' current implementation is 1 to 1. It's astonishingly
hard to get MxN thread scheduling working correctly, and Sun finally
stopped trying. This is probably a good thing, in the long run.

>In conclusion: You can only answer that question if you know the model
>implemented by the Pthreads lib, or experiment if you don't. If you
>tell us the OS / Pthreads implementation used, this should be
>sufficient to give you the exact answer.

The only threads package in wide use (that I'm aware of) in which a
single thread can block the whole process is GNU Pth. And there
are even optional wrappers there for most platforms.

It's extremely rare to find such a hopelessly broken thread
implementation (i.e. one that allows such blocking) these days.
--
Steve Watt KD6GGD PP-ASEL-IA ICBM: 121W 56' 57.8" / 37N 20' 14.9"
Internet: steve @ Watt.COM Whois: SW32
Free time? There's no such thing. It just comes in varying prices...

sunil

unread,
Jul 16, 2003, 11:24:32 PM7/16/03
to
loic...@gmx.net (Loic Domaigne) wrote in message news:<3e0374e6.03071...@posting.google.com>...

> Hi!
>
> > > If one thread is blocking in read() call, can other thread in the same
> > > process run at the same time?
> > > I just want to know, whether blocking in read() call is actually
> > > blocking the whole process.
> >
> > It depends on your threads implementation. What are you using? POSIX
> > pthreads does not block the whole process.

>
>
> Yes, the outcome depends on the threads implementation. However, it is
> incorrect to believe that a POSIX conformant implementation won't
> block the whole process. In fact, everything depends on "how much does
> the kernel scheduler know about threads".

Are you sure of this? Because if you see many POSIX compliant thread
library implementations based on M:1 model (FSU Pthreads, GNU pth)
they all seem to provide non-blocking behavior i.e. one thread making
a blocking call allows another thread (if any) to be scheduled. They
either use asynchronous I/O or event demultiplexing mechanism with
select() call at the core so as to achieve non-blocking behavior for
M:1 models. So I am not sure if this is a POSIX requirement or not.
Need to refer to POSIX 1003.1c specification.


>
> There is 3 common models for threads implementation:
>
> - "M to 1" or "user space" model: The notion of threads is only known
> by the threads library. The threads are scheduled by the library
> itself. On the kernel side, the whole MT-process is viewed as "one
> process". IOW, the kernel has no notion of "threads". Unless the
> library provides some wrappers for the system calls, if one thread
> issues a blocking system call, it is likely that the whole process
> gets blocked.

True. If library doesn't take care of this only solution to avoid
blocking is to use asynchronous IO. However standard asynchronous I/O
(glibc) on LINUX is
implemented using threads!

qazmlp

unread,
Jul 17, 2003, 12:15:31 AM7/17/03
to
m...@users.sourceforge.net (Måns Rullgård) wrote in message news:<yw1xvfu2...@users.sourceforge.net>...

I am using pthread library in Solaris.
I hope that makes my question to be unambiguous.

Loic Domaigne

unread,
Jul 17, 2003, 8:32:49 AM7/17/03
to
Hello!

First, I would like to apologize for my previous post that was
partially wrong and added nebulosity instead of answering the question
simply.


So let's start with the simple answer:

> > > [qazmlp wrote ]


> > >
> > > I just want to know, whether blocking in read() call is actually
> > > blocking the whole process.

On most of the modern threads implementations, the answer is "no, it
won't". On a POSIX compliant implementation, you are sure that
blocking a thread shall not "indefinitely" prevent other threads from
executing.


Now let's turn to the complicated development:

> > [Loic Domaigne wrote]

> >
> > Yes, the outcome depends on the threads implementation. However, it is
> > incorrect to believe that a POSIX conformant implementation won't
> > block the whole process. In fact, everything depends on "how much does
> > the kernel scheduler know about threads".

> [ Steve Watt wrote ]


>
> Actually, if it's POSIX conformant, a thread absolutely MUST NOT be able
> to block the rest of the threads by calling a POSIX API function.

Quoting our Pthread Master David Butenhof:

| Although POSIX intends that a thread's blocking operation should not
| prevent other threads from making progress, the actual requirement
| is that a blocking thread shall not "indefinitely" prevent other
| threads from executing.

If I understand correctly, it means that the whole process might be
blocked, but only a finite time. So I guess, the correct answer is
"Pthreads guarantees that the whole process won't be blocked
indefinitely".


> [Sunil wrote]


>
> Are you sure of this? Because if you see many POSIX compliant thread
> library implementations based on M:1 model (FSU Pthreads, GNU pth)
> they all seem to provide non-blocking behavior i.e. one thread making
> a blocking call allows another thread (if any) to be scheduled. They
> either use asynchronous I/O or event demultiplexing mechanism with
> select() call at the core so as to achieve non-blocking behavior for
> M:1 models. So I am not sure if this is a POSIX requirement or not.
> Need to refer to POSIX 1003.1c specification.

In the light of the previous explanations, I think that you are right.
A M:1 model based POSIX implementation _MUST_ ensure that the syscalls
won't block indefinitely (using for instance the technics that you
have described).


I hope that the explanations are now correct...
Improvements/corrections are _ESPECIALLY_ welcome!

Loic.

Patrick TJ McPhee

unread,
Jul 17, 2003, 11:49:51 AM7/17/03
to
In article <db9bbf31.03071...@posting.google.com>,
qazmlp <qazml...@rediffmail.com> wrote:
% m...@users.sourceforge.net (Måns Rullgård) wrote in message
% news:<yw1xvfu2...@users.sourceforge.net>...
% > qazml...@rediffmail.com (qazmlp) writes:
% >
% > > If one thread is blocking in read() call, can other thread in the same
% > > process run at the same time?
% > > I just want to know, whether blocking in read() call is actually
% > > blocking the whole process.
% >
% > It depends on your threads implementation. What are you using? POSIX
% > pthreads does not block the whole process.
%
% I am using pthread library in Solaris.
% I hope that makes my question to be unambiguous.

In this case, blocking in a read() call will not prevent other threads
from running.
--

Patrick TJ McPhee
East York Canada
pt...@interlog.com

David Butenhof

unread,
Jul 23, 2003, 8:36:54 AM7/23/03
to
Steve Watt wrote:

> In article <3e0374e6.03071...@posting.google.com>,
> Loic Domaigne <loic...@gmx.net> wrote:
>>
>>Yes, the outcome depends on the threads implementation. However, it is
>>incorrect to believe that a POSIX conformant implementation won't
>>block the whole process. In fact, everything depends on "how much does
>>the kernel scheduler know about threads".
>
> Actually, if it's POSIX conformant, a thread absolutely MUST NOT be able
> to block the rest of the threads by calling a POSIX API function.

This is critical. Any implementation that allows ANY blocking operation in
one thread to block progress of other threads in the process is NOT "POSIX
threads". It may implement the interfaces, but it's a fake.

>>- "M to N" aka "2 level scheduler" model: This is a mix between the
>>two previous models. M threads are mapped to N kernel threads, with
>>eventually M > N. This means that a kernel thread might be responsible
>>for 2 or more threads of the process. The same problem might occurred
>>as for the "M to 1" model. However, some implementations like Solaris
>>(a well known two level implementation) use some tricks, in other to
>>avoid that the all the LWPs mapped to one kernel thread gets blocked.
>
> Actually, Solaris' current implementation is 1 to 1. It's astonishingly
> hard to get MxN thread scheduling working correctly, and Sun finally
> stopped trying. This is probably a good thing, in the long run.

Yes, it is hard to get M:N working right, though there are real advantages.
(System Software development is not generally dedicated to the principle of
avoiding "hard" problems, after all.) But the history of Sun's trouble with
M:N isn't nearly as much technical as political. Even when developers tried
to address design problems, they weren't allowed. So, yes, giving up on M:N
probably was the best course, for Sun. M:N isn't something that can be done
halfway -- you either commit to the whole thing and follow through, or
you're better off not trying. Unlike Solaris, the Tru64 UNIX M:N scheduling
model was actually designed to work, and does. It (like all else) isn't
perfect, but it scales, it supports detailed and effective debugging, and
it's cleanly and deeply integrated with the kernel.

>>In conclusion: You can only answer that question if you know the model
>>implemented by the Pthreads lib, or experiment if you don't. If you
>>tell us the OS / Pthreads implementation used, this should be
>>sufficient to give you the exact answer.

If it claims to be POSIX threads, and it's possible for a blocking thread to
(in POSIX language) "prevent other threads from making progress", then
that's a BUG. They declared it a bug when they claimed to be POSIX: you
can't have it both ways. If they won't or can't fix the bozo
implementation, choose a real implementation instead. Would you continue to
use a word processor that arbitrarily deleted letters as you typed? Even if
your boss or customer insisted? (Of course, if your answer is "yes", well,
"there you go". ;-) )

--
/--------------------[ David.B...@hp.com ]--------------------\
| Hewlett-Packard Company Tru64 UNIX & VMS Thread Architect |
| My book: http://www.awl.com/cseng/titles/0-201-63392-2/ |
\----[ http://homepage.mac.com/dbutenhof/Threads/Threads.html ]---/

David Butenhof

unread,
Jul 23, 2003, 8:50:13 AM7/23/03
to
Loic Domaigne wrote:

> Quoting our Pthread Master David Butenhof:
>
> | Although POSIX intends that a thread's blocking operation should not
> | prevent other threads from making progress, the actual requirement
> | is that a blocking thread shall not "indefinitely" prevent other
> | threads from executing.
>
> If I understand correctly, it means that the whole process might be
> blocked, but only a finite time. So I guess, the correct answer is
> "Pthreads guarantees that the whole process won't be blocked
> indefinitely".

The word "indefinitely" was specifically inserted, back in 1991 or so, to
avoid completely precluding deployment of early thread libraries that could
not rely on kernel support of any kind. It doesn't really mean much. Or
rather, removing it wouldn't really help anyone without specific latency
metrics. If "not indefinitely" means "immediately", how does one define and
measure "immediate"? On a uniprocessor when one thread blocks on the single
"execution engine", the scheduler needs to locate and dispatch another
thread... that takes measurable time. POSIX deliberately (and over the
objections of the hard realtime folk who comprised the core of the
committee that developed threads) omitted any form of standard performance
metrics for threads, because despite the origin they were chartered to be
general purpose rather than specifically realtime.

The point is simply that you can call ANY blocking operation in a thread and
be absolutely assured that your program won't grind to a screeching halt.
And, in particular, you may READ from a file to which you expect another
thread will eventually WRITE, without any possibility that the
implementation will prevent the WRITE from ever occurring. "Indefinitely"
really only means that there's no formal latency guarantees... and that's
quite appropriate within the scope of a general purpose source level API
specification.

0 new messages