2009-07-03 12:37:28

by Michal Simek

[permalink] [raw]
Subject: mmap syscall problem

Hi all,

I am trying to solve problem with mmap syscall on Microblaze which I have.
I am running mmap01 test program from LTP. In attachment is hacked
version and inline version is below too.

Here is the simple mmap test description
1. open temp file
2. write there hello word (in my case ABCD\n EFGH\n - for better tracing
0x41424344 0a20 45464748 0a20)
3. then find a place for allocation of mmap
4. before mmap fill this place with A - whole place (0x41 in hex)
5. then called mmap - map file with string to place which was filled by A.
6a. Correct behavior is that this place must contain only the same data
as was in file (not any A chars) (the rest of chars should be zero)
6b. Wrong behavior is that this place contain any (0x41) data - which is
my case

The facts which I know:
1. Problem is not relate with caches - We tried to run in on system
without cache and the problem is the same
2. Microblaze implementation of sys_mmap02 is the same as is for sparc,
blackfin, m68k and others.
Arnd: Anyway maybe worth to move sys_mmap2 to any generic location. What
do you think?

I copy&paste two output of that program. First checking loop show that
there are old data and second that
data are correct from address 0x10026010. Every run I am getting
different values - sometimes

First log
# ./mmap
dummy 0x10005050, addr 0x10026000, sbrk 0x100006c0 0x1000
file size=0x18, first writing addr=0x10026018
0x10026000: 0x41414141
0x10026004: 0x41414141
0x10026008: 0x41414141
0x1002600c: 0x41414141
0x10026010: 0x41414141
0x10026014: 0x41414141
0x10026018: 0x41414141
0x1002601c: 0x41414141
0x10026020: 0x41414141
0x10026024: 0x41414141
0x10026028: 0x41414141
0x1002602c: 0x41414141
0x10026030: 0x41414141
0x10026034: 0x41414141
0x10026038: 0x41414141
------------
0x10026000: 0x41424344
0x10026004: 0x0a204546
0x10026008: 0x47480a20
0x1002600c: 0x626c6120
0x10026010: 0x626c6120
0x10026014: 0x626c610a
0x10026018: 0x11121300
0x1002601c: 0x00000000
0x10026020: 0x00000000
0x10026024: 0x00000000
0x10026028: 0x00000000
0x1002602c: 0x00000000
0x10026030: 0x00000000
0x10026034: 0x00000000
0x10026038: 0x00000000

Second log
# ./mmap
dummy 0x10005050, addr 0x10026000, sbrk 0x100006c0 0x1000
file size=0x18, first writing addr=0x10026018
0x10026000: 0x41414141
0x10026004: 0x41414141
0x10026008: 0x41414141
0x1002600c: 0x41414141
0x10026010: 0x626c6120
0x10026014: 0x626c610a
0x10026018: 0x11121300
0x1002601c: 0x00000000
0x10026020: 0x00000000
0x10026024: 0x00000000
0x10026028: 0x00000000
0x1002602c: 0x00000000
0x10026030: 0x00000000
0x10026034: 0x00000000
0x10026038: 0x00000000
------------
0x10026000: 0x41424344
0x10026004: 0x0a204546
0x10026008: 0x47480a20
0x1002600c: 0x626c6120
0x10026010: 0x626c6120
0x10026014: 0x626c610a
0x10026018: 0x11121300
0x1002601c: 0x00000000
0x10026020: 0x00000000
0x10026024: 0x00000000
0x10026028: 0x00000000
0x1002602c: 0x00000000
0x10026030: 0x00000000
0x10026034: 0x00000000
0x10026038: 0x00000000


If I add any code which do any loop for delay program a little bit -
program passed that's why
I think that my problem could be related with any timing issue.
I tried to run that test on x86 and there is no problem with that test
but doesn't mean that
the problem is not there too (just x86 is much faster than Microblaze)

Do you have any idea what could be wrong?

Thanks for your hints,
Michal


/*
*
* Copyright (c) International Business Machines Corp., 2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

/*
* Test Name: mmap01
*
* Test Description:
* Verify that, mmap() succeeds when used to map a file where size of the
* file is not a multiple of the page size, the memory area beyond the end
* of the file to the end of the page is accessible. Also, verify that
* this area is all zeroed and the modifications done to this area are
* not written to the file.
*
* Expected Result:
* mmap() should succeed returning the address of the mapped region.
* The memory area beyond the end of file to the end of page should be
* filled with zero.
* The changes beyond the end of file should not get written to the file.
*
* Algorithm:
* Setup:
* Setup signal handling.
* Pause for SIGUSR1 if option specified.
* Create temporary directory.
*
* Test:
* Loop if the proper options are given.
* Execute system call
* Check return code, if system call failed (return=-1)
* Log the errno and Issue a FAIL message.
* Otherwise,
* Verify the Functionality of system call
* if successful,
* Issue Functionality-Pass message.
* Otherwise,
* Issue Functionality-Fail message.
* Cleanup:
* Print timing stats if options given
* Delete the temporary directory created.
*
* Usage: <for command-line>
* mmap01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
* where, -c n : Run n copies concurrently.
* -f : Turn off functionality Testing.
* -i n : Execute test n times.
* -I x : Execute test for x seconds.
* -P x : Pause for x seconds between iterations.
* -t : Turn on syscall timing.
*
* HISTORY
* 07/2001 Ported by Wayne Boyer
*
* RESTRICTIONS:
* None.
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdint.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/shm.h>

#define TEMPFILE "mmapfile"

char *TCID = "mmap01"; /* Test program identifier. */
int TST_TOTAL = 1; /* Total number of test cases. */
extern int Tst_count; /* Test Case counter for tst_* routines */
char *addr; /* addr of memory mapped region */
char *dummy; /* dummy string */
size_t page_sz; /* system page size */
size_t file_sz; /* mapped file size */
int fildes; /* file descriptor for tempfile */
char Cmd_buffer[BUFSIZ]; /* command buffer to hold test command */

void setup(); /* Main setup function of test */
void cleanup(); /* cleanup function for the test */

int main(int ac, char **av)
{
int lc; /* loop counter */
char *msg; /* message returned from parse_opts */
int i;
/* Perform global setup for test */
struct stat stat_buf;
char write_buf[] = "ABCD\n EFGH\n"; //41424344

/* Creat a temporary file used for mapping */
if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) {
printf( "open() on %s Failed, errno=%d : %s", TEMPFILE, errno,
strerror(errno));
cleanup();
}

/* Write some data into temporary file */
if (write(fildes, write_buf, strlen(write_buf)) != strlen(write_buf)) {
printf("write() on %s Failed, errno=%d : %s", TEMPFILE, errno,
strerror(errno));
cleanup();
}

/* Get the size of temporary file */
if (stat(TEMPFILE, &stat_buf) < 0) {
printf( "stat() on %s Failed, errno=%d : %s", TEMPFILE, errno,
strerror(errno));
cleanup();
}
file_sz = stat_buf.st_size;

/* Get the system page size */
if ((page_sz = getpagesize()) < 0) {
printf("getpagesize() fails to get system page size");
cleanup();
}

/* Allocate and initialize dummy string of system page size bytes */
if ((dummy = (char *)calloc(page_sz, sizeof(char))) == NULL) {
printf("calloc() failed to allocate space");
cleanup();
}

/*
* Initialize addr to align with the first segment boundary address
* above the break address of the process.
*/
addr = (void *)(((intptr_t) sbrk(0) + (SHMLBA - 1)) & ~(SHMLBA - 1));

printf("dummy 0x%x, addr 0x%x, sbrk 0x%x 0x%x\n", dummy, addr, sbrk,
SHMLBA);

/* Set the break address of the process to the addr plus one
* page size.
*/
if ((intptr_t) sbrk(SHMLBA + page_sz) == -1) {
printf("sbrk(SHMLBA + page_sz) failed");
cleanup();
}

/* Initialize one page region from addr with 'A' */
memset(addr, 'A', page_sz);


#if 0
/* delayed loops */
/* Hera is one loop which read all data which are in addr -> all are
0x41414141 which is correct */
int *test = (int *)addr;

/* +1 caused that I read one word after allocated space */
for( i = 0; i<(page_sz/4 + 1); i++) {
printf("0x%x: 0x%x\n", test, *test);
test++;
}


/* test with printf - on nfs works, on initramfs sometimes failed */
printf("hello\n");

/* test with syscall */
sync();
#endif

/*
* Call mmap to map the temporary file beyond EOF
* with write access.
*/
errno = 0;
addr = mmap(addr, page_sz, PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED | MAP_FIXED, fildes, 0);

/* Check for the return value of mmap() */
if (addr == MAP_FAILED) {
printf("mmap() Failed on %s, errno=%d : %s",
TEMPFILE, errno, strerror(errno));
}


printf("file size=0x%x, first writing addr=0x%x\n", file_sz,
&addr[file_sz]);

/* 1. checking loop after mmap */
/* read fist 15 words mmap memory */
int *file = (int *)addr;
for( i = 0; i<(15); i++) {
printf("0x%x: 0x%08x\n", file, *file);
file++;
}

/*
* Initialize memory beyond file size
*/
addr[file_sz] = 0x11;
addr[file_sz + 1] = 0x12;
addr[file_sz + 2] = 0x13;

/* 2. checking after writing - always is correct */
printf("------------\n");
file = (int *)addr;
for( i = 0; i<(15); i++) {
printf("0x%x: 0x%08x\n", file, *file);
file++;
}

/*
* Synchronize the mapped memory region
* with the file.
*/
if (msync(addr, page_sz, MS_SYNC) != 0) {
printf("msync() failed to "
"synchronize mapped file, error:%d",
errno);
cleanup();
}

/* Create the command which will be executed in the test */
sprintf(Cmd_buffer, "grep XYZ %s > /dev/null", TEMPFILE);


/*
* Now, Search for the pattern 'XYZ' in the
* temporary file. The pattern should not be
* found and the return value should be 1.
*/
if (system(Cmd_buffer) != 0) {
printf("Functionality of mmap() successful");
} else {
printf("Specified pattern found in file");
}




/* Clean up things in case we are looping */
/* Unmap the mapped memory */
if (munmap(addr, page_sz) != 0) {
printf("munmap() fails to unmap the "
"memory, errno=%d", errno);
}




/* Call cleanup() to undo setup done for the test. */
cleanup();
/*NOTREACHED*/ return 0;
} /* End main */

/*
* cleanup() - performs all ONE TIME cleanup for this test at
* completion or premature exit.
* Free the memory allocated to variable.
* Remove the temporary directory created.
*/
void cleanup()
{
/*
* print timing stats if that option was specified.
*/
close(fildes);

/* Free the memory allocated for dummy string */
if (dummy) {
free(dummy);
}
}











--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663


Attachments:
mmap.c (7.60 kB)

2009-07-03 15:03:18

by Arnd Bergmann

[permalink] [raw]
Subject: Re: mmap syscall problem

On Friday 03 July 2009, Michal Simek wrote:

> I am trying to solve problem with mmap syscall on Microblaze which I have.
> I am running mmap01 test program from LTP. In attachment is hacked
> version and inline version is below too.

Does this happen on microblaze-mmu or microblaze-nommu, or both?
The mmap code for the two is very different.

What file system is backing the temporary file?

For -nommu, there are a number of ristrictions from
Documentation/nommu-mmap.txt, in particular, MAP_FIXED is
forbidden, as is PROT_WRITE with regular files.

> Arnd: Anyway maybe worth to move sys_mmap2 to any generic location. What
> do you think?

Yes, that would be good. I actually have a patch for that somewhere in
my playground repository, but it build-breaks some architectures in the
current state. I'm planning to fix that (and do the same for execve
and maybe some of the other remaining arch specific syscalls) at some
point.

Arnd <><

2009-07-06 06:32:25

by Michal Simek

[permalink] [raw]
Subject: Re: mmap syscall problem

Arnd Bergmann wrote:
> On Friday 03 July 2009, Michal Simek wrote:
>
>
>> I am trying to solve problem with mmap syscall on Microblaze which I have.
>> I am running mmap01 test program from LTP. In attachment is hacked
>> version and inline version is below too.
>>
>
> Does this happen on microblaze-mmu or microblaze-nommu, or both?
> The mmap code for the two is very different.
>
For MMU code.

> What file system is backing the temporary file?
>
I tested it on nfs and initramfs.
The behavior on both has the same symptoms but on initramfs is program
much faster
which is presumtive.

If I run that test, 10times or more and see the output. For example
first 4 tests failed the rest
passed. I look at cpu internals and from syscalls/context switch I see
that that 4 tests which failed
are not interrupted. The rest is interrupted and that tests passed. I
have accurate log for it if you want to see that behavior.
Interruption caused that "anything" in kernel give a time to finish any
work which caused that mmap
memory is consistent.
This behavior is seen in my previous email that depends on time when is
listing called.
Is there any part of kernel which should take care about it?

Thanks for any suggestion.


> For -nommu, there are a number of ristrictions from
> Documentation/nommu-mmap.txt, in particular, MAP_FIXED is
> forbidden, as is PROT_WRITE with regular files.
>
This test can'b be run on noMMU.


Michal



>
>
>> Arnd: Anyway maybe worth to move sys_mmap2 to any generic location. What
>> do you think?
>>
>
> Yes, that would be good. I actually have a patch for that somewhere in
> my playground repository, but it build-breaks some architectures in the
> current state. I'm planning to fix that (and do the same for execve
> and maybe some of the other remaining arch specific syscalls) at some
> point.
>
> Arnd <><
>


--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663

2009-07-06 08:05:59

by Arnd Bergmann

[permalink] [raw]
Subject: Re: mmap syscall problem

On Monday 06 July 2009, Michal Simek wrote:
> > Does this happen on microblaze-mmu or microblaze-nommu, or both?
> > The mmap code for the two is very different.
> >
> For MMU code.

Could this be a cache-aliasing problem? If your cache is 'virtually-indexed'
(most architectures are 'physically-indexed'), the kernel may have written
into different parts of the D-cache than what the user space is reading
from. If you have a write-through cache, that can explain why you only
see the stale data at the beginning of the page -- the cache controller
is still busy writing back the data when you start reading it from
DRAM through the cache alias.

If this is your problem, then you need to implement flush_dcache_page()
and other functions that maintain cache consistency. See
Documentation/cachetlb.txt and http://www.linuxjournal.com/article/7105

Arnd <><

2009-07-06 12:07:18

by Michal Simek

[permalink] [raw]
Subject: Re: mmap syscall problem

Arnd Bergmann wrote:
> On Monday 06 July 2009, Michal Simek wrote:
>
>>> Does this happen on microblaze-mmu or microblaze-nommu, or both?
>>> The mmap code for the two is very different.
>>>
>>>
>> For MMU code.
>>
>
> Could this be a cache-aliasing problem? If your cache is 'virtually-indexed'
> (most architectures are 'physically-indexed'), the kernel may have written
> into different parts of the D-cache than what the user space is reading
> from. If you have a write-through cache, that can explain why you only
> see the stale data at the beginning of the page -- the cache controller
> is still busy writing back the data when you start reading it from
> DRAM through the cache alias.
>
I don't think so because we run that test on Microblaze without caches
and test failed too.
I think that this is sufficient test to tell that the problem is not
relate with caches.

Michal

> If this is your problem, then you need to implement flush_dcache_page()
> and other functions that maintain cache consistency. See
> Documentation/cachetlb.txt and http://www.linuxjournal.com/article/7105
>
> Arnd <><
>


--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663

2009-07-06 12:15:19

by Paul Mundt

[permalink] [raw]
Subject: Re: mmap syscall problem

On Mon, Jul 06, 2009 at 02:07:06PM +0200, Michal Simek wrote:
> Arnd Bergmann wrote:
> > On Monday 06 July 2009, Michal Simek wrote:
> >
> >>> Does this happen on microblaze-mmu or microblaze-nommu, or both?
> >>> The mmap code for the two is very different.
> >>>
> >>>
> >> For MMU code.
> >>
> >
> > Could this be a cache-aliasing problem? If your cache is 'virtually-indexed'
> > (most architectures are 'physically-indexed'), the kernel may have written
> > into different parts of the D-cache than what the user space is reading
> > from. If you have a write-through cache, that can explain why you only
> > see the stale data at the beginning of the page -- the cache controller
> > is still busy writing back the data when you start reading it from
> > DRAM through the cache alias.
> >
> I don't think so because we run that test on Microblaze without caches
> and test failed too.
> I think that this is sufficient test to tell that the problem is not
> relate with caches.
>
Not necessarily, even on platforms that manage aliases in hardware
mappings that violate the aliasing constraints can still result in
undefined behaviour, this really depends more on your cache controller
and MMU than anything else. I notice that microblaze sets SHMLBA to
PAGE_SIZE, you may want to see if this test still breaks after bumping it
up to something like PAGE_SIZE * 4.

This is unfortunately one of the areas where what POSIX says is possible
and what hardware can support are at odds (you can look through
arch/sh/mm/mmap.c for a better idea).

2009-07-06 12:54:19

by Michal Simek

[permalink] [raw]
Subject: Re: mmap syscall problem

Paul Mundt wrote:
> On Mon, Jul 06, 2009 at 02:07:06PM +0200, Michal Simek wrote:
>
>> Arnd Bergmann wrote:
>>
>>> On Monday 06 July 2009, Michal Simek wrote:
>>>
>>>
>>>>> Does this happen on microblaze-mmu or microblaze-nommu, or both?
>>>>> The mmap code for the two is very different.
>>>>>
>>>>>
>>>>>
>>>> For MMU code.
>>>>
>>>>
>>> Could this be a cache-aliasing problem? If your cache is 'virtually-indexed'
>>> (most architectures are 'physically-indexed'), the kernel may have written
>>> into different parts of the D-cache than what the user space is reading
>>> from. If you have a write-through cache, that can explain why you only
>>> see the stale data at the beginning of the page -- the cache controller
>>> is still busy writing back the data when you start reading it from
>>> DRAM through the cache alias.
>>>
>>>
>> I don't think so because we run that test on Microblaze without caches
>> and test failed too.
>> I think that this is sufficient test to tell that the problem is not
>> relate with caches.
>>
>>
> Not necessarily, even on platforms that manage aliases in hardware
> mappings that violate the aliasing constraints can still result in
> undefined behaviour, this really depends more on your cache controller
> and MMU than anything else. I notice that microblaze sets SHMLBA to
> PAGE_SIZE, you may want to see if this test still breaks after bumping it
> up to something like PAGE_SIZE * 4.
>
Yes, test still break - behavior is the same. I don't have accurate
information about MMU unit
but I will ask a question about. We are able to turn off cache
controller directly in HW.
> This is unfortunately one of the areas where what POSIX says is possible
> and what hardware can support are at odds (you can look through
> arch/sh/mm/mmap.c for a better idea).
>

Thanks,
Michal


--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663

2009-07-06 14:16:32

by Arnd Bergmann

[permalink] [raw]
Subject: Re: mmap syscall problem

On Monday 06 July 2009, Michal Simek wrote:
>
> > Not necessarily, even on platforms that manage aliases in hardware
> > mappings that violate the aliasing constraints can still result in
> > undefined behaviour, this really depends more on your cache controller
> > and MMU than anything else. I notice that microblaze sets SHMLBA to
> > PAGE_SIZE, you may want to see if this test still breaks after bumping it
> > up to something like PAGE_SIZE * 4.
> >
> Yes, test still break - behavior is the same. I don't have accurate
> information about MMU unit
> but I will ask a question about. We are able to turn off cache
> controller directly in HW.

There may still be a problem with data being queued in some write
buffers that don't get flushed before reading back from another
address.

What happens in a simple user space program that mmaps the same
page to two addresses? Something like

#include <sys/mman.h>
#include <fcntl.h>
int main(void)
{
int fd = open("existing-4k-file", O_RDWR);
char *p1 = mmap(0, 4096, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
char *p2 = mmap(p1 + 4096, 4096, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED, fd, 0);

*p1 = 0xaa; *p2 = 0x55;

return *p1; /* returns 0xaa if broken, 0x55 if correct */
}

Arnd <><

2009-07-06 14:43:57

by Michal Simek

[permalink] [raw]
Subject: Re: mmap syscall problem

Arnd Bergmann wrote:
> On Monday 06 July 2009, Michal Simek wrote:
>
>>> Not necessarily, even on platforms that manage aliases in hardware
>>> mappings that violate the aliasing constraints can still result in
>>> undefined behaviour, this really depends more on your cache controller
>>> and MMU than anything else. I notice that microblaze sets SHMLBA to
>>> PAGE_SIZE, you may want to see if this test still breaks after bumping it
>>> up to something like PAGE_SIZE * 4.
>>>
>>>
>> Yes, test still break - behavior is the same. I don't have accurate
>> information about MMU unit
>> but I will ask a question about. We are able to turn off cache
>> controller directly in HW.
>>
>
> There may still be a problem with data being queued in some write
> buffers that don't get flushed before reading back from another
> address.
>
> What happens in a simple user space program that mmaps the same
> page to two addresses? Something like
>
> #include <sys/mman.h>
> #include <fcntl.h>
> int main(void)
> {
> int fd = open("existing-4k-file", O_RDWR);
> char *p1 = mmap(0, 4096, PROT_READ | PROT_WRITE,
> MAP_SHARED, fd, 0);
> char *p2 = mmap(p1 + 4096, 4096, PROT_READ | PROT_WRITE,
> MAP_SHARED | MAP_FIXED, fd, 0);
>
> *p1 = 0xaa; *p2 = 0x55;
>
I closed fd too.
close(fd);
> return *p1; /* returns 0xaa if broken, 0x55 if correct */
> }
>
# ls -la existing-4k-file
-rw-rw-r-- 1 monstr monstr 4096 Jul 6 2009 existing-4k-file

# ./test-arnd
# echo $?
85
# dd if=existing-4k-file of=/dev/console count=1 2>/dev/null
U#

in file is first char U (0x55) which is IMO correct.

Michal



> Arnd <><
>


--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663

2009-07-06 15:05:59

by Arnd Bergmann

[permalink] [raw]
Subject: Re: mmap syscall problem

On Monday 06 July 2009, Michal Simek wrote:
> > *p1 = 0xaa; *p2 = 0x55;
> >
> I closed fd too.
> close(fd);
> > return *p1; /* returns 0xaa if broken, 0x55 if correct */
> > }

If you close the fd between the assignment and reading
from the pointer again, the test case becomes invalid because of
timing. Closing the fd before the '*p1 = 0xaa' should be fine,
but unnecessary.

I also realized that you might need to mark the pointers
as 'volatile' so that the compiler has to do the operations
in order.

> >
> # ls -la existing-4k-file
> -rw-rw-r-- 1 monstr monstr 4096 Jul 6 2009 existing-4k-file
>
> # ./test-arnd
> # echo $?
> 85

Ok, so inside a single task, this does not happen.

> # dd if=existing-4k-file of=/dev/console count=1 2>/dev/null
> U#
>
> in file is first char U (0x55) which is IMO correct.

Right, though that was not part of the test, I'd expect this in
the file even if the return value was broken.

Arnd <><

2009-07-06 15:19:54

by Michal Simek

[permalink] [raw]
Subject: Re: mmap syscall problem

Arnd Bergmann wrote:
> On Monday 06 July 2009, Michal Simek wrote:
>
>>> *p1 = 0xaa; *p2 = 0x55;
>>>
>>>
>> I closed fd too.
>> close(fd);
>>
>>> return *p1; /* returns 0xaa if broken, 0x55 if correct */
>>> }
>>>
>
> If you close the fd between the assignment and reading
> from the pointer again, the test case becomes invalid because of
> timing. Closing the fd before the '*p1 = 0xaa' should be fine,
> but unnecessary.
>
> I also realized that you might need to mark the pointers
> as 'volatile' so that the compiler has to do the operations
> in order.
>
>
The result are the same. I tried to run mmap test which are in LTP and
only first one failed.

Do you have any ideas what buffer could caused that problems?
>>>
>>>
>> # ls -la existing-4k-file
>> -rw-rw-r-- 1 monstr monstr 4096 Jul 6 2009 existing-4k-file
>>
>> # ./test-arnd
>> # echo $?
>> 85
>>
>
> Ok, so inside a single task, this does not happen.
>
I print output in that task and there is 0x55 too.
>
>> # dd if=existing-4k-file of=/dev/console count=1 2>/dev/null
>> U#
>>
>> in file is first char U (0x55) which is IMO correct.
>>
>
> Right, though that was not part of the test, I'd expect this in
> the file even if the return value was broken.
>
Not in case that mmap is completely broken. This test confirm that mmap
map that fd and is possible to write there.

Thanks,
Michal


> Arnd <><
>


--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663

2009-07-07 00:45:24

by Valdis Klētnieks

[permalink] [raw]
Subject: Re: mmap syscall problem

On Mon, 06 Jul 2009 16:16:11 +0200, Arnd Bergmann said:

> What happens in a simple user space program that mmaps the same
> page to two addresses? Something like
>
> #include <sys/mman.h>
> #include <fcntl.h>
> int main(void)
> {
> int fd = open("existing-4k-file", O_RDWR);
> char *p1 = mmap(0, 4096, PROT_READ | PROT_WRITE,
> MAP_SHARED, fd, 0);
> char *p2 = mmap(p1 + 4096, 4096, PROT_READ | PROT_WRITE,
> MAP_SHARED | MAP_FIXED, fd, 0);
>
> *p1 = 0xaa; *p2 = 0x55;
>
> return *p1; /* returns 0xaa if broken, 0x55 if correct */
> }

Strictly speaking, doesn't that need a barrier of some sort between the two
assignments? I mean, how is gcc supposed to intuit that p1 and p2 alias
each other and it needs to reload *p1 before returning that value?

(And in more complicated code, I could even see the compiler re-ordering those
two assignments, so the in-file value is different as well as the return; value)


Attachments:
(No filename) (226.00 B)