2 This source code file is part of thread_mpi.
3 Written by Sander Pronk, Erik Lindahl, and possibly others.
5 Copyright (c) 2009, Sander Pronk, Erik Lindahl.
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 1) Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3) Neither the name of the copyright holders nor the
16 names of its contributors may be used to endorse or promote products
17 derived from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
20 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 If you want to redistribute modifications, please consider that
31 scientific software is very special. Version control is crucial -
32 bugs must be traceable. We will be happy to consider code for
33 inclusion in the official distribution, but derived work should not
34 be called official thread_mpi. Details are found in the README & COPYING
38 #ifdef HAVE_TMPI_CONFIG_H
39 #include "tmpi_config.h"
62 int tMPI_Wait(tMPI_Request *request, tMPI_Status *status)
64 int ret = TMPI_SUCCESS;
65 struct tmpi_thread *cur = tMPI_Get_current();
66 struct req_list *rql = &(cur->rql);
70 tMPI_Profile_count_start(cur);
73 tMPI_Trace_print("tMPI_Wait(%p, %p)", request, status);
75 if (!request || !(*request))
81 /* fix the pointers */
85 /* and wait for our request */
88 if (tMPI_Test_single(cur, rq))
92 tMPI_Wait_process_incoming(cur);
96 rq->ev = NULL; /* we won't be using that envelope any more */
99 tMPI_Set_status(rq, status);
102 tMPI_Return_req(rql, *request);
105 tMPI_Profile_count_stop(cur, TMPIFN_Wait);
110 int tMPI_Test(tMPI_Request *request, int *flag, tMPI_Status *status)
112 int ret = TMPI_SUCCESS;
113 struct tmpi_thread *cur = tMPI_Get_current();
114 struct req_list *rql = &(cur->rql);
115 struct tmpi_req_ *rq;
118 tMPI_Profile_count_start(cur);
121 tMPI_Trace_print("tMPI_Test(%p, %p, %p)", request, flag, status);
123 if (!request || !(*request))
129 /* fix the pointers */
133 /* and check our request */
134 if (tMPI_Test_single(cur, rq))
143 tMPI_Set_status(rq, status);
145 tMPI_Return_req(rql, *request);
146 *request = TMPI_REQUEST_NULL;
150 tMPI_Profile_count_stop(cur, TMPIFN_Test);
170 /* test multiple requests by first making a linked list of them, and then
171 checking for their completion. Used in tMPI_{Test|Wait}{all|any|some}
173 wait = whether to wait for incoming events
174 blocking = whether to block until all reqs are completed */
175 static void tMPI_Test_multi_req(struct tmpi_thread *cur,
176 int count, tMPI_Request *array_of_requests,
177 tmpi_bool wait, tmpi_bool blocking)
180 struct tmpi_req_ *first = NULL, *last = NULL;
182 /* construct the list of requests */
183 for (i = 0; i < count; i++)
185 struct tmpi_req_ *curr = array_of_requests[i];
192 /* fix the pointers */
195 /* we connect to itself */
202 /* we connect to the last */
210 /* and wait for our request */
213 if (tMPI_Test_multi(cur, first, NULL))
219 tMPI_Wait_process_incoming(cur);
222 while (blocking && wait);
227 int tMPI_Waitall(int count, tMPI_Request *array_of_requests,
228 tMPI_Status *array_of_statuses)
231 int ret = TMPI_SUCCESS;
232 struct tmpi_thread *cur = tMPI_Get_current();
233 struct req_list *rql = &(cur->rql);
235 tMPI_Profile_count_start(cur);
238 tMPI_Trace_print("tMPI_Waitall(%d, %p, %p)", count, array_of_requests,
241 tMPI_Test_multi_req(cur, count, array_of_requests, TRUE, TRUE);
243 /* deallocate the now finished requests */
244 for (i = 0; i < count; i++)
246 if (array_of_requests[i])
248 if (array_of_statuses)
250 tMPI_Set_status(array_of_requests[i], &(array_of_statuses[i]));
252 if (array_of_requests[i]->error != TMPI_SUCCESS)
254 ret = TMPI_ERR_IN_STATUS;
256 tMPI_Return_req(rql, array_of_requests[i]);
257 array_of_requests[i] = TMPI_REQUEST_NULL;
262 tMPI_Profile_count_stop(cur, TMPIFN_Waitall);
267 int tMPI_Testall(int count, tMPI_Request *array_of_requests,
268 int *flag, tMPI_Status *array_of_statuses)
271 int ret = TMPI_SUCCESS;
272 struct tmpi_thread *cur = tMPI_Get_current();
273 struct req_list *rql = &(cur->rql);
275 tMPI_Profile_count_start(cur);
278 tMPI_Trace_print("tMPI_Testall(%d, %p, %p, %p)", count, array_of_requests,
279 flag, array_of_statuses);
281 tMPI_Test_multi_req(cur, count, array_of_requests, FALSE, TRUE);
287 /* deallocate the possibly finished requests */
288 for (i = 0; i < count; i++)
290 if (array_of_requests[i] && array_of_requests[i]->finished)
293 if (array_of_statuses)
295 tMPI_Set_status(array_of_requests[i], &(array_of_statuses[i]));
297 if (array_of_requests[i]->error != TMPI_SUCCESS)
299 ret = TMPI_ERR_IN_STATUS;
301 tMPI_Return_req(rql, array_of_requests[i]);
302 array_of_requests[i] = TMPI_REQUEST_NULL;
315 tMPI_Profile_count_stop(cur, TMPIFN_Testall);
321 int tMPI_Waitany(int count, tMPI_Request *array_of_requests, int *index,
325 int ret = TMPI_SUCCESS;
326 struct tmpi_thread *cur = tMPI_Get_current();
327 struct req_list *rql = &(cur->rql);
329 tMPI_Profile_count_start(cur);
332 tMPI_Trace_print("tMPI_Waitany(%d, %p, %p, %p)", count, array_of_requests,
336 tMPI_Test_multi_req(cur, count, array_of_requests, TRUE, FALSE);
338 /* deallocate the possibly finished requests */
339 for (i = 0; i < count; i++)
341 if (array_of_requests[i] && array_of_requests[i]->finished)
343 tMPI_Set_status(array_of_requests[i], status);
348 if (array_of_requests[i]->error != TMPI_SUCCESS)
350 ret = TMPI_ERR_IN_STATUS;
352 tMPI_Return_req(rql, array_of_requests[i]);
353 array_of_requests[i] = TMPI_REQUEST_NULL;
354 /* and we only need one */
360 tMPI_Profile_count_stop(cur, TMPIFN_Waitany);
367 int tMPI_Testany(int count, tMPI_Request *array_of_requests, int *index,
368 int *flag, tMPI_Status *status)
371 int ret = TMPI_SUCCESS;
372 struct tmpi_thread *cur = tMPI_Get_current();
373 struct req_list *rql = &(cur->rql);
375 tMPI_Profile_count_start(cur);
378 tMPI_Trace_print("tMPI_Testany(%d, %p, %p %p, %p)", count,
379 array_of_requests, flag, index, status);
382 tMPI_Test_multi_req(cur, count, array_of_requests, FALSE, FALSE);
390 *index = TMPI_UNDEFINED;
392 /* deallocate the possibly finished requests */
393 for (i = 0; i < count; i++)
395 if (array_of_requests[i] && array_of_requests[i]->finished)
397 tMPI_Set_status(array_of_requests[i], status);
406 if (array_of_requests[i]->error != TMPI_SUCCESS)
408 ret = TMPI_ERR_IN_STATUS;
410 tMPI_Return_req(rql, array_of_requests[i]);
411 array_of_requests[i] = TMPI_REQUEST_NULL;
412 /* and we only need one */
418 tMPI_Profile_count_stop(cur, TMPIFN_Testany);
425 int tMPI_Waitsome(int incount, tMPI_Request *array_of_requests,
426 int *outcount, int *array_of_indices,
427 tMPI_Status *array_of_statuses)
430 int ret = TMPI_SUCCESS;
431 struct tmpi_thread *cur = tMPI_Get_current();
432 struct req_list *rql = &(cur->rql);
434 tMPI_Profile_count_start(cur);
437 tMPI_Trace_print("tMPI_Waitsome(%d, %p, %p, %p, %p)", incount,
438 array_of_requests, outcount, array_of_indices,
441 tMPI_Test_multi_req(cur, incount, array_of_requests, TRUE, FALSE);
444 /* deallocate the possibly finished requests */
445 for (i = 0; i < incount; i++)
447 if (array_of_requests[i] && array_of_requests[i]->finished)
449 array_of_indices[*outcount]++;
451 if (array_of_statuses)
453 tMPI_Set_status(array_of_requests[i], &(array_of_statuses[i]));
455 if (array_of_requests[i]->error != TMPI_SUCCESS)
457 ret = TMPI_ERR_IN_STATUS;
459 tMPI_Return_req(rql, array_of_requests[i]);
460 array_of_requests[i] = TMPI_REQUEST_NULL;
465 tMPI_Profile_count_stop(cur, TMPIFN_Waitsome);
470 int tMPI_Testsome(int incount, tMPI_Request *array_of_requests,
471 int *outcount, int *array_of_indices,
472 tMPI_Status *array_of_statuses)
475 int ret = TMPI_SUCCESS;
476 struct tmpi_thread *cur = tMPI_Get_current();
477 struct req_list *rql = &(cur->rql);
479 tMPI_Profile_count_start(cur);
482 tMPI_Trace_print("tMPI_Testsome(%d, %p, %p, %p, %p)", incount,
483 array_of_requests, outcount, array_of_indices,
486 tMPI_Test_multi_req(cur, incount, array_of_requests, FALSE, TRUE);
489 /* deallocate the possibly finished requests */
490 for (i = 0; i < incount; i++)
492 if (array_of_requests[i] && array_of_requests[i]->finished)
494 array_of_indices[*outcount]++;
496 if (array_of_statuses)
498 tMPI_Set_status(array_of_requests[i], &(array_of_statuses[i]));
500 if (array_of_requests[i]->error != TMPI_SUCCESS)
502 ret = TMPI_ERR_IN_STATUS;
504 tMPI_Return_req(rql, array_of_requests[i]);
505 array_of_requests[i] = TMPI_REQUEST_NULL;
511 tMPI_Profile_count_stop(cur, TMPIFN_Testsome);