1 /* Copyright (C) 2001-2023 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
27 /* We need this special structure to handle asynchronous I/O. */
31 struct sigevent sigev
;
32 struct waitlist list
[0];
37 __getaddrinfo_a (int mode
, struct gaicb
*list
[], int ent
, struct sigevent
*sig
)
39 struct sigevent defsigev
;
40 struct requestlist
*requests
[ent
];
42 volatile unsigned int total
= 0;
45 /* Check arguments. */
46 if (mode
!= GAI_WAIT
&& mode
!= GAI_NOWAIT
)
54 defsigev
.sigev_notify
= SIGEV_NONE
;
58 /* Request the mutex. */
59 __pthread_mutex_lock (&__gai_requests_mutex
);
61 /* Now we can enqueue all requests. Since we already acquired the
62 mutex the enqueue function need not do this. */
63 for (cnt
= 0; cnt
< ent
; ++cnt
)
64 if (list
[cnt
] != NULL
)
66 requests
[cnt
] = __gai_enqueue_request (list
[cnt
]);
68 if (requests
[cnt
] != NULL
)
69 /* Successfully enqueued. */
72 /* Signal that we've seen an error. `errno' and the error code
73 of the gaicb will tell more. */
81 /* We don't have anything to do except signalling if we work
84 /* Release the mutex. We do this before raising a signal since the
85 signal handler might do a `siglongjmp' and then the mutex is
87 __pthread_mutex_unlock (&__gai_requests_mutex
);
89 if (mode
== GAI_NOWAIT
)
90 __gai_notify_only (sig
,
91 sig
->sigev_notify
== SIGEV_SIGNAL
? getpid () : 0);
95 else if (mode
== GAI_WAIT
)
97 #ifndef DONT_NEED_GAI_MISC_COND
98 pthread_cond_t cond
= PTHREAD_COND_INITIALIZER
;
100 struct waitlist waitlist
[ent
];
104 for (cnt
= 0; cnt
< ent
; ++cnt
)
105 if (requests
[cnt
] != NULL
)
107 #ifndef DONT_NEED_GAI_MISC_COND
108 waitlist
[cnt
].cond
= &cond
;
110 waitlist
[cnt
].next
= requests
[cnt
]->waiting
;
111 waitlist
[cnt
].counterp
= &total
;
112 waitlist
[cnt
].sigevp
= NULL
;
113 waitlist
[cnt
].caller_pid
= 0; /* Not needed. */
114 requests
[cnt
]->waiting
= &waitlist
[cnt
];
118 /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
119 points we must be careful. We added entries to the waiting lists
120 which we must remove. So defer cancelation for now. */
121 __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE
, &oldstate
);
125 #ifdef DONT_NEED_GAI_MISC_COND
126 int not_used
__attribute__ ((unused
));
127 GAI_MISC_WAIT (not_used
, total
, NULL
, 1);
129 pthread_cond_wait (&cond
, &__gai_requests_mutex
);
133 /* Now it's time to restore the cancelation state. */
134 __pthread_setcancelstate (oldstate
, NULL
);
136 #ifndef DONT_NEED_GAI_MISC_COND
137 /* Release the conditional variable. */
138 if (pthread_cond_destroy (&cond
) != 0)
139 /* This must never happen. */
145 struct async_waitlist
*waitlist
;
147 waitlist
= (struct async_waitlist
*)
148 malloc (sizeof (struct async_waitlist
)
149 + (ent
* sizeof (struct waitlist
)));
151 if (waitlist
== NULL
)
155 pid_t caller_pid
= sig
->sigev_notify
== SIGEV_SIGNAL
? getpid () : 0;
158 for (cnt
= 0; cnt
< ent
; ++cnt
)
159 if (requests
[cnt
] != NULL
)
161 #ifndef DONT_NEED_GAI_MISC_COND
162 waitlist
->list
[cnt
].cond
= NULL
;
164 waitlist
->list
[cnt
].next
= requests
[cnt
]->waiting
;
165 waitlist
->list
[cnt
].counterp
= &waitlist
->counter
;
166 waitlist
->list
[cnt
].sigevp
= &waitlist
->sigev
;
167 waitlist
->list
[cnt
].caller_pid
= caller_pid
;
168 requests
[cnt
]->waiting
= &waitlist
->list
[cnt
];
172 waitlist
->counter
= total
;
173 waitlist
->sigev
= *sig
;
177 /* Release the mutex. */
178 __pthread_mutex_unlock (&__gai_requests_mutex
);
183 versioned_symbol (libc
, __getaddrinfo_a
, getaddrinfo_a
, GLIBC_2_34
);
185 # if OTHER_SHLIB_COMPAT (libanl, GLIBC_2_2_3, GLIBC_2_34)
186 compat_symbol (libanl
, __getaddrinfo_a
, getaddrinfo_a
, GLIBC_2_2_3
);
188 #else /* !PTHREAD_IN_LIBC */
189 strong_alias (__getaddrinfo_a
, getaddrinfo_a
)
190 #endif /* !PTHREAD_IN_LIBC */