mirror of https://gitee.com/Nocallback/glibc.git
Browse Source
(struct waitlist): Don't add cond. * sysdeps/pthread/aio_notify.c [!DONT_USE_BOOTSTRAP_MAP] (__aio_notify): Use AIO_MISC_NOTIFY instead of pthread_cond_signal. * sysdeps/pthread/aio_suspend.c [!DONT_USE_BOOTSTRAP_MAP]: Don't use condvar, use AIO_MISC_WAIT. * sysdeps/pthread/lio_listio.c: Likewise. * rt/Makefile (tests): Add aio_suspend. * rt/tst-aio9.c: New file.cvs/glibc-2_5-branch
11 changed files with 312 additions and 19 deletions
@ -0,0 +1,73 @@ |
|||
/* Copyright (C) 2006 Free Software Foundation, Inc.
|
|||
This file is part of the GNU C Library. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
The GNU C Library 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 |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with the GNU C Library; if not, write to the Free |
|||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
|||
02111-1307 USA. */ |
|||
|
|||
/* We define a special synchronization primitive for AIO. POSIX
|
|||
conditional variables would be ideal but the pthread_cond_*wait |
|||
operations do not return on EINTR. This is a requirement for |
|||
correct aio_suspend and lio_listio implementations. */ |
|||
|
|||
#include <assert.h> |
|||
#include <pthreadP.h> |
|||
#include <lowlevellock.h> |
|||
|
|||
#define DONT_NEED_AIO_MISC_COND 1 |
|||
|
|||
#define AIO_MISC_NOTIFY(waitlist) \ |
|||
do { \ |
|||
if (--*waitlist->counterp == 0) \ |
|||
lll_futex_wake (waitlist->counterp, 1); \ |
|||
} while (0) |
|||
|
|||
#define AIO_MISC_WAIT(result, futex, timeout, cancel) \ |
|||
do { \ |
|||
int oldval = futex; \ |
|||
\ |
|||
if (oldval != 0) \ |
|||
{ \ |
|||
pthread_mutex_unlock (&__aio_requests_mutex); \ |
|||
\ |
|||
int oldtype; \ |
|||
if (cancel) \ |
|||
oldtype = LIBC_CANCEL_ASYNC (); \ |
|||
\ |
|||
int status; \ |
|||
do \ |
|||
{ \ |
|||
status = lll_futex_timed_wait (&futex, oldval, timeout); \ |
|||
if (status != -EWOULDBLOCK) \ |
|||
break; \ |
|||
\ |
|||
oldval = futex; \ |
|||
} \ |
|||
while (oldval != 0); \ |
|||
\ |
|||
if (cancel) \ |
|||
LIBC_CANCEL_RESET (oldtype); \ |
|||
\ |
|||
if (status == -EINTR) \ |
|||
result = EINTR; \ |
|||
else if (status == -ETIMEDOUT) \ |
|||
result = EAGAIN; \ |
|||
else \ |
|||
assert (status == 0 || status == -EWOULDBLOCK); \ |
|||
\ |
|||
pthread_mutex_lock (&__aio_requests_mutex); \ |
|||
} \ |
|||
} while (0) |
|||
|
|||
#include_next <aio_misc.h> |
|||
@ -0,0 +1,124 @@ |
|||
#include <aio.h> |
|||
#include <errno.h> |
|||
#include <signal.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <pthread.h> |
|||
#include <unistd.h> |
|||
|
|||
static pthread_barrier_t b; |
|||
static pthread_t main_thread; |
|||
static int flag; |
|||
|
|||
|
|||
static void * |
|||
tf (void *arg) |
|||
{ |
|||
int e = pthread_barrier_wait (&b); |
|||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) |
|||
{ |
|||
puts ("child: barrier_wait failed"); |
|||
exit (1); |
|||
} |
|||
|
|||
/* There is unfortunately no other way to try to make sure the other
|
|||
thread reached the aio_suspend call. This test could fail on |
|||
highly loaded machines. */ |
|||
sleep (2); |
|||
|
|||
pthread_kill (main_thread, SIGUSR1); |
|||
|
|||
while (1) |
|||
sleep (1000); |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
|
|||
static void |
|||
sh (int sig) |
|||
{ |
|||
flag = 1; |
|||
} |
|||
|
|||
|
|||
static int |
|||
do_test (void) |
|||
{ |
|||
main_thread = pthread_self (); |
|||
|
|||
struct sigaction sa; |
|||
|
|||
sa.sa_handler = sh; |
|||
sa.sa_flags = 0; |
|||
sigemptyset (&sa.sa_mask); |
|||
|
|||
if (sigaction (SIGUSR1, &sa, NULL) != 0) |
|||
{ |
|||
puts ("sigaction failed"); |
|||
return 1; |
|||
} |
|||
|
|||
if (pthread_barrier_init (&b, NULL, 2) != 0) |
|||
{ |
|||
puts ("barrier_init"); |
|||
return 1; |
|||
} |
|||
|
|||
int fds[2]; |
|||
if (pipe (fds) != 0) |
|||
{ |
|||
puts ("pipe failed"); |
|||
return 1; |
|||
} |
|||
|
|||
char buf[42]; |
|||
struct aiocb req; |
|||
req.aio_fildes = fds[0]; |
|||
req.aio_reqprio = 0; |
|||
req.aio_offset = 0; |
|||
req.aio_buf = buf; |
|||
req.aio_nbytes = sizeof (buf); |
|||
req.aio_sigevent.sigev_notify = SIGEV_NONE; |
|||
|
|||
if (aio_read (&req) != 0) |
|||
{ |
|||
puts ("aio_read failed"); |
|||
return 1; |
|||
} |
|||
|
|||
pthread_t th; |
|||
if (pthread_create (&th, NULL, tf, NULL) != 0) |
|||
{ |
|||
puts ("create failed"); |
|||
return 1; |
|||
} |
|||
|
|||
int e = pthread_barrier_wait (&b); |
|||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) |
|||
{ |
|||
puts ("parent: barrier_wait failed"); |
|||
exit (1); |
|||
} |
|||
|
|||
const struct aiocb *list[1]; |
|||
list[0] = &req; |
|||
|
|||
e = aio_suspend (list, 1, NULL); |
|||
if (e != -1) |
|||
{ |
|||
puts ("aio_suspend succeeded"); |
|||
return 1; |
|||
} |
|||
if (errno != EINTR) |
|||
{ |
|||
puts ("aio_suspend did not return EINTR"); |
|||
return 1; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
#define TEST_FUNCTION do_test () |
|||
#define TIMEOUT 5 |
|||
#include "../test-skeleton.c" |
|||
Loading…
Reference in new issue