mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
325 lines
9.6 KiB
C
325 lines
9.6 KiB
C
![]() |
/****************************************************************************************
|
||
|
* 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;
|
||
|
}
|