[PATCH] arm: align shared memory unconditionally to the SHMLBA boundary
Alexander Kartashov
alekskartashov at parallels.com
Tue Feb 19 01:11:09 EST 2013
Currently IPC SHM works in a strange way on ARM:
the syscall sys_shmat() requires the argument shmaddr
be SHMLBA-aligned (ARM has the macro __ARCH_FORCE_SHMLBA
unconditionally defined) but allocates memory that
isn't SHMLBA-aligned because the value of memory alignment
depends on presense of certain cache aliases.
Such a behavior raises the following problem. Consider
the program:
static int p[2];
static pid_t task2_pid;
static int task1()
{
int task2_status;
int *n;
int shmid;
shmid = shmget(0x94646337, 40960, IPC_CREAT);
if (shmid < 0) {
perror("Failed to get a SHM descriptor");
return 10;
}
n = (int*)shmat(shmid, 0, 0);
if (n == (int*)-1) {
perror("task1: failed to attach the SHM segment");
return 11;
}
*n = MAGIC;
shmdt(n);
if (write(p[1], &n, sizeof(n)) != sizeof(n))
{
perror("task1: failed to send the SHM address");
return 12;
}
if (waitpid(task2_pid, &task2_status, 0) != task2_pid)
{
perror("task2: failed to wait for task2");
return 13;
}
if (!WIFEXITED(task2_status))
{
printf("task1: task2 hasn't exited!\n");
return 14;
}
printf("task1: task2 exited with code %d, "
"the SHM was attached to %p.\n",
WEXITSTATUS(task2_status), n);
return 0;
}
static int task2()
{
int *n = 0;
int res;
void *addr;
int shmid;
shmid = shmget(0x94646337, 40960, IPC_CREAT);
if (shmid < 0) {
perror("Failed to get a SHM descriptor");
return 20;
}
if (read(p[0], &n, sizeof(n)) != sizeof(n))
{
perror("task2: failed to receive the SHM address");
return 21;
}
addr = shmat(shmid, n, 0);
if (addr == (void*)-1)
{
printf("task2: failed to attach the SHM to the address %p: %s\n",
n, strerror(errno));
res = 22;
goto exit_task2;
}
if ((void*)n != addr)
{
printf("task2: the SHM isn't attached where it's expected:"
"expected %p, got %p\n", n, addr);
res = 23;
goto exit_task2;
}
if (*n != MAGIC)
{
printf("task2: *n (%d) isn't %d\n", *n, MAGIC);
res = 24;
goto exit_task2;
}
exit_task2:
shmdt(addr);
return res;
}
int main()
{
int res = 0;
if (pipe(p) < 0)
{
perror("Failed to create a pipe");
return 2;
}
task2_pid = fork();
if (task2_pid)
res = task1();
else
res = task2();
close(p[0]);
close(p[1]);
return res;
}
This program sometimes fails generating the output like that:
root at test:~/shmfail# ./shmfail
task2: failed to attach the SHM to the address 0xb6e3a000: Invalid argument
task1: task2 exited with code 22, the SHM was attached to 0xb6e3a000.
root at test:~/shmfail# ./shmfail
task2: failed to attach the SHM to the address 0xb6e63000: Invalid argument
task1: task2 exited with code 22, the SHM was attached to 0xb6e63000.
and sometimes succeeds:
root at test:~/shmfail# ./shmfail
task1: task2 exited with code 0, the SHM was attached to 0xb6e94000.
The problem is reproducible in the mainstream kernel branch as well as
in a stable (3.7.5) kernel release. The program isn't reproducible on x86_64.
As you can see the program fails when the address returned by
the function shmat() isn't SHMLBA-aligned.
This patch makes file-mmapped memory be unconditionaly
SHMLBA-aligned.
Signed-off-by: Alexander Kartashov <alekskartashov at parallels.com>
CC: Russell King - ARM Linux <linux at arm.linux.org.uk>
CC: Cyrill Gorcunov <gorcunov at openvz.org>
CC: Pavel Emelyanov <xemul at parallels.com>
---
arch/arm/mm/mmap.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 10062ce..eca577e3 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -65,8 +65,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
* We only need to do colour alignment if either the I or D
* caches alias.
*/
- if (aliasing)
- do_align = filp || (flags & MAP_SHARED);
+ do_align = filp || (flags & MAP_SHARED);
/*
* We enforce the MAP_FIXED case.
--
1.7.9.5
More information about the linux-arm-kernel
mailing list