[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug Report?

>>"Rob" == Rob Browning <rlb@cs.utexas.edu> writes:

 Rob> Jeff McWilliams <jjmcwill@yahoo.com> writes:
 >> How about sched_yield?

 Rob> That's exactly what I wanted.  I just didn't know it existed.  I had
 Rob> used "pthread_yield" in the past, but I think it was a hack, and it
 Rob> doesn't exist now.

	pthread_yield existed under draft 4 of the posix threads, but
 was removed in the final draft (10) which became the
 standard. pthread_yield() is not a POSIX thread function. The POSIX
 function to request a scheduler yield is sched_yield, which is part
 of the POSIX priority scheduling option (_POSIX_PRIORITY_SCHEDULING
 is defined in <unistd.h>).

	On the other hand, unless you're targeting a compute-bound threaded
application specifically to a uniprocessor system, I'd suggest avoiding use
of yield at all: it's usually just wasted time.

From: Dave Butenhof <butenhof@zko.dec.com>
Newsgroups: comp.programming.threads
Subject: Re: HPUX10.20 and pthreads - no context switches
Date: Thu, 28 May 1998 08:21:03 -0400
Organization: Digital Equipment Corporation
> Hi,
>     I'm using pthreads on HPUX 10.20 and the aCC C++ compiler.  When I try
> using pthreads, I always need to ask the thread to yield in order to make a
> context switch.
>     The psuedo code is as follows:
> function run(int *threadID) {  // thread origin
>     lock mutex;
>     database query;
>     unlock mutex;
>     yield;
> }
>     AFAIK I shouldn't have to use yield.  I've initialized the threads,
> attribute, and mutex in the main() function.

You haven't asked a question, and you've provided no details to allow me to
determine whether, in your particular case, you might actually gain some
benefit from calling yield. I'll hazard a guess... but first...

In general, you don't need to use yield. In fact, yield may not even do

So why do you want to use it? Presumably, you believe that something you
expect to happen isn't happening unless you call yield. Your belief may or may
not be accurate, and may or may not have anything at all to do with yield.

So... what is your program trying to do? What is it actually doing (pseudo
code, especially incomplete pseudo code of an isolated function, is not a
particularly useful description in most cases)? What do you expect to happen
when you do that? What's actually happening when you don't call yield? What's
actually happening when you do call yield?

My guess is that you're actually executing this pseudo code in a tight loop,
such that the mutex is locked at the top of the loop and unlocked at the
bottom; and that you've got several threads doing this. The result is that the
first such thread to enter the loop unlocks the mutex only across the branch
(and possibly a comparison) from the bottom to the top of the loop. Even on a
multiprocessor, this thread will "monopolize" the mutex until some other
thread happens to "sneak in" during those few instructions. If the thread is
timesliced, it will probably be preempted while holding the mutex, forcing
other threads to wait for it to be scheduled again.

On a uniprocessor, a timeslice will "hardly ever" occur during those few
instructions while the mutex is unlocked. Because HP-UX 10.20 supports only
user-mode "DCE threads", incapable of using multiple processors even when
they're configured, the program is always "uniprocessor".

This (a hot mutex loop, particularly on a uniprocessor) is one of the few
places where a yield call is meaningful. (And even then, there are usually
alternative solutions with lower overhead and better results.) Yield is not "a
context switch". You should think of yield as nothing more than a gentle hint
to the scheduler that "if you're inclined to preempt me, now would be a good
time" -- e.g., while the mutex is unlocked. (Even on a multiprocessor the
yield may help in these cases -- but really only because it adds some cycles
outside the mutex!)

RULE: never code an extended iteration that's 100% (or nearly 100%)
interlocked. Try to balance the locked and unlocked execution so that
threading has a chance to work. I often joke that mutexes were badly named.
They should have been called "bottlenecks" to give people a better idea of
what they do. When you lock a mutex, you're pushing your program through a
deliberate bottleneck. If you're just going to push the whole thing through
the same bottleneck, then creating threads is a waste of time. (Yes, there are
still "functional isolation" benefits to using threads, but I'd question
whether that's often worthwhile if you really don't want ANY concurrency out
of the added synchronization overhead!)

 People seem to think that the blanket phrase, "I only work here,"
 absolves them utterly from any moral obligation in terms of the
 public -- but this was precisely Eichmann's excuse for his job in the
 concentration camps.
Manoj Srivastava  <srivasta@acm.org> <http://www.datasync.com/%7Esrivasta/>
Key C7261095 fingerprint = CB D9 F4 12 68 07 E4 05  CC 2D 27 12 1D F5 E8 6E

Reply to: