On 05/29/2014 04:12 PM, John Lumby wrote:
Thanks for looking at it!
Date: Thu, 29 May 2014 00:19:33 +0300
From: hlinnakan...@vmware.com
To: johnlu...@hotmail.com; pgsql-hackers@postgresql.org
CC: klaussfre...@gmail.com
Subject: Re: [HACKERS] Extended Prefetching using Asynchronous IO - proposal
and patch
On 05/28/2014 11:52 PM, John Lumby wrote:
The patch seems to assume that you can put the aiocb struct in shared
memory, initiate an asynchronous I/O request from one process, and wait
for its completion from another process. I'm pretty surprised if that
works on any platform.
It works on linux. Actually this ability allows the asyncio implementation to
reduce complexity in one respect (yes I know it looks complex enough) :
it makes waiting for completion of an in-progress IO simpler than for
the existing synchronous IO case,. since librt takes care of the waiting.
specifically, no need for extra wait-for-io control blocks
such as in bufmgr's WaitIO()
[checks]. No, it doesn't work. See attached test program.
It kinda seems to work sometimes, because of the way it's implemented in
glibc. The aiocb struct has a field for the result value and errno, and
when the I/O is finished, the worker thread fills them in. aio_error()
and aio_return() just return the values of those fields, so calling
aio_error() or aio_return() do in fact happen to work from a different
process. aio_suspend(), however, is implemented by sleeping on a
process-local mutex, which does not work from a different process.
Even if it worked on Linux today, it would be a bad idea to rely on it
from a portability point of view. No, the only sane way to make this
work is that the process that initiates an I/O request is responsible
for completing it. If another process needs to wait for an async I/O to
complete, we must use some other means to do the waiting. Like the
io_in_progress_lock that we already have, for the same purpose.
- Heikki
/*
* Test program to test if POSIX aio functions work across processes
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <aio.h>
char *shmem;
void
processA(void)
{
int fd;
struct aiocb *aiocbp = (struct aiocb *) shmem;
char *buf = shmem + sizeof(struct aiocb);
fd = open("aio-shmem-test-file", O_CREAT | O_WRONLY | O_SYNC, S_IRWXU);
if (fd == -1)
{
fprintf(stderr, "open() failed\n");
exit(1);
}
printf("processA starting AIO\n");
strcpy(buf, "foobar");
memset(aiocbp, 0, sizeof(struct aiocb));
aiocbp->aio_fildes = fd;
aiocbp->aio_offset = 0;
aiocbp->aio_buf = buf;
aiocbp->aio_nbytes = strlen(buf);
aiocbp->aio_reqprio = 0;
aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE;
if (aio_write(aiocbp) != 0)
{
fprintf(stderr, "aio_write() failed\n");
exit(1);
}
}
void
processB(void)
{
struct aiocb *aiocbp = (struct aiocb *) shmem;
const struct aiocb * const pl[1] = { aiocbp };
int rv;
printf("waiting for the write to finish in process B\n");
if (aio_suspend(pl, 1, NULL) != 0)
{
fprintf(stderr, "aio_suspend() failed\n");
exit(1);
}
printf("aio_suspend() returned 0\n");
rv = aio_error(aiocbp);
if (rv != 0)
{
fprintf(stderr, "aio_error returned %d: %s\n", rv, strerror(rv));
exit(1);
}
rv = aio_return(aiocbp);
printf("aio_return returned %d\n", rv);
}
int main(int argc, char **argv)
{
int pidB;
shmem = mmap(NULL, sizeof(struct aiocb) + 1000,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
-1, 0);
if (shmem == MAP_FAILED)
{
fprintf(stderr, "mmap() failed\n");
exit(1);
}
#ifdef SINGLE_PROCESS
/* this works */
processA();
processB();
#else
/*
* Start the I/O request in parent process, then fork and try to wait
* for it to finish from the child process. (doesn't work, it will hang
* forever)
*/
processA();
pidB = fork();
if (pidB == -1)
{
fprintf(stderr, "fork() failed\n");
exit(1);
}
if (pidB != 0)
{
/* parent */
wait (pidB);
}
else
{
/* child */
processB();
}
#endif
}
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers