1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00
libhermit/usr/ircce/iRCCE_waitlist.c

325 lines
9.6 KiB
C
Raw Permalink Normal View History

/****************************************************************************************
* 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;
}