1 /*
2                                   NETWIB
3                              Network library
4                 Copyright(c) 1999-2010 Laurent Constantin
5                                   -----
6 
7   Main server   : http://www.laurentconstantin.com/
8   Backup server : http://laurentconstantin.free.fr/
9   [my current email address is on the web servers]
10 
11                                   -----
12   This file is part of Netwib.
13 
14   Netwib is free software: you can redistribute it and/or modify
15   it under the terms of the GNU General Public License version 3
16   as published by the Free Software Foundation.
17 
18   Netwib is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details (http://www.gnu.org/).
22 
23 ------------------------------------------------------------------------
24 */
25 
26 #include <netwib/inc/maininc.h>
27 
28 /*-------------------------------------------------------------*/
29 struct netwib_wait {
30   netwib_wait_event_pf pfuncevent;
31   netwib_ptr infos;
32   netwib_wait_close_pf pfuncclose;
33 };
34 
35 /*-------------------------------------------------------------*/
netwib_wait_init(netwib_wait_event_pf pfuncevent,netwib_ptr infos,netwib_wait_close_pf pfuncclose,netwib_wait ** ppwait)36 netwib_err netwib_wait_init(netwib_wait_event_pf pfuncevent,
37                             netwib_ptr infos,
38                             netwib_wait_close_pf pfuncclose,
39                             netwib_wait **ppwait)
40 {
41   netwib_wait *pwait;
42 
43   /* allocate needed memory to store pwait */
44   netwib_er(netwib_ptr_malloc(sizeof(netwib_wait), (netwib_ptr*)&pwait));
45   *ppwait = pwait;
46   pwait->pfuncevent = pfuncevent;
47   pwait->infos = infos;
48   pwait->pfuncclose = pfuncclose;
49 
50 #if NETWIB_DEBUG_LEAK==1
51   netwib_er(netwib_debug_leak_add_wait(pwait));
52 #endif
53 
54   return(NETWIB_ERR_OK);
55 }
56 
57 /*-------------------------------------------------------------*/
netwib_wait_close(netwib_wait ** ppwait)58 netwib_err netwib_wait_close(netwib_wait **ppwait)
59 {
60   netwib_wait *pwait;
61 
62   /* parameter verification */
63   if (ppwait == NULL) {
64     return(NETWIB_ERR_PANULLPTR);
65   }
66   pwait = *ppwait;
67 
68   if (pwait->pfuncclose != NULL) {
69     netwib_er((*pwait->pfuncclose)(pwait->infos));
70   }
71 
72 #if NETWIB_DEBUG_LEAK==1
73   netwib_er(netwib_debug_leak_del_wait(*ppwait));
74 #endif
75 
76   /* free memory */
77   netwib_er(netwib_ptr_free((netwib_ptr*)ppwait));
78 
79   return(NETWIB_ERR_OK);
80 }
81 
82 /*-------------------------------------------------------------*/
83 typedef struct {
84   netwib_io *pio;
85   netwib_io_waytype way;
86 } netwib_priv_wait_io;
netwib_priv_wait_event_io(netwib_ptr infos,netwib_consttime * pabstime,netwib_bool * pevent)87 static netwib_err netwib_priv_wait_event_io(netwib_ptr infos,
88                                             netwib_consttime *pabstime,
89                                             netwib_bool *pevent)
90 {
91   netwib_priv_wait_io *pwio = (netwib_priv_wait_io *)infos;
92 
93   netwib_er(netwib_io_wait(pwio->pio, pwio->way, pabstime, pevent));
94   return(NETWIB_ERR_OK);
95 }
netwib_priv_wait_close_io(netwib_ptr infos)96 static netwib_err netwib_priv_wait_close_io(netwib_ptr infos)
97 {
98   netwib_er(netwib_ptr_free(&infos));
99   return(NETWIB_ERR_OK);
100 }
netwib_wait_init_io(netwib_io * pio,netwib_io_waytype way,netwib_wait ** ppwait)101 netwib_err netwib_wait_init_io(netwib_io *pio,
102                                netwib_io_waytype way,
103                                netwib_wait **ppwait)
104 {
105   netwib_priv_wait_io *pwio;
106 
107   netwib_er(netwib_ptr_malloc(sizeof(netwib_priv_wait_io),
108                               (netwib_ptr*)&pwio));
109   pwio->pio = pio;
110   pwio->way = way;
111 
112   netwib_er(netwib_wait_init(&netwib_priv_wait_event_io, pwio,
113                            &netwib_priv_wait_close_io, ppwait));
114   return(NETWIB_ERR_OK);
115 }
116 
117 /*-------------------------------------------------------------*/
118 typedef struct {
119   netwib_thread *pthread;
120   netwib_err *preturnederror;
121   netwib_ptr *pinfosout;
122 } netwib_priv_wait_thread;
netwib_priv_wait_event_thread(netwib_ptr infos,netwib_consttime * pabstime,netwib_bool * pevent)123 static netwib_err netwib_priv_wait_event_thread(netwib_ptr infos,
124                                                 netwib_consttime *pabstime,
125                                                 netwib_bool *pevent)
126 {
127   netwib_priv_wait_thread *pwthread = (netwib_priv_wait_thread *)infos;
128 
129   netwib_er(netwib_thread_wait(pwthread->pthread, pabstime, pevent,
130                                pwthread->preturnederror, pwthread->pinfosout));
131   return(NETWIB_ERR_OK);
132 }
netwib_priv_wait_close_thread(netwib_ptr infos)133 static netwib_err netwib_priv_wait_close_thread(netwib_ptr infos)
134 {
135   netwib_er(netwib_ptr_free(&infos));
136   return(NETWIB_ERR_OK);
137 }
netwib_wait_init_thread_end(netwib_thread * pthread,netwib_err * preturnederror,netwib_ptr * pinfosout,netwib_wait ** ppwait)138 netwib_err netwib_wait_init_thread_end(netwib_thread *pthread,
139                                        netwib_err *preturnederror,
140                                        netwib_ptr *pinfosout,
141                                        netwib_wait **ppwait)
142 {
143   netwib_priv_wait_thread *pwthread;
144 
145   netwib_er(netwib_ptr_malloc(sizeof(netwib_priv_wait_thread),
146                               (netwib_ptr*)&pwthread));
147   pwthread->pthread = pthread;
148   pwthread->preturnederror = preturnederror;
149   pwthread->pinfosout = pinfosout;
150 
151   netwib_er(netwib_wait_init(&netwib_priv_wait_event_thread, pwthread,
152                              &netwib_priv_wait_close_thread, ppwait));
153   return(NETWIB_ERR_OK);
154 }
155 
156 /*-------------------------------------------------------------*/
157 typedef struct {
158   netwib_thread_cond *pcond;
159   netwib_uint32 *pvalue;
160 } netwib_priv_wait_thread_cond;
netwib_priv_wait_event_thread_cond(netwib_ptr infos,netwib_consttime * pabstime,netwib_bool * pevent)161 static netwib_err netwib_priv_wait_event_thread_cond(netwib_ptr infos,
162                                                      netwib_consttime *pabstime,
163                                                      netwib_bool *pevent)
164 {
165   netwib_priv_wait_thread_cond *pwthread = (netwib_priv_wait_thread_cond *)infos;
166 
167   netwib_er(netwib_thread_cond_wait(pwthread->pcond, pabstime, pevent,
168                                     pwthread->pvalue));
169   return(NETWIB_ERR_OK);
170 }
netwib_priv_wait_close_thread_cond(netwib_ptr infos)171 static netwib_err netwib_priv_wait_close_thread_cond(netwib_ptr infos)
172 {
173   netwib_er(netwib_ptr_free(&infos));
174   return(NETWIB_ERR_OK);
175 }
netwib_wait_init_thread_cond(netwib_thread_cond * pcond,netwib_uint32 * pvalue,netwib_wait ** ppwait)176 netwib_err netwib_wait_init_thread_cond(netwib_thread_cond *pcond,
177                                         netwib_uint32 *pvalue,
178                                         netwib_wait **ppwait)
179 {
180   netwib_priv_wait_thread_cond *pwthread;
181 
182   netwib_er(netwib_ptr_malloc(sizeof(netwib_priv_wait_thread_cond),
183                               (netwib_ptr*)&pwthread));
184   pwthread->pcond = pcond;
185   pwthread->pvalue = pvalue;
186 
187   netwib_er(netwib_wait_init(&netwib_priv_wait_event_thread_cond, pwthread,
188                              &netwib_priv_wait_close_thread_cond, ppwait));
189   return(NETWIB_ERR_OK);
190 }
191 
192 /*-------------------------------------------------------------*/
netwib_wait_wait1(netwib_wait * pwait,netwib_consttime * pabstime,netwib_bool * pevent)193 netwib_err netwib_wait_wait1(netwib_wait *pwait,
194                              netwib_consttime *pabstime,
195                              netwib_bool *pevent)
196 {
197   /* parameters verification */
198   if (pwait == NULL) {
199     return(NETWIB_ERR_PANULLPTR);
200   }
201 #if NETWIB_DEBUG_LEAK==1
202   netwib_er(netwib_debug_leak_valid_wait(pwait));
203 #endif
204 
205   netwib_er((*pwait->pfuncevent)(pwait->infos, pabstime, pevent));
206 
207   return(NETWIB_ERR_OK);
208 }
209 
210 /*-------------------------------------------------------------*/
netwib_priv_wait_wait5(netwib_wait * pwait1,netwib_wait * pwait2,netwib_wait * pwait3,netwib_wait * pwait4,netwib_wait * pwait5,netwib_bool * pevent,netwib_bool * pevent1,netwib_bool * pevent2,netwib_bool * pevent3,netwib_bool * pevent4,netwib_bool * pevent5)211 static netwib_err netwib_priv_wait_wait5(netwib_wait *pwait1,
212                                          netwib_wait *pwait2,
213                                          netwib_wait *pwait3,
214                                          netwib_wait *pwait4,
215                                          netwib_wait *pwait5,
216                                          netwib_bool *pevent,
217                                          netwib_bool *pevent1,
218                                          netwib_bool *pevent2,
219                                          netwib_bool *pevent3,
220                                          netwib_bool *pevent4,
221                                          netwib_bool *pevent5)
222 {
223   netwib_bool event;
224 
225   *pevent = NETWIB_FALSE;
226 
227   if (pwait1 != NULL) {
228     netwib_er((*pwait1->pfuncevent)(pwait1->infos, NETWIB_TIME_ZERO, &event));
229     if (pevent1 != NULL) *pevent1 = event;
230     if (event) *pevent = NETWIB_TRUE;
231   }
232   if (pwait2 != NULL) {
233     netwib_er((*pwait2->pfuncevent)(pwait2->infos, NETWIB_TIME_ZERO, &event));
234     if (pevent2 != NULL) *pevent2 = event;
235     if (event) *pevent = NETWIB_TRUE;
236   }
237   if (pwait3 != NULL) {
238     netwib_er((*pwait3->pfuncevent)(pwait3->infos, NETWIB_TIME_ZERO, &event));
239     if (pevent3 != NULL) *pevent3 = event;
240     if (event) *pevent = NETWIB_TRUE;
241   }
242   if (pwait4 != NULL) {
243     netwib_er((*pwait4->pfuncevent)(pwait4->infos, NETWIB_TIME_ZERO, &event));
244     if (pevent4 != NULL) *pevent4 = event;
245     if (event) *pevent = NETWIB_TRUE;
246   }
247   if (pwait5 != NULL) {
248     netwib_er((*pwait5->pfuncevent)(pwait5->infos, NETWIB_TIME_ZERO, &event));
249     if (pevent5 != NULL) *pevent5 = event;
250     if (event) *pevent = NETWIB_TRUE;
251   }
252 
253   return(NETWIB_ERR_OK);
254 }
255 
256 /*-------------------------------------------------------------*/
netwib_wait_wait5(netwib_wait * pwait1,netwib_wait * pwait2,netwib_wait * pwait3,netwib_wait * pwait4,netwib_wait * pwait5,netwib_consttime * pabstime,netwib_bool * pevent1,netwib_bool * pevent2,netwib_bool * pevent3,netwib_bool * pevent4,netwib_bool * pevent5)257 netwib_err netwib_wait_wait5(netwib_wait *pwait1,
258                              netwib_wait *pwait2,
259                              netwib_wait *pwait3,
260                              netwib_wait *pwait4,
261                              netwib_wait *pwait5,
262                              netwib_consttime *pabstime,
263                              netwib_bool *pevent1,
264                              netwib_bool *pevent2,
265                              netwib_bool *pevent3,
266                              netwib_bool *pevent4,
267                              netwib_bool *pevent5)
268 {
269   netwib_uint32 numcalls;
270   netwib_bool event, elapsed;
271 
272 #if NETWIB_DEBUG_LEAK==1
273   if (pwait1 != NULL) {
274     netwib_er(netwib_debug_leak_valid_wait(pwait1));
275   }
276   if (pwait2 != NULL) {
277     netwib_er(netwib_debug_leak_valid_wait(pwait2));
278   }
279   if (pwait3 != NULL) {
280     netwib_er(netwib_debug_leak_valid_wait(pwait3));
281   }
282   if (pwait4 != NULL) {
283     netwib_er(netwib_debug_leak_valid_wait(pwait4));
284   }
285   if (pwait5 != NULL) {
286     netwib_er(netwib_debug_leak_valid_wait(pwait5));
287   }
288 #endif
289 
290   if (pabstime == NETWIB_TIME_ZERO) {
291     netwib_er(netwib_priv_wait_wait5(pwait1, pwait2, pwait3, pwait4, pwait5,
292                                      &event,
293                                      pevent1, pevent2, pevent3, pevent4,
294                                      pevent5));
295     return(NETWIB_ERR_OK);
296   }
297 
298   if (pabstime == NETWIB_TIME_INFINITE) {
299     numcalls = 0;
300     while (NETWIB_TRUE) {
301       netwib_er(netwib_priv_wait_wait5(pwait1, pwait2, pwait3, pwait4, pwait5,
302                                        &event,
303                                        pevent1, pevent2, pevent3, pevent4,
304                                        pevent5));
305       if (event) {
306         return(NETWIB_ERR_OK);
307       }
308       /* small pause */
309       netwib_er(netwib_priv_pause2(&numcalls));
310     }
311   }
312 
313   numcalls = 0;
314   while (NETWIB_TRUE) {
315     /* check time */
316     netwib_er(netwib_time_iselapsed(pabstime, &elapsed));
317     if (elapsed) {
318       if (pevent1 != NULL) *pevent1 = NETWIB_FALSE;
319       if (pevent2 != NULL) *pevent2 = NETWIB_FALSE;
320       if (pevent3 != NULL) *pevent3 = NETWIB_FALSE;
321       if (pevent4 != NULL) *pevent4 = NETWIB_FALSE;
322       if (pevent5 != NULL) *pevent5 = NETWIB_FALSE;
323       break;
324     }
325     /* wait */
326     netwib_er(netwib_priv_wait_wait5(pwait1, pwait2, pwait3, pwait4, pwait5,
327                                      &event,
328                                      pevent1, pevent2, pevent3, pevent4,
329                                      pevent5));
330     if (event) {
331       break;
332     }
333     /* small pause */
334     netwib_er(netwib_priv_pause2(&numcalls));
335   }
336 
337   return(NETWIB_ERR_OK);
338 }
339