added mailbox-system
This commit is contained in:
parent
ce6272ab6e
commit
683f36b83e
1 changed files with 360 additions and 0 deletions
360
arch/x86/scc/iRCCE_mailbox.c
Normal file
360
arch/x86/scc/iRCCE_mailbox.c
Normal file
|
@ -0,0 +1,360 @@
|
|||
//******************************************************************************
|
||||
// Mailbox system.
|
||||
//******************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//******************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// [2011-05-08] implemented mailbox send/recv routines
|
||||
// by Simon Pickartz, Chair for Operating Systems,
|
||||
// RWTH Aachen University
|
||||
//
|
||||
#include "iRCCE_lib.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mailbox_print_header
|
||||
//------------------------------------------------------------------------------
|
||||
// routine for printing given header (debugging purpose)
|
||||
//------------------------------------------------------------------------------
|
||||
void iRCCE_mailbox_print_header(iRCCE_MAIL_HEADER* header) {
|
||||
|
||||
printf( "\n"
|
||||
"-------------------------\n"
|
||||
"| RCK%d\n"
|
||||
"-------------------------\n"
|
||||
"| Sender\t: %d\t\n"
|
||||
"| Size\t\t: %d\t\n"
|
||||
"| Tag\t\t: %d\t\n"
|
||||
"| Prio\t\t: %d\t\n"
|
||||
"| Payload\t: %s\n"
|
||||
"-------------------------\n\n",
|
||||
RCCE_IAM, header->source,
|
||||
header->size, header->tag,
|
||||
header->prio, header->payload);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mailbox_enqueue_header
|
||||
//------------------------------------------------------------------------------
|
||||
// routine to put push received header into iRCCE_mailbox_recv_queue
|
||||
//------------------------------------------------------------------------------
|
||||
static int iRCCE_mail_fetch(
|
||||
int rank // rank from whom to empty mailbox
|
||||
) {
|
||||
|
||||
iRCCE_MAIL_HEADER* header;
|
||||
|
||||
// check for memory in garbage collection or allocate new
|
||||
if( iRCCE_mail_garbage.first ) {
|
||||
header = iRCCE_mail_garbage.first;
|
||||
iRCCE_mail_garbage.first =
|
||||
iRCCE_mail_garbage.first->next;
|
||||
|
||||
header->next = NULL;
|
||||
if( iRCCE_mail_garbage.first == NULL ) {
|
||||
iRCCE_mail_garbage.last = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
header = (iRCCE_MAIL_HEADER*)kmalloc(sizeof(iRCCE_MAIL_HEADER));
|
||||
}
|
||||
|
||||
|
||||
// copy header to allocated memory
|
||||
RC_cache_invalidate();
|
||||
iRCCE_memcpy_get( (void*)header, (void*)iRCCE_mailbox_recv[rank],
|
||||
RCCE_LINE_SIZE );
|
||||
|
||||
// check if received a last-mail
|
||||
if( header->tag == iRCCE_LAST_MAIL ) {
|
||||
iRCCE_last_mail[rank] = 1;
|
||||
iRCCE_mailbox_close( rank ); // we can close respective mailbox
|
||||
free( header );
|
||||
}
|
||||
else {
|
||||
// check mail priority
|
||||
int prio = header->prio;
|
||||
|
||||
// enqueue accordingly
|
||||
if( iRCCE_mailbox_recv_queue[prio] == NULL ) {
|
||||
iRCCE_mailbox_recv_queue[prio] = header;
|
||||
}
|
||||
else {
|
||||
iRCCE_MAIL_HEADER* run = iRCCE_mailbox_recv_queue[prio];
|
||||
while( run->next != NULL ) run = run->next;
|
||||
run->next = header;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mailbox_check
|
||||
//------------------------------------------------------------------------------
|
||||
// routine to check for new mail in mailboxes
|
||||
//------------------------------------------------------------------------------
|
||||
static int iRCCE_mailbox_check() {
|
||||
int i, j;
|
||||
int tmp;
|
||||
|
||||
for( i=0; i<RCCE_NP; ++i ) {
|
||||
// only check open mailboxes
|
||||
if( iRCCE_mailbox_status[i] == iRCCE_MAILBOX_OPEN ) {
|
||||
|
||||
RC_cache_invalidate();
|
||||
if( iRCCE_mailbox_recv[i]->sent ) {
|
||||
iRCCE_mail_fetch(i);
|
||||
|
||||
// reset senders flag
|
||||
RC_cache_invalidate();
|
||||
iRCCE_mailbox_recv[i]->sent = RCCE_FLAG_UNSET;
|
||||
*(int *)RCCE_fool_write_combine_buffer = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mail_recv
|
||||
//------------------------------------------------------------------------------
|
||||
// routine for fetching received headers out of iRCCE_mailbox_recv_queue
|
||||
//------------------------------------------------------------------------------
|
||||
int iRCCE_mail_recv(
|
||||
iRCCE_MAIL_HEADER** header // pointer to incoming header
|
||||
) { // (memory allocated by iRCCE)
|
||||
|
||||
int i;
|
||||
|
||||
// if there is no mail, check for incoming
|
||||
if ( !iRCCE_mailbox_recv_queue[0] ) {
|
||||
iRCCE_mailbox_check();
|
||||
}
|
||||
|
||||
// check priority queues
|
||||
for( i=0; i<iRCCE_PRIOS; ++i ) {
|
||||
if ( iRCCE_mailbox_recv_queue[i] ) {
|
||||
iRCCE_MAIL_HEADER* help_header =
|
||||
iRCCE_mailbox_recv_queue[i];
|
||||
iRCCE_mailbox_recv_queue[i] =
|
||||
iRCCE_mailbox_recv_queue[i]->next;
|
||||
help_header->next = NULL;
|
||||
|
||||
|
||||
*header = help_header;
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// no mail queued
|
||||
*header = NULL;
|
||||
return iRCCE_MAILBOX_EMPTY;
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mail_release
|
||||
//------------------------------------------------------------------------------
|
||||
// routine to free memory for given header
|
||||
//------------------------------------------------------------------------------
|
||||
int iRCCE_mail_release(
|
||||
iRCCE_MAIL_HEADER** header
|
||||
) {
|
||||
|
||||
// put header in garbage collection
|
||||
if( (iRCCE_mail_garbage.first == NULL)
|
||||
&& (iRCCE_mail_garbage.last == NULL ) ) {
|
||||
|
||||
iRCCE_mail_garbage.first = *header;
|
||||
iRCCE_mail_garbage.last = *header;
|
||||
}
|
||||
else {
|
||||
iRCCE_mail_garbage.last->next = *header;
|
||||
iRCCE_mail_garbage.last = *header;
|
||||
}
|
||||
iRCCE_mail_garbage.last->next = NULL;
|
||||
|
||||
// reset header
|
||||
*header = NULL;
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mail_send
|
||||
//------------------------------------------------------------------------------
|
||||
// routine for sending headers into receivers mailbox (blocking)
|
||||
//------------------------------------------------------------------------------
|
||||
int iRCCE_mail_send(
|
||||
size_t size, // size of following message expected to be send/received
|
||||
int tag, // tag to indicate message type
|
||||
char prio, // mail priority
|
||||
char* payload, // pointer to buffer for header payload
|
||||
int dest // UE that will receive the header
|
||||
) {
|
||||
|
||||
// if dest mailbox is full, check for incoming mail
|
||||
RC_cache_invalidate();
|
||||
while( iRCCE_mailbox_send[dest]->sent ) {
|
||||
iRCCE_mailbox_check();
|
||||
RC_cache_invalidate();
|
||||
}
|
||||
|
||||
// check if mailbox is closed
|
||||
RCCE_acquire_lock( dest );
|
||||
RC_cache_invalidate();
|
||||
if( iRCCE_mailbox_send[dest]->closed ) {
|
||||
RCCE_release_lock( dest );
|
||||
return iRCCE_MAILBOX_CLOSED;
|
||||
}
|
||||
|
||||
// prepare header
|
||||
iRCCE_MAIL_HEADER header = { RCCE_IAM, size, tag, NULL, prio,
|
||||
RCCE_FLAG_UNSET, RCCE_FLAG_UNSET,
|
||||
{[0 ... iRCCE_MAIL_HEADER_PAYLOAD-1] = 0} };
|
||||
|
||||
// payload within the header?
|
||||
if( payload ) {
|
||||
memcpy( header.payload, payload, iRCCE_MAIL_HEADER_PAYLOAD );
|
||||
}
|
||||
|
||||
// do the actual copy to MPB
|
||||
RC_cache_invalidate();
|
||||
iRCCE_memcpy_put( (void*)iRCCE_mailbox_send[dest],
|
||||
(void*)&header, RCCE_LINE_SIZE );
|
||||
|
||||
// set senders flag
|
||||
RC_cache_invalidate();
|
||||
iRCCE_mailbox_send[dest]->sent = RCCE_FLAG_SET;
|
||||
*(int *)RCCE_fool_write_combine_buffer = 1;
|
||||
RC_cache_invalidate();
|
||||
|
||||
RCCE_release_lock( dest );
|
||||
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_last_mail_recv
|
||||
//------------------------------------------------------------------------------
|
||||
// check if all final headers are received from all UEs
|
||||
//------------------------------------------------------------------------------
|
||||
int iRCCE_last_mail_recv(void) {
|
||||
int i;
|
||||
int res = iRCCE_SUCCESS;
|
||||
|
||||
for( i=0; i<RCCE_NP; ++i ) {
|
||||
if( iRCCE_last_mail[i] == 0 ) {
|
||||
res = iRCCE_LAST_MAILS_NOT_RECV;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mailbox_wait
|
||||
//------------------------------------------------------------------------------
|
||||
// wait for all last-mails to be received
|
||||
//------------------------------------------------------------------------------
|
||||
int iRCCE_mailbox_wait(void) {
|
||||
while( iRCCE_last_mail_recv() == iRCCE_LAST_MAILS_NOT_RECV ) {
|
||||
iRCCE_mailbox_check();
|
||||
}
|
||||
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mailbox_flush
|
||||
//------------------------------------------------------------------------------
|
||||
// dequeue all iRCCE_mailbox_recv_queue elements and free memory
|
||||
//------------------------------------------------------------------------------
|
||||
int iRCCE_mailbox_flush(void) {
|
||||
int i;
|
||||
|
||||
for( i=0; i<iRCCE_PRIOS; ++i ) {
|
||||
iRCCE_MAIL_HEADER* erase_header = iRCCE_mailbox_recv_queue[i];
|
||||
|
||||
while( erase_header != NULL ) {
|
||||
iRCCE_mailbox_recv_queue[i] = iRCCE_mailbox_recv_queue[i]->next;
|
||||
free( erase_header );
|
||||
erase_header = iRCCE_mailbox_recv_queue[i];
|
||||
}
|
||||
}
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mailbox_close_one
|
||||
//------------------------------------------------------------------------------
|
||||
// routine to close one mailbox
|
||||
//------------------------------------------------------------------------------
|
||||
static int iRCCE_mailbox_close_one(int rank) {
|
||||
RCCE_acquire_lock( RCCE_IAM );
|
||||
|
||||
// check if it contains new mail
|
||||
RC_cache_invalidate();
|
||||
if( iRCCE_mailbox_recv[rank]->sent ) {
|
||||
iRCCE_mail_fetch(rank);
|
||||
|
||||
}
|
||||
|
||||
// close mailbox
|
||||
iRCCE_MAIL_HEADER help_header = { 0, 0, 0, NULL, 0, RCCE_FLAG_UNSET,
|
||||
RCCE_FLAG_SET, {[0 ... iRCCE_MAIL_HEADER_PAYLOAD-1] = 0} };
|
||||
|
||||
RC_cache_invalidate();
|
||||
iRCCE_memcpy_put( (void*)iRCCE_mailbox_recv[rank],
|
||||
&help_header, RCCE_LINE_SIZE );
|
||||
|
||||
RCCE_release_lock( RCCE_IAM );
|
||||
|
||||
iRCCE_mailbox_status[rank] = iRCCE_MAILBOX_CLOSED;
|
||||
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_mailbox_close()
|
||||
//------------------------------------------------------------------------------
|
||||
// routine to close one or all mailboxes
|
||||
//------------------------------------------------------------------------------
|
||||
int iRCCE_mailbox_close(int rank) {
|
||||
if( rank == iRCCE_MAILBOX_ALL ) {
|
||||
int i;
|
||||
for( i=0; i<RCCE_NP; ++i ) {
|
||||
iRCCE_mailbox_close_one( i );
|
||||
}
|
||||
}
|
||||
else {
|
||||
iRCCE_mailbox_close_one( rank );
|
||||
}
|
||||
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
Loading…
Add table
Reference in a new issue