1 /* Copyright (C) 2001, 2006 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 /* We need this special structure to handle asynchronous I/O. */
33 struct sigevent sigev
;
34 struct waitlist list
[0];
39 getaddrinfo_a (int mode
, struct gaicb
*list
[], int ent
, struct sigevent
*sig
)
41 struct sigevent defsigev
;
42 struct requestlist
*requests
[ent
];
44 volatile int total
= 0;
47 /* Check arguments. */
48 if (mode
!= GAI_WAIT
&& mode
!= GAI_NOWAIT
)
56 defsigev
.sigev_notify
= SIGEV_NONE
;
60 /* Request the mutex. */
61 pthread_mutex_lock (&__gai_requests_mutex
);
63 /* Now we can enqueue all requests. Since we already acquired the
64 mutex the enqueue function need not do this. */
65 for (cnt
= 0; cnt
< ent
; ++cnt
)
66 if (list
[cnt
] != NULL
)
68 requests
[cnt
] = __gai_enqueue_request (list
[cnt
]);
70 if (requests
[cnt
] != NULL
)
71 /* Successfully enqueued. */
74 /* Signal that we've seen an error. `errno' and the error code
75 of the gaicb will tell more. */
83 /* We don't have anything to do except signalling if we work
86 /* Release the mutex. We do this before raising a signal since the
87 signal handler might do a `siglongjmp' and then the mutex is
89 pthread_mutex_unlock (&__gai_requests_mutex
);
91 if (mode
== GAI_NOWAIT
)
92 __gai_notify_only (sig
,
93 sig
->sigev_notify
== SIGEV_SIGNAL
? getpid () : 0);
97 else if (mode
== GAI_WAIT
)
99 #ifndef DONT_NEED_GAI_MISC_COND
100 pthread_cond_t cond
= PTHREAD_COND_INITIALIZER
;
102 struct waitlist waitlist
[ent
];
106 for (cnt
= 0; cnt
< ent
; ++cnt
)
107 if (requests
[cnt
] != NULL
)
109 #ifndef DONT_NEED_GAI_MISC_COND
110 waitlist
[cnt
].cond
= &cond
;
112 waitlist
[cnt
].next
= requests
[cnt
]->waiting
;
113 waitlist
[cnt
].counterp
= &total
;
114 waitlist
[cnt
].sigevp
= NULL
;
115 waitlist
[cnt
].caller_pid
= 0; /* Not needed. */
116 requests
[cnt
]->waiting
= &waitlist
[cnt
];
120 /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
121 points we must be careful. We added entries to the waiting lists
122 which we must remove. So defer cancelation for now. */
123 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE
, &oldstate
);
127 #ifdef DONT_NEED_GAI_MISC_COND
129 GAI_MISC_WAIT (result
, total
, NULL
, 1);
131 pthread_cond_wait (&cond
, &__gai_requests_mutex
);
135 /* Now it's time to restore the cancelation state. */
136 pthread_setcancelstate (oldstate
, NULL
);
138 #ifndef DONT_NEED_GAI_MISC_COND
139 /* Release the conditional variable. */
140 if (pthread_cond_destroy (&cond
) != 0)
141 /* This must never happen. */
147 struct async_waitlist
*waitlist
;
149 waitlist
= (struct async_waitlist
*)
150 malloc (sizeof (struct async_waitlist
)
151 + (ent
* sizeof (struct waitlist
)));
153 if (waitlist
== NULL
)
157 pid_t caller_pid
= sig
->sigev_notify
== SIGEV_SIGNAL
? getpid () : 0;
160 for (cnt
= 0; cnt
< ent
; ++cnt
)
161 if (requests
[cnt
] != NULL
)
163 #ifndef DONT_NEED_GAI_MISC_COND
164 waitlist
->list
[cnt
].cond
= NULL
;
166 waitlist
->list
[cnt
].next
= requests
[cnt
]->waiting
;
167 waitlist
->list
[cnt
].counterp
= &waitlist
->counter
;
168 waitlist
->list
[cnt
].sigevp
= &waitlist
->sigev
;
169 waitlist
->list
[cnt
].caller_pid
= caller_pid
;
170 requests
[cnt
]->waiting
= &waitlist
->list
[cnt
];
174 waitlist
->counter
= total
;
175 waitlist
->sigev
= *sig
;
179 /* Release the mutex. */
180 pthread_mutex_unlock (&__gai_requests_mutex
);