/**************************************************************************************** * Functions for a convenient handling of multiple outstanding non-blocking requests **************************************************************************************** * * Authors: Jacek Galowicz, Carsten Clauss * Chair for Operating Systems, RWTH Aachen University * Date: 2010-12-09 * **************************************************************************************** * * Copyright 2010 Jacek Galowicz, Chair for Operating Systems, * RWTH Aachen University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "iRCCE_lib.h" void iRCCE_init_wait_list(iRCCE_WAIT_LIST *list) { list->first = NULL; list->last = NULL; } static void iRCCE_add_wait_list_generic(iRCCE_WAIT_LIST *list, iRCCE_WAIT_LISTELEM * elem) { if (list->first == NULL) { list->first = elem; list->last = elem; return; } list->last->next = elem; list->last = elem; } //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_add_recv_to_wait_list //-------------------------------------------------------------------------------------- // Function for adding Send requests to the waitall-queue //-------------------------------------------------------------------------------------- void iRCCE_add_send_to_wait_list(iRCCE_WAIT_LIST *list, iRCCE_SEND_REQUEST * req) { iRCCE_WAIT_LISTELEM *elem; elem = (iRCCE_WAIT_LISTELEM*)malloc(sizeof(iRCCE_WAIT_LISTELEM)); elem->type = iRCCE_WAIT_LIST_SEND_TYPE; elem->next = NULL; elem->req = (void*)req; iRCCE_add_wait_list_generic(list, elem); return; } //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_add_send_to_wait_list //-------------------------------------------------------------------------------------- // Function for adding Recv requests to the waitall-queue //-------------------------------------------------------------------------------------- void iRCCE_add_recv_to_wait_list(iRCCE_WAIT_LIST *list, iRCCE_RECV_REQUEST * req) { iRCCE_WAIT_LISTELEM *elem; elem = (iRCCE_WAIT_LISTELEM*)malloc(sizeof(iRCCE_WAIT_LISTELEM)); elem->type = iRCCE_WAIT_LIST_RECV_TYPE; elem->next = NULL; elem->req = (void*)req; iRCCE_add_wait_list_generic(list, elem); return; } //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_add_to_wait_list //-------------------------------------------------------------------------------------- // Function for adding Send and/or Recv requests to the waitall-queue //-------------------------------------------------------------------------------------- void iRCCE_add_to_wait_list(iRCCE_WAIT_LIST *list, iRCCE_SEND_REQUEST * send_req, iRCCE_RECV_REQUEST * recv_req) { if (send_req != NULL) iRCCE_add_send_to_wait_list(list, send_req); if (recv_req != NULL) iRCCE_add_recv_to_wait_list(list, recv_req); return; } //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_wait_all //-------------------------------------------------------------------------------------- // Blocking wait for completion of all enqueued send and recv calls //-------------------------------------------------------------------------------------- int iRCCE_wait_all(iRCCE_WAIT_LIST *list) { while(iRCCE_test_all(list, NULL) != iRCCE_SUCCESS) ; return iRCCE_SUCCESS; } //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_test_all //-------------------------------------------------------------------------------------- // Nonblocking test for completion of all enqueued send and recv calls // Just provide NULL instead of testvar if you don't need it //-------------------------------------------------------------------------------------- int iRCCE_test_all(iRCCE_WAIT_LIST *list, int *test) { int retval = iRCCE_SUCCESS; int req_state; iRCCE_WAIT_LISTELEM *pElem; iRCCE_WAIT_LISTELEM *pLastElem; iRCCE_WAIT_LISTELEM *pTemp; pLastElem = NULL; pElem = list->first; while (pElem != NULL) { if (pElem->type == iRCCE_WAIT_LIST_SEND_TYPE) req_state = iRCCE_isend_test((iRCCE_SEND_REQUEST*)pElem->req, NULL); else req_state = iRCCE_irecv_test((iRCCE_RECV_REQUEST*)pElem->req, NULL); if (req_state == iRCCE_SUCCESS) { // Remove this element from the list if (pElem == list->first) { list->first = pElem->next; } else if (pElem == list->last) { list->last = pLastElem; pLastElem->next = NULL; } else { pLastElem->next = pElem->next; } pTemp = pElem->next; free(pElem); pElem = pTemp; } else { retval = iRCCE_PENDING; pLastElem = pElem; pElem = pElem->next; } } if (test) { if (retval == iRCCE_SUCCESS) { (*test) = 1; } else { (*test) = 0; } } return retval; } //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_wait_any //-------------------------------------------------------------------------------------- // Blocking wait for completion of any enqueued send and recv request //-------------------------------------------------------------------------------------- int iRCCE_wait_any(iRCCE_WAIT_LIST *list, iRCCE_SEND_REQUEST ** send_request, iRCCE_RECV_REQUEST ** recv_request) { while(iRCCE_test_any(list, send_request, recv_request) != iRCCE_SUCCESS) ; return iRCCE_SUCCESS; } //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_test_any //-------------------------------------------------------------------------------------- // Nonblocking test for completion of any enqueued send or recv request //-------------------------------------------------------------------------------------- int iRCCE_test_any(iRCCE_WAIT_LIST *list, iRCCE_SEND_REQUEST ** send_request, iRCCE_RECV_REQUEST ** recv_request) { int req_state; iRCCE_WAIT_LISTELEM *pElem; iRCCE_WAIT_LISTELEM *pLastElem; iRCCE_WAIT_LISTELEM *pTemp; pLastElem = NULL; pElem = list->first; while (pElem != NULL) { if (pElem->type == iRCCE_WAIT_LIST_SEND_TYPE) req_state = iRCCE_isend_test((iRCCE_SEND_REQUEST*)pElem->req, NULL); else req_state = iRCCE_irecv_test((iRCCE_RECV_REQUEST*)pElem->req, NULL); if (req_state == iRCCE_SUCCESS) { // Remove this element from the list if (pElem == list->first) { list->first = pElem->next; } else if (pElem == list->last) { list->last = pLastElem; pLastElem->next = NULL; } else { pLastElem->next = pElem->next; } if (pElem->type == iRCCE_WAIT_LIST_SEND_TYPE) { if(send_request) { (*send_request) = (iRCCE_SEND_REQUEST*)pElem->req; } if(recv_request) { (*recv_request) = NULL; } } else { if(send_request) { (*send_request) = NULL; } if(recv_request) { (*recv_request) = (iRCCE_RECV_REQUEST*)pElem->req; } } pTemp = pElem->next; free(pElem); pElem = pTemp; return iRCCE_SUCCESS; } else { pLastElem = pElem; pElem = pElem->next; } } if(send_request) { (*send_request) = NULL; } if(recv_request) { (*recv_request) = NULL; } return iRCCE_PENDING; } //-------------------------------------------------------------------------------------- // FUNCTIONS: iRCCE_get_dest, iRCCE_get_source, iRCCE_get_length, iRCCE_get_status //-------------------------------------------------------------------------------------- // Functions to determine the respective sender/receiver after test_any() / wait_any() // (Can also be used after receiving a message via wildcard mechanism!) //-------------------------------------------------------------------------------------- int iRCCE_get_dest(iRCCE_SEND_REQUEST *request) { if(request != NULL) return request->dest; return iRCCE_ERROR; } //-------------------------------------------------------------------------------------- int iRCCE_get_source(iRCCE_RECV_REQUEST *request) { if(request != NULL) return request->source; return iRCCE_recent_source; } //-------------------------------------------------------------------------------------- int iRCCE_get_size(iRCCE_SEND_REQUEST * send_req, iRCCE_RECV_REQUEST * recv_req) { if(send_req != NULL) return send_req->size; if(recv_req != NULL) return recv_req->size; return iRCCE_recent_length; } //-------------------------------------------------------------------------------------- int iRCCE_get_length(void) { return iRCCE_recent_length; } //-------------------------------------------------------------------------------------- int iRCCE_get_status(iRCCE_SEND_REQUEST * send_req, iRCCE_RECV_REQUEST * recv_req) { if(send_req != NULL) { if(send_req->finished) { return(iRCCE_SUCCESS); } if(iRCCE_isend_queue != send_req) { return(iRCCE_RESERVED); } else { return(iRCCE_PENDING); } } if(recv_req != NULL) { if(recv_req->finished) { return(iRCCE_SUCCESS); } if(iRCCE_irecv_queue[recv_req->source] != recv_req) { return(iRCCE_RESERVED); } else { return(iRCCE_PENDING); } } return iRCCE_ERROR; }