This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug nptl/16882] New: Incorrect implementation of pthread_spin_lock for sparc, no ldstub after spinning


https://sourceware.org/bugzilla/show_bug.cgi?id=16882

            Bug ID: 16882
           Summary: Incorrect implementation of pthread_spin_lock for
                    sparc, no ldstub after spinning
           Product: glibc
           Version: 2.16
            Status: NEW
          Severity: normal
          Priority: P2
         Component: nptl
          Assignee: unassigned at sourceware dot org
          Reporter: a5b at mail dot ru
                CC: drepper.fsp at gmail dot com

I think there is sparc-specific bug introduced by commit 
'Avoid "anonymous" code in pthread_spin_lock' from 3 May 2012
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=e2dbf201abdfa13fc4035a1a8888ecec91bef44c

The bug exists since 2.16 version of glibc.

New version of pthread_spin_lock for sparc64 and sparcv8+ doesn't do "ldstub"
to lock the spinlock, if there were any spins on spinlock, locked by another
thread.

Original implementation of pthread_spin_lock: 

 Try to lock spinlock and return
 if spinlock was locked, go to 2: and spin, waiting spinlock to unlock
 then go to 1: to try lock it


    ("1: ldstub [%0], %%g2\n"
     "   orcc   %%g2, 0x0, %%g0\n"
     "   bne,a  2f\n"
     "   ldub   [%0], %%g2\n"
     ".subsection 2\n"
     "2: orcc   %%g2, 0x0, %%g0\n"
     "   bne,a  2b\n"
     "   ldub   [%0], %%g2\n"
     "   b,a    1b\n"
     ".previous"
     : /* no outputs */
     : "r" (lock)
     : "g2", "memory", "cc");

Code after patch:

 Try to lock spinlock and return
 if spinlock was locked, go to 2: and spin, waiting spinlock to unlock
 then return  

ENTRY(pthread_spin_lock)
       ldstub          [%o0], %g1
       brnz,pn         %g1, 2f
        membar         #StoreLoad | #StoreStore
1:     retl
        mov            0, %o0
2:     ldub            [%o0], %g1
       brnz,pt         %g1, 2b
        membar         #LoadLoad
       ba,a,pt         %xcc, 1b
END(pthread_spin_lock)


With newer code, pthread_spin_lock may return without actually locking the
spinlock. This is incorrect according to The Open Group Base Specifications
Issue 6
http://pubs.opengroup.org/onlinepubs/009695299/functions/pthread_spin_lock.html

> The pthread_spin_lock() function shall lock the spin lock referenced by lock.

I have short test:

$ cat pthread_spin_test.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void* thread(void *arg)
{
    pthread_spinlock_t *lock = (pthread_spinlock_t*) arg;
    printf("Thread started, lock locked by main, value is %08x\n",
*(int*)lock);
    pthread_spin_lock(lock);
    printf("Lock now locked by thread, value is %08x\n", *(int*)lock);
    pthread_spin_unlock(lock);
    printf("Lock now unlocked by thread, value is %08x\n", *(int*)lock);
    return NULL;
}

int main()
{
    pthread_t thr1;
    pthread_spinlock_t lock;
    pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
    printf("Lock created, value is %08x after init\n", *(int*)&lock);
    pthread_spin_lock(&lock);
    printf("Lock locked by main, value is %08x\n", *(int*)&lock);
    pthread_create(&thr1, NULL, thread, (void*)&lock);
    sleep(1);
    pthread_spin_unlock(&lock);
    pthread_join(thr1, NULL);
    return 0;
}

With glibc-2.7 it always outputs 0xFF as value of locked spinlock:

Lock created, value is 00000000 after init
Lock locked by main, value is ff000000
Thread started, lock locked by main, value is ff000000
Lock now locked by thread, value is ff000000
Lock now unlocked by thread, value is 00000000


And with glibc-2.16, spinlock locked by thread has incorrect value 0
(unlocked):

Lock created, value is 00000000 after init
Lock locked by main, value is ff000000
Thread started, lock locked by main, value is ff000000
Lock now locked by thread, value is 00000000       <<<<
Lock now unlocked by thread, value is 00000000


To fix the bug, I think it can be enough to move "1:" label before ldstub in
files
nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S

-- 
You are receiving this mail because:
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]