1 /* Copyright (C) 2001-2013 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
28 /* We need this special structure to handle asynchronous I/O. */
32 struct sigevent sigev
;
33 struct waitlist list
[0];
38 getaddrinfo_a (int mode
, struct gaicb
*list
[], int ent
, struct sigevent
*sig
)
40 struct sigevent defsigev
;
41 struct requestlist
*requests
[ent
];
43 volatile int total
= 0;
46 /* Check arguments. */
47 if (mode
!= GAI_WAIT
&& mode
!= GAI_NOWAIT
)
55 defsigev
.sigev_notify
= SIGEV_NONE
;
59 /* Request the mutex. */
60 pthread_mutex_lock (&__gai_requests_mutex
);
62 /* Now we can enqueue all requests. Since we already acquired the
63 mutex the enqueue function need not do this. */
64 for (cnt
= 0; cnt
< ent
; ++cnt
)
65 if (list
[cnt
] != NULL
)
67 requests
[cnt
] = __gai_enqueue_request (list
[cnt
]);
69 if (requests
[cnt
] != NULL
)
70 /* Successfully enqueued. */
73 /* Signal that we've seen an error. `errno' and the error code
74 of the gaicb will tell more. */
82 /* We don't have anything to do except signalling if we work
85 /* Release the mutex. We do this before raising a signal since the
86 signal handler might do a `siglongjmp' and then the mutex is
88 pthread_mutex_unlock (&__gai_requests_mutex
);
90 if (mode
== GAI_NOWAIT
)
91 __gai_notify_only (sig
,
92 sig
->sigev_notify
== SIGEV_SIGNAL
? getpid () : 0);
96 else if (mode
== GAI_WAIT
)
98 #ifndef DONT_NEED_GAI_MISC_COND
99 pthread_cond_t cond
= PTHREAD_COND_INITIALIZER
;
101 struct waitlist waitlist
[ent
];
105 for (cnt
= 0; cnt
< ent
; ++cnt
)
106 if (requests
[cnt
] != NULL
)
108 #ifndef DONT_NEED_GAI_MISC_COND
109 waitlist
[cnt
].cond
= &cond
;
111 waitlist
[cnt
].next
= requests
[cnt
]->waiting
;
112 waitlist
[cnt
].counterp
= &total
;
113 waitlist
[cnt
].sigevp
= NULL
;
114 waitlist
[cnt
].caller_pid
= 0; /* Not needed. */
115 requests
[cnt
]->waiting
= &waitlist
[cnt
];
119 /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
120 points we must be careful. We added entries to the waiting lists
121 which we must remove. So defer cancelation for now. */
122 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE
, &oldstate
);
126 #ifdef DONT_NEED_GAI_MISC_COND
127 int not_used
__attribute__ ((unused
));
128 GAI_MISC_WAIT (not_used
, total
, NULL
, 1);
130 pthread_cond_wait (&cond
, &__gai_requests_mutex
);
134 /* Now it's time to restore the cancelation state. */
135 pthread_setcancelstate (oldstate
, NULL
);
137 #ifndef DONT_NEED_GAI_MISC_COND
138 /* Release the conditional variable. */
139 if (pthread_cond_destroy (&cond
) != 0)
140 /* This must never happen. */
146 struct async_waitlist
*waitlist
;
148 waitlist
= (struct async_waitlist
*)
149 malloc (sizeof (struct async_waitlist
)
150 + (ent
* sizeof (struct waitlist
)));
152 if (waitlist
== NULL
)
156 pid_t caller_pid
= sig
->sigev_notify
== SIGEV_SIGNAL
? getpid () : 0;
159 for (cnt
= 0; cnt
< ent
; ++cnt
)
160 if (requests
[cnt
] != NULL
)
162 #ifndef DONT_NEED_GAI_MISC_COND
163 waitlist
->list
[cnt
].cond
= NULL
;
165 waitlist
->list
[cnt
].next
= requests
[cnt
]->waiting
;
166 waitlist
->list
[cnt
].counterp
= &waitlist
->counter
;
167 waitlist
->list
[cnt
].sigevp
= &waitlist
->sigev
;
168 waitlist
->list
[cnt
].caller_pid
= caller_pid
;
169 requests
[cnt
]->waiting
= &waitlist
->list
[cnt
];
173 waitlist
->counter
= total
;
174 waitlist
->sigev
= *sig
;
178 /* Release the mutex. */
179 pthread_mutex_unlock (&__gai_requests_mutex
);