Problem with memmap file with SMP

Steve Bradshaw (steveb@linoox.engr.tachyon.net)
Tue, 13 Jul 1999 10:41:22 -0700


Hello,

The following test program running on an SMP machine does not run consitantly
with the USE_MEMMAP_FILE define set to 1 (using a memory mapped file shared
between two processes). With the USE_MEMMAP_FILE define set to 0 (using a
shared memory segment), it works fine.
What's up with that?

% gcc -O -o x x.c
% ./x 1 &
% ./x <-- may have to run a few of times

The "./x" program modifying sm->value effects the sm->lock value
in the "./x 1" program. Can anyone confirm on other SMP configs?

Dell PowerEdge 6350
500 MHz, Quad PIII Xeon, 256K L2
Linux 2.2.9, Doug Ledford PIII patch 99-04-19

Please CC me in replies.

Thanks,
Steve Bradshaw
steveb@tachyon.net

-----------

#define USE_MEMMAP_FILE 1

#define __SMP__
#include <stdio.h>
#include <asm/bitops.h>

#if USE_MEMMAP_FILE
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#else
#include <sys/shm.h>
#include <asm/page.h>
#endif

#define lock_inuse(plock) test_bit(0, plock)
#define lock_release(plock) clear_bit(0, plock)
#define lock_try(plock) (test_and_set_bit(0, plock) == 0)

typedef struct {
volatile unsigned long lock;
volatile unsigned long value;
} ShMem;

int
main(int argc, char *argv[])
{
ShMem *sm;
int fd;

#if USE_MEMMAP_FILE
{
char *file = "./smfile";
fd = open(file, O_RDWR|O_CREAT, 0664);
if (fd < 0) {
fprintf(stderr, "Unable to open file\n");
exit(1);
}
if (argc > 1) {
static ShMem buf;
write(fd, &buf, sizeof(buf));
}
sm = (void*)mmap(0, sizeof(*sm), PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
if (sm == MAP_FAILED) {
fprintf(stderr, "Unable to memory-map file\n");
close(fd);
exit(1);
}
close(fd);
}
#else
{
int size = (sizeof(*sm) + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
fd = shmget(0x12345678, size, IPC_CREAT|0644);
if (fd < 0) {
fprintf(stderr, "Unable to get shared-memory\n");
exit(1);
}
sm = shmat(fd, 0, 0);
if (sm == (void*)-1) {
fprintf(stderr, "Unable to attach shared-memory\n");
return(0);
}
}
#endif

if (argc > 1) {
/*
* This invocation loops doing lock try/release.
*/
fprintf(stdout, "\nReady..\n");
for (;;) {
if (sm->lock != 0) {
fprintf(stderr, "Lock busy before try!\n");
break;
}
if (lock_try(&sm->lock)) {
if (sm->lock == 0) {
fprintf(stderr, "Lock released after lock!\n");
break;
}
lock_release(&sm->lock);
if (sm->lock != 0) {
fprintf(stderr, "Lock busy after release!\n");
break;
}
}
else {
fprintf(stderr, "Lock busy!\n");
break;
}
}
fprintf(stderr, "\nExit!\n");
}
else {
/*
* This invocation modifies memory and returns.
*/
sm->value++;
}

exit(0);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/