1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <errno.h>
21: #include <netdb.h>
22: #include <pthread.h>
23: #include <stdlib.h>
24: #include <unistd.h>
25:
26: #include <gai_misc.h>
27:
28:
29:
30: struct async_waitlist
31: {
32: int counter;
33: struct sigevent sigev;
34: struct waitlist list[0];
35: };
36:
37:
38: int
39: getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
40: {
41: struct sigevent defsigev;
42: struct requestlist *requests[ent];
43: int cnt;
44: volatile int total = 0;
45: int result = 0;
46:
47:
48: if (mode != GAI_WAIT && mode != GAI_NOWAIT)
49: {
50: __set_errno (EINVAL);
51: return EAI_SYSTEM;
52: }
53:
54: if (sig == NULL)
55: {
56: defsigev.sigev_notify = SIGEV_NONE;
57: sig = &defsigev;
58: }
59:
60:
61: pthread_mutex_lock (&__gai_requests_mutex);
62:
63:
64:
65: for (cnt = 0; cnt < ent; ++cnt)
66: if (list[cnt] != NULL)
67: {
68: requests[cnt] = __gai_enqueue_request (list[cnt]);
69:
70: if (requests[cnt] != NULL)
71:
72: ++total;
73: else
74:
75:
76: result = EAI_SYSTEM;
77: }
78: else
79: requests[cnt] = NULL;
80:
81: if (total == 0)
82: {
83:
84:
85:
86:
87:
88:
89: pthread_mutex_unlock (&__gai_requests_mutex);
90:
91: if (mode == GAI_NOWAIT)
92: __gai_notify_only (sig,
93: sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0);
94:
95: return result;
96: }
97: else if (mode == GAI_WAIT)
98: {
99: #ifndef DONT_NEED_GAI_MISC_COND
100: pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
101: #endif
102: struct waitlist waitlist[ent];
103: int oldstate;
104:
105: total = 0;
106: for (cnt = 0; cnt < ent; ++cnt)
107: if (requests[cnt] != NULL)
108: {
109: #ifndef DONT_NEED_GAI_MISC_COND
110: waitlist[cnt].cond = &cond;
111: #endif
112: waitlist[cnt].next = requests[cnt]->waiting;
113: waitlist[cnt].counterp = &total;
114: waitlist[cnt].sigevp = NULL;
115: waitlist[cnt].caller_pid = 0;
116: requests[cnt]->waiting = &waitlist[cnt];
117: ++total;
118: }
119:
120:
121:
122:
123: pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
124:
125: while (total > 0)
126: {
127: #ifdef DONT_NEED_GAI_MISC_COND
128: int result;
129: GAI_MISC_WAIT (result, total, NULL, 1);
130: #else
131: pthread_cond_wait (&cond, &__gai_requests_mutex);
132: #endif
133: }
134:
135:
136: pthread_setcancelstate (oldstate, NULL);
137:
138: #ifndef DONT_NEED_GAI_MISC_COND
139:
140: if (pthread_cond_destroy (&cond) != 0)
141:
142: abort ();
143: #endif
144: }
145: else
146: {
147: struct async_waitlist *waitlist;
148:
149: waitlist = (struct async_waitlist *)
150: malloc (sizeof (struct async_waitlist)
151: + (ent * sizeof (struct waitlist)));
152:
153: if (waitlist == NULL)
154: result = EAI_AGAIN;
155: else
156: {
157: pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0;
158: total = 0;
159:
160: for (cnt = 0; cnt < ent; ++cnt)
161: if (requests[cnt] != NULL)
162: {
163: #ifndef DONT_NEED_GAI_MISC_COND
164: waitlist->list[cnt].cond = NULL;
165: #endif
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];
171: ++total;
172: }
173:
174: waitlist->counter = total;
175: waitlist->sigev = *sig;
176: }
177: }
178:
179:
180: pthread_mutex_unlock (&__gai_requests_mutex);
181:
182: return result;
183: }