Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Jul 2001 13:24:53 -0700 (PDT)
From:      Julian Elischer <julian@elischer.org>
To:        Louis-Philippe Gagnon <louisphilippe@macadamian.com>
Cc:        freebsd-hackers@FreeBSD.ORG, Stephane Lussier <stephane@macadamian.com>
Subject:   Re: flock/pthread bug?
Message-ID:  <Pine.BSF.4.21.0107181320030.94740-100000@InterJet.elischer.org>
In-Reply-To: <1f9c01c10fb5$3d4ba770$2964a8c0@macadamian.com>

next in thread | previous in thread | raw e-mail | index | archive | help
probably you should try :

     #define   LOCK_NB        0x04      /* don't block when locking */

Also if you have shared memory, why not use 

/* Get a spin lock, handle recursion inline (as the less common case) */
#define _getlock_spin_block(mtxp, tid, type) ({                         \
        int     _res = MTX_UNOWNED;                                     \
                                                                        \
        __asm __volatile (                                              \
"       pushfl;"                                                        \
"       cli;"                                                           \
"       " MPLOCKED ""                                                   \ 
"       cmpxchgl %3,%1;"                        /* Try */               \
"       jz      2f;"                            /* got it */            \
"       pushl   %4;"                                                    \
"       pushl   %5;"                                                    \
"       call    mtx_enter_hard;" /* mtx_enter_hard(mtxp, type, oflags) */
\ 
"       addl    $12,%%esp;"                                             \
"       jmp     1f;"                                                    \ 
"2:     popl    %2;"                            /* save flags */        \
"1:"                                                                    \
"# getlock_spin_block"                                                  \
        : "+a" (_res),                          /* 0 */                 \
          "+m" (mtxp->mtx_lock),                /* 1 */                 \
          "=m" (mtxp->mtx_savecrit)             /* 2 */                 \
        : "r" (tid),                            /* 3 (input) */         \
          "gi" (type),                          /* 4 */                 \
          "g" (mtxp)                            /* 5 */                 \
        : "cc", "memory", "ecx", "edx"          /* used */ );           \
})


(or similar) taken from -current /sys/i386/include/mutex.h.

the key is the cmpxchgl  instruction.

use the cvsweb interface to explore these 
instructions. (also look at atomic.h I think)


On Wed, 18 Jul 2001, Louis-Philippe Gagnon wrote:

> Hi,
> 
> I've been looking for a way to get inter-process synchronization between multithreaded processes. (I need synchronized access to
> an area of shared memory between multiple instances of the same process)
> 
> Since I was using SysV shared memory, I had first thought of using SysV semaphores for synchronization; however, the functions
> semop, semctl (etc) don't seem to be pthread-aware, so that if a semop() call blocks, the entire process is blocked instead of
> only the calling thread.
> 
> I then looked at the pthread mutexes, but it looks like the FreeBSD implementation doesn't support PTHREAD_PROCESS_SHARED (at
> least in 4.3-release; has this changed in -stable or -current?)
> 
> Then I found out about the flock() function; the man page mentions a different implementation for threaded and non-threaded
> libraries, so I though this would work with pthreads.
> 
> This does not appear to be the case. If one program locks a file with flock(LOCK_EX), the next program that tries to lock will be
> suspended completely, instead of only the calling thread.
> 
> Given this program :
> 
> #include <pthread.h>
> 
> #include <fcntl.h>
> #include <stdio.h>
> #include <sys/file.h>
> 
> void *printf_thread(void *p)
> {
>     while(1)
>         printf("#");
> }
> 
> void main(void)
> {
>     pthread_t t;
>     int fd;
> 
>     fd = open("lockfile",O_WRONLY|O_CREAT, 0666);
>     pthread_create(&t,NULL,printf_thread,NULL);
>     flock(fd,LOCK_EX);
>     pthread_join(t,NULL);
> }
> 
> (program opens a file, launches a thread (which calls printf() endlessly), locks the file and waits for ^C)
> 
> The first instance launched will print an infinity of #'s from its printf_thread
> The second instance (launced from the sae directory, to use the same lock file) will not print anything until the first intance is
> killed. Since the printf_thread is launched before the flock() call, I expected it to keep running while the main thread blocks;
> instead, both threads apear to be blocked.
> 
> (I tried on Linux (RH6.1), the program behaves as I expected)
> 
> I tried another test before this one (don't have the source anymore, I overwrote the same file), which used only one instance of
> the program, with 2 threads trying to lock the file
> I expected something like this :
> thread 1 locks the file
> thread 2 tries to lock the file, blocks
> thread 1 unlocks the file
> thread 2 gets file lock and unblocks
> 
> Instead I got
> thread 1 locks the file
> thread 2 tries to lock the file, whole process blocks
> (thread 1 is blocked, can't unlock the file : deadlock)
> 
> So :
> -Is flock() supposed to block the whole process?
> -Is my test program wrong?
> -Does this look like a bug in libc_r?
> -Is there a better (working) way of getting interprocess synchronization in multithreaded programs?
> 
> Thanks.
> 
> Louis-Philippe Gagnon
> 
> ps. should I submit problem reports immediately in cases like this, or wait for people's opinions first?
> 
> 
> 
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-hackers" in the body of the message
> 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0107181320030.94740-100000>