- To: libc-gnats at gnu dot org, gnats-admin at gnu dot org
- Subject: libc/2223: _pthread_lock sometimes spins uselessly
- From: aegl at unix-os dot sc dot intel dot com
- Date: Mon, 30 Apr 2001 14:05:02 -0400
- Delivery-date: Mon, 30 Apr 2001 20:44:01 +0200
- Envelope-to: aj@localhost
- Reply-To: aegl at unix-os dot sc dot intel dot com
- Xref: gromit.rhein-neckar.de mail.gnats-libc-bugs:5949
>Number: 2223
>Category: libc
>Synopsis: _pthread_lock sometimes spins uselessly
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: libc-gnats
>State: open
>Quarter:
>Keywords:
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Mon Apr 30 14:05:01 -0400 2001
>Cases:
>Originator: Tony Luck
>Release: libc-2.2.1
>Organization:
Intel
>Environment:
machine: 2-cpu ia64
os: linux 2.4.3
Host type: ia64-redhat-linux-gnu
System: Linux selsey.sc.intel.com 2.4.3 #3 SMP Thu Apr 19 16:31:11 PDT 2001 ia64 unknown
Architecture: ia64
Addons: c_stubs linuxthreads
Build CFLAGS: -DNDEBUG=1 -g -O3
Build CC: gcc
Compiler version: 2.96-ia64-000717 snap 001117
Kernel headers: 2.4.0-0.99.11
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio
>Description:
The "__status" field of the _pthread_fastlock structure is not
declared with volatile storage type. Thus the compiler may
optimize references to this location outside the loop in
_pthread_lock, causing the processor to spin checking the value
in a register, instead of in memory.
>How-To-Repeat:
Run 3 copies of this program on a 4-way machine. Observe %CPU using
"top" and notice that sometimes one process of a pair will consume
100% of a cpu, while its partner gets zero cpu time.
/*
* how fast can we context switch?
*/
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
sem_t s1, s2;
volatile unsigned long pingloops;
void *ping(void *a)
{
for (;;) {
pingloops++;
sem_wait(&s1);
sem_post(&s2);
}
}
void *pong(void *a)
{
for (;;) {
sem_wait(&s2);
sem_post(&s1);
}
}
int
main(int argc, char **argv)
{
pthread_t tid;
struct timeval now, then;
unsigned long lastloops;
double sec;
sem_init(&s1, 0, 1);
sem_init(&s2, 0, 0);
pthread_create(&tid, NULL, ping, NULL);
pthread_create(&tid, NULL, pong, NULL);
gettimeofday(&then, 0);
lastloops = pingloops;
for (;;) {
sleep(5);
gettimeofday(&now, 0);
sec = (now.tv_sec - then.tv_sec) +
(now.tv_usec - then.tv_usec) / 1.0e6;
printf("loopspersec=%.1f\n", (pingloops-lastloops)/sec);
then = now;
lastloops = pingloops;
}
return 0;
}
>Fix:
In linuxthreads/sysdeps/pthread/bits/pthreadtypes.h make the __status
element of the _pthread_fastlock structure volatile.