1 /* Copyright (C) 2001 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 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 waitlist
[cnt
].cond
= &cond
;
108 waitlist
[cnt
].next
= requests
[cnt
]->waiting
;
109 waitlist
[cnt
].counterp
= &total
;
110 waitlist
[cnt
].sigevp
= NULL
;
111 waitlist
[cnt
].caller_pid
= 0; /* Not needed. */
112 requests
[cnt
]->waiting
= &waitlist
[cnt
];
116 /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
117 points we must be careful. We added entries to the waiting lists
118 which we must remove. So defer cancelation for now. */
119 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE
, &oldstate
);
122 pthread_cond_wait (&cond
, &__gai_requests_mutex
);
124 /* Now it's time to restore the cancelation state. */
125 pthread_setcancelstate (oldstate
, NULL
);
127 /* Release the conditional variable. */
128 if (pthread_cond_destroy (&cond
) != 0)
129 /* This must never happen. */
134 struct async_waitlist
*waitlist
;
136 waitlist
= (struct async_waitlist
*)
137 malloc (sizeof (struct async_waitlist
)
138 + (ent
* sizeof (struct waitlist
)));
140 if (waitlist
== NULL
)
144 pid_t caller_pid
= sig
->sigev_notify
== SIGEV_SIGNAL
? getpid () : 0;
147 for (cnt
= 0; cnt
< ent
; ++cnt
)
148 if (requests
[cnt
] != NULL
)
150 waitlist
->list
[cnt
].cond
= NULL
;
151 waitlist
->list
[cnt
].next
= requests
[cnt
]->waiting
;
152 waitlist
->list
[cnt
].counterp
= &waitlist
->counter
;
153 waitlist
->list
[cnt
].sigevp
= &waitlist
->sigev
;
154 waitlist
->list
[cnt
].caller_pid
= caller_pid
;
155 requests
[cnt
]->waiting
= &waitlist
->list
[cnt
];
159 waitlist
->counter
= total
;
160 waitlist
->sigev
= *sig
;
164 /* Release the mutex. */
165 pthread_mutex_unlock (&__gai_requests_mutex
);