Merge remote branch 'origin/mailbox_integration' into demo

This commit is contained in:
Stefan Lankes 2011-08-27 08:07:43 -07:00
commit c81c83e9ff
20 changed files with 1480 additions and 176 deletions

View file

@ -40,18 +40,22 @@
#define iRCCE_ANY_SOURCE -1
#define iRCCE_PRIOS 5
#define iRCCE_MAILBOX_EMPTY -2
#define iRCCE_LAST_MAILS_NOT_RECV -3
#define iRCCE_MAILBOX_ALL -4
#define iRCCE_MAILBOX_OPEN 0
#define iRCCE_MAILBOX_CLOSED 1
// status codes
#define iRCCE_ERROR_ID RCCE_ERROR_ID
#define iRCCE_MAILBOX_OPEN -1
#define iRCCE_MAILBOX_CLOSED -2
#define iRCCE_MAILBOX_INVALID -3
#define iRCCE_MAILBOX_EMPTY -4
#define iRCCE_LAST_MAILS_NOT_RECV -5
// iRCCE-mailbox-system tags
#define iRCCE_LAST_MAIL -1
#define iRCCE_LAST_MAIL -1
#define iRCCE_ANYLENGTH -2
#define iRCCE_ANYLENGTH_PIGGYBACK -3
typedef volatile char iRCCE_SHORT_FLAG;
typedef struct _iRCCE_SEND_REQUEST {
@ -112,21 +116,30 @@ typedef struct _iRCCE_WAIT_LIST {
#define iRCCE_MAIL_HEADER_PAYLOAD 13
/**
* @struct _iRCCE_MAIL_HEADER
* @brief mail that can be send/received by iRCCE_mail_send/iRCCE_mail_recv
*
* _iRCCE_MAIL_HEADER has exactly the size of one cacheline (32 byte). Create an
* object by using the iRCCE_MAIL_HEADER identifier.
*/
typedef struct _iRCCE_MAIL_HEADER {
int source; // UE that will send the header
size_t size; // size of the message which will be send/received
int tag; // tag indicating which kind of message we have
struct _iRCCE_MAIL_HEADER* next;// pointer for queue - could be replaced by list-object
char prio; // priority of the mail
iRCCE_SHORT_FLAG sent; // flag indicating that header is new
iRCCE_SHORT_FLAG closed; // flag indication that mailbox is closed
char payload[iRCCE_MAIL_HEADER_PAYLOAD]; // payload for small messages
/** @{ */
int source; /**< UE that will send the header */
size_t size; /**< size of the message which will be send/received */
int tag; /**< tag indicating which kind of message we have */
struct _iRCCE_MAIL_HEADER* next;/**< pointer for queue - could be replaced by list-object */
char prio; /**< priority of the mail */
iRCCE_SHORT_FLAG sent; /**< flag indicating that header is new */
iRCCE_SHORT_FLAG closed; /**< flag indication that mailbox is closed */
char payload[iRCCE_MAIL_HEADER_PAYLOAD]; /**< payload for small messages */
/** @} */
} iRCCE_MAIL_HEADER;
typedef struct _iRCCE_MAIL_TRASH_BIN {
typedef struct _iRCCE_MAIL_HEADER_LIST {
iRCCE_MAIL_HEADER* first;
iRCCE_MAIL_HEADER* last;
} iRCCE_MAIL_TRASH_BIN;
} iRCCE_MAIL_HEADER_LIST;
///////////////////////////////////////////////////////////////
//
@ -172,7 +185,8 @@ int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *, int *);
int iRCCE_mail_send(size_t, int, char, char*, int);
int iRCCE_mail_recv(iRCCE_MAIL_HEADER**);
//
// functions to empty mailbox-queue and to check for last mails:
// functions to empty mailbox-queue and to check for mails:
int iRCCE_mail_check(int);
int iRCCE_mail_release(iRCCE_MAIL_HEADER**);
int iRCCE_last_mail_recv(void);
int iRCCE_mailbox_wait(void);

View file

@ -0,0 +1,201 @@
//
// 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.
//
// [2010-10-25] added support for non-blocking send/recv operations
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
// by Carsten Clauss, Chair for Operating Systems,
// RWTH Aachen University
//
// [2010-11-12] extracted non-blocking code into separate library
// by Carsten Scholtes, University of Bayreuth
//
// [2010-12-09] added functions for a convenient handling of multiple
// pending non-blocking requests
// by Jacek Galowicz, Chair for Operating Systems
// RWTH Aachen University
//
#ifndef IRCCE_H
#define IRCCE_H
#include "RCCE.h"
#define iRCCE_SUCCESS RCCE_SUCCESS
#define iRCCE_PENDING -1
#define iRCCE_RESERVED -2
#define iRCCE_NOT_ENQUEUED -3
#define iRCCE_ANY_SOURCE -1
#define iRCCE_PRIOS 5
#define iRCCE_MAILBOX_EMPTY -2
#define iRCCE_LAST_MAILS_NOT_RECV -3
#define iRCCE_MAILBOX_ALL -4
#define iRCCE_MAILBOX_OPEN 0
#define iRCCE_MAILBOX_CLOSED 1
// iRCCE-mailbox-system tags
#define iRCCE_LAST_MAIL -1
#define iRCCE_ANYLENGTH -2
#define iRCCE_ANYLENGTH_PIGGYBACK -3
typedef volatile char iRCCE_SHORT_FLAG;
typedef struct _iRCCE_SEND_REQUEST {
char *privbuf; // source buffer in local private memory (send buffer)
t_vcharp combuf; // intermediate buffer in MPB
size_t chunk; // size of MPB available for this message (bytes)
RCCE_FLAG *ready; // flag indicating whether receiver is ready
RCCE_FLAG *sent; // flag indicating whether message has been sent by source
size_t size; // size of message (bytes)
int dest; // UE that will receive the message
size_t wsize; // offset within send buffer when putting in "chunk" bytes
size_t remainder; // bytes remaining to be sent
size_t nbytes; // number of bytes to be sent in single RCCE_put call
char *bufptr; // running pointer inside privbuf for current location
int label; // jump/goto label for the reentrance of the respective poll function
int finished; // flag that indicates whether the request has already been finished
struct _iRCCE_SEND_REQUEST *next;
} iRCCE_SEND_REQUEST;
typedef struct _iRCCE_RECV_REQUEST {
char *privbuf; // source buffer in local private memory (send buffer)
t_vcharp combuf; // intermediate buffer in MPB
size_t chunk; // size of MPB available for this message (bytes)
RCCE_FLAG *ready; // flag indicating whether receiver is ready
RCCE_FLAG *sent; // flag indicating whether message has been sent by source
size_t size; // size of message (bytes)
int source; // UE that will send the message
size_t wsize; // offset within send buffer when putting in "chunk" bytes
size_t remainder; // bytes remaining to be sent
size_t nbytes; // number of bytes to be sent in single RCCE_put call
char *bufptr; // running pointer inside privbuf for current location
int label; // jump/goto label for the reentrance of the respective poll function
int finished; // flag that indicates whether the request has already been finished
int started; // flag that indicates whether message parts have already been received
struct _iRCCE_RECV_REQUEST *next;
} iRCCE_RECV_REQUEST;
#define iRCCE_WAIT_LIST_RECV_TYPE 0
#define iRCCE_WAIT_LIST_SEND_TYPE 1
typedef struct _iRCCE_WAIT_LISTELEM {
int type;
struct _iRCCE_WAIT_LISTELEM * next;
void * req;
} iRCCE_WAIT_LISTELEM;
typedef struct _iRCCE_WAIT_LIST {
iRCCE_WAIT_LISTELEM * first;
iRCCE_WAIT_LISTELEM * last;
} iRCCE_WAIT_LIST;
#define iRCCE_MAIL_HEADER_PAYLOAD 13
typedef struct _iRCCE_MAIL_HEADER {
int source; // UE that will send the header
size_t size; // size of the message which will be send/received
int tag; // tag indicating which kind of message we have
struct _iRCCE_MAIL_HEADER* next;// pointer for queue - could be replaced by list-object
char prio; // priority of the mail
iRCCE_SHORT_FLAG sent; // flag indicating that header is new
iRCCE_SHORT_FLAG closed; // flag indication that mailbox is closed
char payload[iRCCE_MAIL_HEADER_PAYLOAD]; // payload for small messages
} iRCCE_MAIL_HEADER;
typedef struct _iRCCE_MAIL_TRASH_BIN {
iRCCE_MAIL_HEADER* first;
iRCCE_MAIL_HEADER* last;
} iRCCE_MAIL_TRASH_BIN;
///////////////////////////////////////////////////////////////
//
// THE iRCCE API:
//
// Initialize/Finalize functions:
int iRCCE_init(void);
int iRCCE_finalize(void);
//
// Non-blocking send/recv functions:
int iRCCE_isend(char *, ssize_t, int, iRCCE_SEND_REQUEST *);
int iRCCE_isend_test(iRCCE_SEND_REQUEST *, int *);
int iRCCE_isend_wait(iRCCE_SEND_REQUEST *);
int iRCCE_isend_push(void);
int iRCCE_irecv(char *, size_t, int, iRCCE_RECV_REQUEST *);
int iRCCE_irecv_test(iRCCE_RECV_REQUEST *, int *);
int iRCCE_irecv_wait(iRCCE_RECV_REQUEST *);
int iRCCE_irecv_push(void);
//
// Blocking but pipelined send/recv functions:
int iRCCE_send(char *, size_t, int);
int iRCCE_recv(char *, size_t, int);
//
// SCC-customized put/get and memcpy functions:
int iRCCE_put(t_vcharp, t_vcharp, int, int);
int iRCCE_get(t_vcharp, t_vcharp, int, int);
void* iRCCE_memcpy_put(void*, const void*, size_t);
void* iRCCE_memcpy_get(void*, const void*, size_t);
//
// Wait/test-all/any functions:
void iRCCE_init_wait_list(iRCCE_WAIT_LIST*);
void iRCCE_add_to_wait_list(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST *, iRCCE_RECV_REQUEST *);
int iRCCE_test_all(iRCCE_WAIT_LIST*, int *);
int iRCCE_wait_all(iRCCE_WAIT_LIST*);
int iRCCE_test_any(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST **, iRCCE_RECV_REQUEST **);
int iRCCE_wait_any(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST **, iRCCE_RECV_REQUEST **);
//
// Cancel functions for yet not started non-blocking requests:
int iRCCE_isend_cancel(iRCCE_SEND_REQUEST *, int *);
int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *, int *);
//
// Blocking send/recv functions for mailbox system
int iRCCE_mail_send(size_t, int, char, char*, int);
int iRCCE_mail_recv(iRCCE_MAIL_HEADER**);
//
// functions to empty mailbox-queue and to check for last mails:
int iRCCE_mail_release(iRCCE_MAIL_HEADER**);
int iRCCE_last_mail_recv(void);
int iRCCE_mailbox_wait(void);
int iRCCE_mailbox_flush(void);
int iRCCE_mailbox_close(int);
void iRCCE_mailbox_print_header(iRCCE_MAIL_HEADER*);
//
///////////////////////////////////////////////////////////////
//
// Just for for convenience:
#if 1
#define RCCE_isend iRCCE_isend
#define RCCE_isend_test iRCCE_isend_test
#define RCCE_isend_wait iRCCE_isend_wait
#define RCCE_isend_push iRCCE_isend_push
#define RCCE_irecv iRCCE_irecv
#define RCCE_irecv_test iRCCE_irecv_test
#define RCCE_irecv_wait iRCCE_irecv_wait
#define RCCE_irecv_push iRCCE_irecv_push
#define RCCE_SEND_REQUEST iRCCE_SEND_REQUEST
#define RCCE_RECV_REQUEST iRCCE_RECV_REQUEST
#endif
///////////////////////////////////////////////////////////////
#endif

View file

@ -36,7 +36,7 @@ extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP];
extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP];
// queue for received headers
extern iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
extern iRCCE_MAIL_HEADER_LIST iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
// flags for last mail
extern iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
@ -45,7 +45,8 @@ extern iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
extern iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP];
// garbage collection for mailbox
extern iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage;
extern iRCCE_MAIL_HEADER_LIST iRCCE_mail_garbage;
#ifdef _OPENMP
#pragma omp threadprivate (iRCCE_isend_queue, iRCCE_irecv_queue)
#endif

View file

@ -0,0 +1,56 @@
//
// 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.
//
// [2010-10-25] added support for non-blocking send/recv operations
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
// by Carsten Clauss, Chair for Operating Systems,
// RWTH Aachen University
//
// [2010-11-12] extracted non-blocking code into separate library
// by Carsten Scholtes
//
#ifndef IRCCE_LIB_H
#define IRCCE_LIB_H
#include <asm/iRCCE.h>
#include <asm/RCCE_lib.h>
extern iRCCE_SEND_REQUEST* iRCCE_isend_queue;
extern iRCCE_RECV_REQUEST* iRCCE_irecv_queue[RCCE_MAXNP];
extern iRCCE_RECV_REQUEST* iRCCE_irecv_any_source_queue;
// pointer to MPB-mailbox-space
extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP];
extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP];
// queue for received headers
extern iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
// flags for last mail
extern iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
// field to store open/closed status of mailboxes
extern iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP];
// garbage collection for mailbox
extern iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage;
#ifdef _OPENMP
#pragma omp threadprivate (iRCCE_isend_queue, iRCCE_irecv_queue)
#endif
int iRCCE_test_flag(RCCE_FLAG, RCCE_FLAG_STATUS, int *);
#endif

View file

@ -39,6 +39,13 @@ typedef struct {
extern bootinfo_t* bootinfo;
enum icc_mail_requests {
PING_REQ=1,
PING_RESP,
NOISE,
};
#define ICC_TAG_IP 0
#define ICC_TAG_SVMREQUEST 1
#define ICC_TAG_PINGREQUEST 2
@ -47,8 +54,11 @@ extern bootinfo_t* bootinfo;
int icc_init(void);
int icc_halt(void);
int icc_send_irq(int ue);
void icc_mail_check(void);
void icc_mail_check(int irq);
int icc_mail_ping(void);
int icc_irq_ping(void);
int icc_mail_ping_irq(void);
int icc_mail_noise(void);
#endif

View file

@ -234,8 +234,13 @@ void irq_handler(struct state *s)
/* This is a blank function pointer */
void (*handler) (struct state * s);
// at first, we check our work queues
check_workqueues();
// evaluate only irq status register if int_no = 124
if( s->int_no == 124 ) {
check_workqueues_rem_irq();
}
else {
check_workqueues();
}
/*
* Find out if we have a custom handler to run for this

View file

@ -92,6 +92,7 @@ static void timer_handler(struct state *s)
int timer_wait(unsigned int ticks)
{
uint64_t eticks = timer_ticks + ticks;
task_t* curr_task = per_core(current_task);
if (curr_task->status == TASK_IDLE)

View file

@ -128,7 +128,7 @@ int svm_access_request(size_t addr)
icc_send_irq(remote_rank);
/* check for incoming messages */
icc_mail_check();
icc_mail_check(0);
while (page_owner[pageid] != my_ue) {
NOP4;

View file

@ -55,10 +55,10 @@ volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP]; // store addresses f
volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP]; // store addresses for sending headeres
// mailbox recv queue
iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
iRCCE_MAIL_HEADER_LIST iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
// mail garbage queue
iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage;
iRCCE_MAIL_HEADER_LIST iRCCE_mail_garbage;
// flag indicating if last header was received
iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
@ -66,12 +66,19 @@ iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
// field to store open/closed status of mailboxes
iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP];
//--------------------------------------------------------------------------------------
// FUNCTION: iRCCE_init
//--------------------------------------------------------------------------------------
// initialize the library
/**
* @brief initialize the library
*
* To initialize the mailbox system the function calles RCCE_malloc() as often
* as there are UEs participating. As a result the respective mailboxes are
* located at the begin of the local MPB directly behind the space reserved for
* flags by RCCE_init(). In iRCCE_mailbox_recv[i] a pointer to the mailbox is
* saved respectively. To access the send mailboxes at the receiving UEs the
* coresponding pointers are saved in iRCCE_mailbox_send[i] resprectively.
*/
//--------------------------------------------------------------------------------------
int iRCCE_init(void) {
int i;
@ -93,8 +100,10 @@ int iRCCE_init(void) {
// init mail-priority lists
for( i=0; i<iRCCE_PRIOS; ++i ) {
iRCCE_mailbox_recv_queue[i] = NULL;
iRCCE_mailbox_recv_queue[i].first = NULL;
iRCCE_mailbox_recv_queue[i].last = NULL;
}
// allocate space in MPB for mailbox and set senders mailbox-pointer
for( i=0; i<RCCE_NP; i++ ) {
iRCCE_mailbox_recv[i] = (iRCCE_MAIL_HEADER*)RCCE_malloc(RCCE_LINE_SIZE);
@ -119,6 +128,8 @@ int iRCCE_finalize(void) {
iRCCE_MAIL_HEADER* run;
iRCCE_MAIL_HEADER* erase_header;
iRCCE_mailbox_flush();
for( run = iRCCE_mail_garbage.first; run != NULL; ) {
erase_header = run;
run = run->next;
@ -126,6 +137,7 @@ int iRCCE_finalize(void) {
}
iRCCE_mail_garbage.first = iRCCE_mail_garbage.last = NULL;
return iRCCE_SUCCESS;
}
#endif

View file

@ -0,0 +1,131 @@
//***************************************************************************************
// Administrative routines.
//***************************************************************************************
//
// 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.
//
// [2010-10-25] added support for non-blocking send/recv operations
// - iRCCE_isend(), ..._test(), ..._wait(), ..._push()
// - iRCCE_irecv(), ..._test(), ..._wait(), ..._push()
// by Carsten Clauss, Chair for Operating Systems,
// RWTH Aachen University
//
// [2010-11-12] extracted non-blocking code into separate library
// by Carsten Scholtes
//
// [2011-02-21] added support for multiple incoming queues
// (one recv queue per remote rank)
//
#include <metalsvm/stddef.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/iRCCE_lib.h>
// send request queue
iRCCE_SEND_REQUEST* iRCCE_isend_queue;
// recv request queue
iRCCE_RECV_REQUEST* iRCCE_irecv_queue[RCCE_MAXNP];
// recv request queue for those with source = iRCCE_ANY_SOURCE:
iRCCE_RECV_REQUEST* iRCCE_irecv_any_source_queue;
// mailbox in MPB
volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP]; // store addresses for receiving headers
volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP]; // store addresses for sending headeres
// mailbox recv queue
iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
// mail garbage queue
iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage;
// flag indicating if last header was received
iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
// field to store open/closed status of mailboxes
iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP];
//--------------------------------------------------------------------------------------
// FUNCTION: iRCCE_init
//--------------------------------------------------------------------------------------
// initialize the library
//--------------------------------------------------------------------------------------
int iRCCE_init(void) {
int i;
for(i=0; i<RCCE_MAXNP; i++) {
iRCCE_irecv_queue[i] = NULL;
iRCCE_mailbox_recv[i] = NULL;
iRCCE_mailbox_send[i] = NULL;
iRCCE_last_mail[i] = 0;
iRCCE_mailbox_status[i] = iRCCE_MAILBOX_OPEN;
}
iRCCE_isend_queue = NULL;
iRCCE_irecv_any_source_queue = NULL;
// init trash bin for mailbox
iRCCE_mail_garbage.first = NULL;
iRCCE_mail_garbage.last = NULL;
// init mail-priority lists
for( i=0; i<iRCCE_PRIOS; ++i ) {
iRCCE_mailbox_recv_queue[i] = NULL;
}
// allocate space in MPB for mailbox and set senders mailbox-pointer
for( i=0; i<RCCE_NP; i++ ) {
iRCCE_mailbox_recv[i] = (iRCCE_MAIL_HEADER*)RCCE_malloc(RCCE_LINE_SIZE);
}
for( i=0; i<RCCE_NP; i++ ) {
iRCCE_mailbox_send[i] = (iRCCE_MAIL_HEADER*)(RCCE_comm_buffer[i] + ((RCCE_buff_ptr - RCCE_comm_buffer[RCCE_IAM]) - (RCCE_NP-RCCE_IAM)*RCCE_LINE_SIZE ));
}
return (iRCCE_SUCCESS);
}
//--------------------------------------------------------------------------------------
// FUNCTION: iRCCE_finalize
//--------------------------------------------------------------------------------------
// finalize the library
//--------------------------------------------------------------------------------------
int iRCCE_finalize(void) {
// empty iRCCE_mail_garbage
iRCCE_MAIL_HEADER* run;
iRCCE_MAIL_HEADER* erase_header;
for( run = iRCCE_mail_garbage.first; run != NULL; ) {
erase_header = run;
run = run->next;
kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) );
}
iRCCE_mail_garbage.first = iRCCE_mail_garbage.last = NULL;
return iRCCE_SUCCESS;
}
#endif

View file

@ -244,18 +244,18 @@ int iRCCE_isend(
iRCCE_mail_send( send_size,
iRCCE_ANYLENGTH_PIGGYBACK,
0, privbuf, dest );
NOP8;
NOP8;
icc_send_irq( dest );
//NOP8;
//NOP8;
//send_irq( dest );
return iRCCE_SUCCESS;
}
// we need an extra isend-call
else {
iRCCE_mail_send( send_size, iRCCE_ANYLENGTH,
0, NULL, dest );
NOP8;
NOP8;
icc_send_irq( dest );
//NOP8;
//NOP8;
//send_irq( dest );
return iRCCE_isend_general( privbuf, send_size,
dest, request );
}

View file

@ -1,28 +1,36 @@
/*
* Copyright 2011 Simon Pickartz, 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.
*
* This file is part of MetalSVM.
*/
//******************************************************************************
// Mailbox system.
//******************************************************************************
//
// Author: Simon Pickartz,
// Chair for Operating Systems,
// RWTH Aachen University
// Date: 005/08/2011
//
//******************************************************************************
//
// 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.
//
//
/*
* Mailbox system
/**
*
* @file contains implementation of the mailbox system
* @author Simon Pickartz
*
*
* [2011-05-08] implemented mailbox send/recv routines
* by Simon Pickartz, Chair for Operating Systems,
* RWTH Aachen University
*/
#include <metalsvm/stdlib.h>
@ -30,6 +38,7 @@
#ifdef CONFIG_ROCKCREEK
#include <asm/iRCCE_lib.h>
#include <asm/irqflags.h>
/**
*
@ -89,7 +98,8 @@ void iRCCE_mailbox_print_header(iRCCE_MAIL_HEADER* header) {
static int iRCCE_mail_fetch(
int rank // rank from whom to empty mailbox
) {
/* interrupts should already be disabled! */
iRCCE_MAIL_HEADER* header;
// check for memory in garbage collection or allocate new
@ -109,7 +119,7 @@ static int iRCCE_mail_fetch(
// copy header to allocated memory
RC_cache_invalidate();
//RC_cache_invalidate();
iRCCE_memcpy_get( (void*)header, (void*)iRCCE_mailbox_recv[rank],
RCCE_LINE_SIZE );
@ -124,14 +134,17 @@ static int iRCCE_mail_fetch(
int prio = header->prio;
// enqueue accordingly
if( iRCCE_mailbox_recv_queue[prio] == NULL ) {
iRCCE_mailbox_recv_queue[prio] = header;
header->next = NULL;
if( iRCCE_mailbox_recv_queue[prio].first == NULL ) {
iRCCE_mailbox_recv_queue[prio].first = header;
iRCCE_mailbox_recv_queue[prio].last = header;
}
else {
iRCCE_MAIL_HEADER* run = iRCCE_mailbox_recv_queue[prio];
while( run->next != NULL ) run = run->next;
run->next = header;
iRCCE_mailbox_recv_queue[prio].last->next = header;
iRCCE_mailbox_recv_queue[prio].last = header;
}
}
@ -154,11 +167,19 @@ static int iRCCE_mail_fetch(
* write out the data.
*/
//------------------------------------------------------------------------------
static int iRCCE_mailbox_check() {
int i;
iRCCE_MAIL_HEADER dummy_header = {0, 0, 0, NULL, 0, 0, 0, {[0 ... iRCCE_MAIL_HEADER_PAYLOAD-1] = 0} };
static int iRCCE_mailbox_check() {
int i,j;
uint32_t flags;
/* disable interrupts */
flags = irq_nested_disable();
for( j=1; j<RCCE_NP; ++j ) {
i = (j+RCCE_IAM)%RCCE_NP;
for( i=0; i<RCCE_NP; ++i ) {
if( i == RCCE_IAM ) continue;
// only check open mailboxes
if( iRCCE_mailbox_status[i] == iRCCE_MAILBOX_OPEN ) {
@ -168,15 +189,73 @@ static int iRCCE_mailbox_check() {
// reset senders flag
RC_cache_invalidate();
iRCCE_mailbox_recv[i]->sent = RCCE_FLAG_UNSET;
*(int *)RCCE_fool_write_combine_buffer = 1;
*(iRCCE_mailbox_recv[i]) = dummy_header;
}
}
}
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS;
}
//------------------------------------------------------------------------------
// FUNCTION: iRCCE_mail_check
//------------------------------------------------------------------------------
/**
* @brief routine to check one specific mailbox
* @param sender is the core ID from which the mailbox is checked
*
* This function may be called by the user application to check one specific
* mailbox. It is recommended to use it in combination with an inter core
* interrupt.
*
*/
//------------------------------------------------------------------------------
int iRCCE_mail_check(int sender) {
uint32_t flags;
/* disable interrupts */
flags = irq_nested_disable();
// verify sender's ID
if( (sender < 0) || (sender > RCCE_NP) || (sender == RCCE_IAM) ) {
if( sender == iRCCE_MAILBOX_ALL ) {
iRCCE_mailbox_check();
return 0;
}
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_ERROR_ID;
}
// check if mailbox is open
if( iRCCE_mailbox_status[sender] == iRCCE_MAILBOX_CLOSED ) {
return iRCCE_MAILBOX_CLOSED;
}
RC_cache_invalidate();
if( iRCCE_mailbox_recv[sender]->sent ) {
iRCCE_mail_fetch(sender);
// reset senders flag
RC_cache_invalidate();
*(iRCCE_mailbox_recv[sender]) = dummy_header;
return iRCCE_SUCCESS;
}
else {
return iRCCE_MAILBOX_EMPTY;
}
/* enable interrupts */
irq_nested_enable(flags);
}
//------------------------------------------------------------------------------
// FUNCTION: iRCCE_mail_recv
//------------------------------------------------------------------------------
@ -198,28 +277,45 @@ int iRCCE_mail_recv(
) { // (memory allocated by iRCCE)
int i;
uint32_t flags;
iRCCE_MAIL_HEADER* help_header;
// if there is no mail, check for incoming
if ( !iRCCE_mailbox_recv_queue[0] ) {
/* if ( !iRCCE_mailbox_recv_queue[0].first ) {
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;
if ( iRCCE_mailbox_recv_queue[i].first ) {
/* disable interrupts */
flags = irq_nested_disable();
help_header = iRCCE_mailbox_recv_queue[i].first;
iRCCE_mailbox_recv_queue[i].first =
iRCCE_mailbox_recv_queue[i].first->next;
if( iRCCE_mailbox_recv_queue[i].first == NULL ) {
iRCCE_mailbox_recv_queue[i].last = NULL;
}
help_header->next = NULL;
*header = help_header;
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS;
}
}
// no mail queued
*header = NULL;
return iRCCE_MAILBOX_EMPTY;
}
@ -240,6 +336,11 @@ int iRCCE_mail_recv(
int iRCCE_mail_release(
iRCCE_MAIL_HEADER** header
) {
uint32_t flags;
/* disable interrupts */
flags = irq_nested_disable();
// put header in garbage collection
if( (iRCCE_mail_garbage.first == NULL)
&& (iRCCE_mail_garbage.last == NULL ) ) {
@ -255,6 +356,10 @@ int iRCCE_mail_release(
// reset header
*header = NULL;
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS;
}
@ -294,6 +399,12 @@ int iRCCE_mail_send(
char* payload, // pointer to buffer for header payload
int dest // UE that will receive the header
) {
uint32_t flags;
// check for an attempt to send to own mailbox
if( dest == RCCE_IAM ) {
return iRCCE_MAILBOX_INVALID;
}
// if dest mailbox is full, check for incoming mail
RC_cache_invalidate();
@ -329,10 +440,13 @@ int iRCCE_mail_send(
RC_cache_invalidate();
iRCCE_mailbox_send[dest]->sent = RCCE_FLAG_SET;
*(int *)RCCE_fool_write_combine_buffer = 1;
RC_cache_invalidate();
RC_cache_invalidate();
RCCE_release_lock( dest );
/* enable interrupts */
// irq_nested_enable(flags);
return iRCCE_SUCCESS;
}
@ -397,15 +511,21 @@ int iRCCE_mailbox_wait(void) {
//------------------------------------------------------------------------------
int iRCCE_mailbox_flush(void) {
int i;
uint32_t flags;
for( i=0; i<iRCCE_PRIOS; ++i ) {
iRCCE_MAIL_HEADER* erase_header = iRCCE_mailbox_recv_queue[i];
iRCCE_MAIL_HEADER* erase_header =
iRCCE_mailbox_recv_queue[i].first;
while( erase_header != NULL ) {
iRCCE_mailbox_recv_queue[i] = iRCCE_mailbox_recv_queue[i]->next;
iRCCE_mailbox_recv_queue[i].first =
iRCCE_mailbox_recv_queue[i].first->next;
kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) );
erase_header = iRCCE_mailbox_recv_queue[i];
erase_header = iRCCE_mailbox_recv_queue[i].first;
}
/* enable interrupts */
irq_nested_enable(flags);
}
return iRCCE_SUCCESS;
}
@ -422,16 +542,21 @@ int iRCCE_mailbox_flush(void) {
* last-mail.
*
* This function closes a mailbox of the given rank. If the check flag is set
* an iRCCE_mail_check()-call is performed. The close procedure has to be locked
* to be sure that no UE sends any mail while closing the mailbox.
* an iRCCE_mailbox_check()-call is performed. The close procedure has to be
* locked to be sure that no UE sends any mail while closing the mailbox.
*/
//------------------------------------------------------------------------------
static int iRCCE_mailbox_close_one(int rank, int check) {
uint32_t flags;
RCCE_acquire_lock( RCCE_IAM );
/* disable interrupts */
flags = irq_nested_disable();
// check if it contains new mail
RC_cache_invalidate();
if( check && iRCCE_mailbox_recv[rank]->sent ) {
iRCCE_mail_fetch(rank);
}
@ -443,6 +568,9 @@ static int iRCCE_mailbox_close_one(int rank, int check) {
RC_cache_invalidate();
iRCCE_memcpy_put( (void*)iRCCE_mailbox_recv[rank],
&help_header, RCCE_LINE_SIZE );
/* enable interrupts */
irq_nested_enable(flags);
RCCE_release_lock( RCCE_IAM );

View file

@ -0,0 +1,474 @@
/*
* Copyright 2011 Simon Pickartz, 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.
*
* This file is part of MetalSVM.
*/
/*
* Mailbox system
*
* [2011-05-08] implemented mailbox send/recv routines
* by Simon Pickartz, Chair for Operating Systems,
* RWTH Aachen University
*/
#include <metalsvm/stdlib.h>
#include <metalsvm/string.h>
#ifdef CONFIG_ROCKCREEK
#include <asm/iRCCE_lib.h>
// forward declaration
static int iRCCE_mailbox_close_one(int rank, int check);
//------------------------------------------------------------------------------
// FUNCTION: iRCCE_mailbox_print_header
//------------------------------------------------------------------------------
// routine for printing given header (debugging purpose)
//------------------------------------------------------------------------------
/**
* @brief routine for printing a given header
* @param header is a pointer to a given iRCCE_MAIL_HEADER structure
*/
void iRCCE_mailbox_print_header(iRCCE_MAIL_HEADER* header) {
kprintf( "\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_mail_fetch
//------------------------------------------------------------------------------
/**
* @brief routine to check for new mail in a given mailbox
* @param rank is the ID of the ranks mailbox to be emptied
*
* The function checks if the mailbox has new mail for a given rank. In case of
* new mail it needs memory for the received header. Either there is memory
* in the internal garbage collection or it has to allocated. The next step is
* to check wheter a last-mail was received or a normal one. A last-mail is
* indicated by the iRCCE_LAST_MAIL tag. A last-mail entails the appropriate
* flag in the iRCCE_last_mail array to be set. Otherwise the header has to be
* enqueued in the mailbox_recv_queue accordingly to the priority field.
*/
//------------------------------------------------------------------------------
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_one( rank, 0 ); // we can close respective mailbox
iRCCE_mail_release( &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
//------------------------------------------------------------------------------
/**
* @brief routine to check for new mail in mailboxes
*
* This function has to be called from time to time. It empties all mailboxes of
* the participating cores if the corresponding sent-flag is set and the mailbox
* is not closed. After calling iRCCE_mail_fetch the sent-flag has to be reset.
* Here we have to use a little trick because we can only write to the MPB in
* cacheline granularity. We set the appropriate flag to zero and afterwords
* touch the MPB on another cacheline. That causes the write combine buffer to
* write out the data.
*/
//------------------------------------------------------------------------------
static int iRCCE_mailbox_check() {
int i;
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
//------------------------------------------------------------------------------
/**
* @brief routine for fetching received headers out of iRCCE_mailbox_recv_queue
* @param header is the address of a pointer to an iRCCE_MAIL_HEADER structure
* @return iRCCE_SUCCESS if there was new mail; iRCCE_MAILBOX_EMPTY else
* @todo implement fairer dequeue mechanism
*
* The function checks if the receive queue with highest priority (priority 0)
* contains any mail headers. In this case we pop the first element of that list
* in a FIFO maner. Otherwise iRCCE_mailbox_check() has to be called. Afterwards
* the first element of a non-empty receive queue with highest priority is
* returned.
*/
//------------------------------------------------------------------------------
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
//------------------------------------------------------------------------------
/**
* @brief routine to store released header by user in garbage collection
* @param header is the address of a pointer to an iRCCE_MAIL_HEADER structure
* @return iRCCE_SUCCESS in any case
*
* This function enqueus a pointer to memory for an iRCCE_MAIL_HEADER structure
* that is not used by the user program anymore. 'header' points to NULL by
* return of the function.
*/
//------------------------------------------------------------------------------
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
//------------------------------------------------------------------------------
/**
* @brief routine to send a mail to a given destination (blocking)
* @param size is the size of the following message. This message may be
* contained in the payload or send by an isend()-call
* @param tag is an integer value to distinguish between different mail types
* @param prio indicates the priority of the mail. 0 is the highest priority
* whereas 4 is the lowest.
* @param payload is a pointer to byte array with a size of
* iRCCE_MAIL_HEADER_PAYLOAD. If NULL is passed nothing is done, otherwise array
* pointed by payload is copied into the header.
* @param dest indicates the destination of the mail in terms of the ID of
* one of the participating ranks
* @return iRCCE_SUCCESS if send was successful. If target mailbox is closed
* iRCCE_MAILBOX_CLOESD is returned.
*
* First it has to be checked if the target mailbox still contains an unread mail.
* If this is the case there is time to empty the own mailboxes. It blocks until
* the receiver has emptied its mailbox. The next step is to acquire the lock
* for the target mailbox to be sure that the mailbox is not closed by the
* receiver while the mail is delivered. After locking the mailbox an
* iRCCE_MAIL_HEADER is generated according with the parameters (but with a
* sent-flag set to zero)and is copied into the target mailbox. After all data
* beeing written the appropropriate sent-flag has to be set with the same trick
* already used in iRCCE_mail_check(). Now the lock can be released.
*/
//------------------------------------------------------------------------------
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
//------------------------------------------------------------------------------
/**
* @brief check if all final headers are received from all UEs
* @return iRCCE_SUCCES if all last-mails arrive iRCCE_LAST_MAILS_NOT_RECV
* otherwise
*
* This functions is used to determine if all last-mails arrived at the calling
* UE. Therefore it checks the iRCCE_last_mail array if all flags are set.
*/
//------------------------------------------------------------------------------
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
//------------------------------------------------------------------------------
/**
* @brief wait for all last-mails to be received
* @return iRCCE_SUCCESS
*
* This functions blocks in a loop calling continously iRCCE_last_mail_recv()
* until its return value is iRCCE_SUCCESS what implicates that all last-mails
* of the participating UEs arrived at the calling UE.
* This function is used to shut down the mailbox environment.
*/
//------------------------------------------------------------------------------
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
//------------------------------------------------------------------------------
/**
* @brief dequeue all iRCCE_mailbox_recv_queue elements and free memory
* @return iRCCE_SUCCESS
*
* This function empties all iRCCE_mailbox_recv_queues whith no regard to their
* content. This function is used to shut down the mailbox environment.
*/
//------------------------------------------------------------------------------
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;
kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) );
erase_header = iRCCE_mailbox_recv_queue[i];
}
}
return iRCCE_SUCCESS;
}
//------------------------------------------------------------------------------
// FUNCTION: iRCCE_mailbox_close_one
//------------------------------------------------------------------------------
/**
* @brief routine to close one mailbox
* @return iRCCE_SUCCESS
* @param rank is the ID of the ranks mailbox to be closed
* @param check is a flag indicating wether the mailbox has to be emptied before
* closing or not. This is required for a close-call as a result of a received
* last-mail.
*
* This function closes a mailbox of the given rank. If the check flag is set
* an iRCCE_mail_check()-call is performed. The close procedure has to be locked
* to be sure that no UE sends any mail while closing the mailbox.
*/
//------------------------------------------------------------------------------
static int iRCCE_mailbox_close_one(int rank, int check) {
RCCE_acquire_lock( RCCE_IAM );
// check if it contains new mail
RC_cache_invalidate();
if( check && 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()
//------------------------------------------------------------------------------
/**
* @brief routine to close one or all mailboxes
* @param rank is the ID of the UEs mailbox to be closed if iRCCE_MAILBOX_ALL
* is passed all mailboxes are closed by the calling UE
* @return iRCCE_SUCCESS
*
* This functions closed one or all mailboxes of the calling UE. This is done by
* calling iRCCE_mailbox_close_one for 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, 1 );
}
}
else {
iRCCE_mailbox_close_one( rank, 1 );
}
return iRCCE_SUCCESS;
}
#endif

View file

@ -27,6 +27,12 @@
#include <asm/icc.h>
#include <asm/svm.h>
#define IRQ_STATUS 0xD000
#define IRQ_MASK 0xD200
#define IRQ_RESET 0xD400
#define IRQ_REQUEST 0xD600
#define IRQ_CONFIG 0xD800
#include <net/mmnif.h>
@ -97,7 +103,7 @@ int icc_init(void)
{
int i, z, tmp;
uint64_t start, end, ticks, freq = 533;
uint32_t cr4, msg = 0;
uint32_t cr4;
kputs("Initialize Rock Creek!\n");
@ -198,6 +204,24 @@ int icc_init(void)
// set interrupt handler (INTR/LINT0)
irq_install_handler(124, intr_handler);
// unmask interrupts
volatile uint64_t* irq_mask = (volatile uint64_t*)(FPGA_BASE + IRQ_MASK + my_ue*8);
*irq_mask &= 0;
// reset interrupt reg
volatile uint64_t* irq_reset = (volatile uint64_t*)(FPGA_BASE + IRQ_RESET + my_ue*8);
*irq_reset = ~(0);
// set remote interrupts to LINT 0
volatile int* irq_config = (volatile int*)(FPGA_BASE + IRQ_CONFIG + my_ue*4);
*irq_config = 0;
volatile int* irq_status = (volatile int*)(FPGA_BASE + IRQ_STATUS + my_ue*8);
kprintf( "irq_mask = %x\n", *irq_mask );
kprintf( "irq_config = %x\n", *irq_config );
kprintf( "status_reg = %x\n", *irq_status );
kputs("Now, the SCC is initialized!\n");
return 0;
@ -225,108 +249,303 @@ int icc_send_irq(int ue)
int icc_halt(void)
{
uint32_t flags;
#if 0
uint32_t do_send = 1;
do {
// iRCCE is not thread save => disable interrupts
flags = irq_nested_disable();
if (do_send) {
do_send = (iRCCE_isend_push() == iRCCE_PENDING);
iRCCE_irecv_push();
}
icc_mail_check();
irq_nested_enable(flags);
NOP1;
} while(do_send);
#else
// iRCCE is not thread save => disable interrupts
flags = irq_nested_disable();
icc_mail_check();
irq_nested_enable(flags);
icc_mail_check(0);
NOP1;
#endif
//HALT;
return 0;
}
#define ROUNDS 100000
#define CORE_A 0 // sender
#define CORE_B 4 // receiver
int icc_send_gic_irq(int core_num) {
volatile uint64_t* irq_request = (volatile uint64_t*)(FPGA_BASE+IRQ_REQUEST+my_ue*8);
uint64_t bit_pos;
// determine bit position and set according bit
bit_pos = (1 << core_num);
*irq_request = bit_pos;
return 0;
}
int icc_irq_ping()
{
if( my_ue == 2 ) return -1 ;
icc_send_gic_irq(2);
kprintf( "my_ue = %d\n", my_ue );
kprintf( "sending irq to 1!\n");
return 0;
}
static inline void icc_mail_check_tag(iRCCE_MAIL_HEADER* mail) {
char* recv_buffer;
static int count = 0;
if( !mail ) return;
switch( mail->tag ) {
case iRCCE_ANYLENGTH:
recv_buffer = (char*)kmalloc( mail->size );
iRCCE_irecv(recv_buffer, mail->size,
mail->source, NULL );
break;
case PING_REQ:
// count++;
iRCCE_mail_send(0, PING_RESP, 0, NULL, mail->source);
break;
case NOISE:
// kprintf( "XXX " );
default:
// kprintf( "icc_mail_check_tag: uknown tag id %d\n", mail->tag );
break;
}
}
int icc_mail_ping( void )
{
uint32_t flags;
int remote_rank = (my_ue+1)%2;
uint8_t payload[iRCCE_MAIL_HEADER_PAYLOAD];
uint64_t* timer = (uint64_t*) payload;
uint64_t timer = 0;
int i;
int res;
iRCCE_MAIL_HEADER* recv_header = NULL;
if (my_ue)
return -1;
/* leave function if not participating in pingpong */
if( (my_ue != CORE_A) && (my_ue != CORE_B) ) return -1;
kprintf( "my_ue = %d\n", my_ue );
kprintf( "Hello from mail_ping ... \n" );
kprintf( "rounds = %d\n", ROUNDS );
// disable interrupts
flags = irq_nested_disable();
for( i=0; i<ROUNDS+1; ++i ) {
/* senders part */
if( my_ue == CORE_A ) {
/* send ping request */
iRCCE_mail_send(0, PING_REQ, 0, NULL, CORE_B);
// start timer
*timer = rdtsc();
/* wait for response */
do {
res = iRCCE_mail_check(CORE_B);
} while( res != iRCCE_SUCCESS );
/* send ping request */
iRCCE_mail_send(sizeof(uint64_t), ICC_TAG_PINGREQUEST, 0, payload, remote_rank);
recv_header = NULL;
/* release mail */
do {
if( recv_header ) iRCCE_mail_release(&recv_header);
res = iRCCE_mail_recv(&recv_header);
} while( (recv_header->source != CORE_B)
&& (recv_header->tag == PING_RESP) );
NOP8;
icc_send_irq(remote_rank);
/* release mail */
iRCCE_mail_release(&recv_header);
}
/* receivers part */
else {
/* wait for request */
do {
res = iRCCE_mail_check(CORE_A);
} while( res != iRCCE_SUCCESS );
res = iRCCE_mail_recv(&recv_header);
if( (res == iRCCE_SUCCESS) && (recv_header->tag = PING_REQ) );
/* check for incoming messages */
icc_mail_check();
/* send response */
iRCCE_mail_send(0, PING_RESP, 0, NULL, recv_header->source);
/* release mail */
iRCCE_mail_release(&recv_header);
}
/* start timer in first round */
if( i == 0 ) timer = rdtsc();
}
/* stop timer */
timer = rdtsc() - timer;
if( my_ue == CORE_A ) {
kprintf( "timer = %ld\n", timer );
kprintf( "mail_pingpong needs in average %d msec (%d ticks)!\n",
timer/(2*ROUNDS*533), timer/(2*ROUNDS) );
}
// enable interrupts
irq_nested_enable(flags);
return 0;
}
void icc_mail_check(void)
int icc_mail_ping_irq( void )
{
iRCCE_MAIL_HEADER* header = NULL;
uint64_t timer;
//char* recv_buffer;
kprintf( "Hello from mail_ping_irq ... \n" );
/* return if not core A */
if( my_ue != CORE_A ) return 0;
uint32_t flags;
uint64_t timer = 0;
int i;
int res;
iRCCE_MAIL_HEADER* recv_header = NULL;
// empty mailbox and interpret headers
while( iRCCE_mail_recv( &header ) == iRCCE_SUCCESS ) {
//iRCCE_mailbox_print_header(header);
kprintf( "my_rank = %d\n", my_ue );
kprintf( "rem_rank = %d\n", CORE_B );
kprintf( "rounds = %d\n", ROUNDS );
// disable interrupts
flags = irq_nested_disable();
for( i=0; i<ROUNDS+1; ++i ) {
/* send ping request */
iRCCE_mail_send(0, PING_REQ, 0, NULL, CORE_B);
switch(header->tag)
{
case ICC_TAG_PINGREQUEST:
iRCCE_mail_send( header->size, ICC_TAG_PINGRESPONSE, 0, header->payload, header->source );
NOP8;
icc_send_irq( header->source );
break;
case ICC_TAG_PINGRESPONSE:
timer = rdtsc() - *((uint64_t*) header->payload);
kprintf( "Response received in %d ticks!\n", timer );
break;
case ICC_TAG_SVMREQUEST:
svm_emit_page(((size_t*) header->payload)[1], ((size_t*) header->payload)[0]);
break;
default:
kprintf("Invalid mail: tag = %d\n", header->tag);
break;
}
/*else if( header->tag == iRCCE_ANYLENGTH ) {
recv_buffer = (char*)kmalloc( header->size );
iRCCE_irecv( recv_buffer, header->size, header->source, NULL );
iRCCE_mail_send( 0, 2, 0, NULL, header->source );
/* send interrupt */
icc_send_gic_irq(CORE_B);
/* wait for response */
do {
res = iRCCE_mail_check(CORE_B);
} while( res != iRCCE_SUCCESS );
iRCCE_mail_recv(&recv_header);
iRCCE_mail_release(&recv_header);
/* start timer in first round */
if( i == 0 ) timer = rdtsc();
}
/* stop timer */
timer = rdtsc() - timer;
kprintf( "timer = %d\n", timer );
kprintf( "mail_pingpong needs in average %d nsec (%d ticks)!\n",
timer*1000/(2*ROUNDS*533), timer/(2*ROUNDS) );
irq_nested_enable(flags);
return 0;
}
#define _iRQ_NOISE_ 0
int icc_mail_noise() {
int i, j, res;
int num_ranks = RCCE_num_ues();
iRCCE_MAIL_HEADER* recv_mail = NULL;
int flags;
// leave function if not participating
if( (my_ue == CORE_A) || (my_ue == CORE_B) ) {
kprintf( "mail_noise: leaving" );
return -1;
}
kprintf( "Hello from icc_mail_noise: my_ue = %d\n", my_ue );
kprintf( "num_ues = %d\n", num_ranks );
int count = 0;
for( ;; ++count ) {
if( !(count%1000) ) kprintf( "STILL ALIVE! " );
/* send a mail to each UE */
for( j=0; j<num_ranks; ++j ) {
if( (j == CORE_A) /*|| (j == CORE_B)*/ )
continue;
/* send noise mail */
iRCCE_mail_send(0, NOISE, 1, NULL, j);
#ifdef _IRQ_NOISE_
icc_send_gic_irq(j);
#endif
}
else if( header->tag == iRCCE_ANYLENGTH_PIGGYBACK ) {
iRCCE_mail_send( 0, 2, 0, NULL, header->source );
}*/
#ifndef _IRQ_NOISE_
/* read some mails */
flags = irq_nested_disable;
iRCCE_mail_check(iRCCE_MAILBOX_ALL);
while( iRCCE_mail_recv(&recv_mail) == iRCCE_SUCCESS ) {
icc_mail_check_tag(recv_mail);
iRCCE_mail_release(&recv_mail);
}
irq_nested_enable(flags);
#endif
}
return 0;
}
/*
* Routine to check mailboxes. If irq = 1 is passed only those boxes are checked that
* refere to the cores with set bit in status register.
*
*/
void icc_mail_check(int irq)
{
iRCCE_MAIL_HEADER* header = NULL;
int i, source, res;
volatile uint64_t* irq_status_reg = NULL;
volatile uint64_t* irq_reset_reg = NULL;
uint64_t irq_status = 0;
uint64_t irq_reset = 0;
uint32_t flags;
/* disable interrupts */
flags = irq_nested_disable();
if( irq == 1 ) {
// for( i=0; i<2; ++i ) {
/* read status register */
irq_status_reg = (volatile uint64_t*)(FPGA_BASE + IRQ_STATUS + my_ue*8);
irq_status = irq_reset = *irq_status_reg;
/* determine interrupt sources */
irq_status >>= 6; // shift emac bits
for( source = 0; irq_status != 0; irq_status >>= 1, ++source ) {
if( (irq_status & 0x1) != 0 ) {
res = iRCCE_mail_check(source);
}
}
/* reset status register */
irq_reset_reg = (volatile uint64_t*)(FPGA_BASE + IRQ_RESET + my_ue*8);
*irq_reset_reg = irq_reset;
// }
}
else {
iRCCE_mail_check(iRCCE_MAILBOX_ALL);
}
/* empty mail queue */
while( iRCCE_mail_recv(&header) == iRCCE_SUCCESS ) {
icc_mail_check_tag(header);
iRCCE_mail_release( &header );
}
/* enable interrupts */
irq_nested_enable(flags);
}
#endif

View file

@ -185,12 +185,16 @@ void reschedule(void);
static inline void check_workqueues(void)
{
#ifdef CONFIG_ROCKCREEK
uint32_t flags = irq_nested_disable();
icc_mail_check();
irq_nested_enable(flags);
icc_mail_check(0);
#endif
}
static inline void check_workqueues_rem_irq(void)
{
#ifdef CONFIG_ROCKCREEK
icc_mail_check(1);
#endif
}
#ifdef __cplusplus
}
#endif

View file

@ -221,7 +221,7 @@ int initd(void* arg)
network_init();
list_root();
test_init();
return 0;
}

View file

@ -96,7 +96,7 @@ int main(void)
while(1) {
#ifdef CONFIG_ROCKCREEK
icc_halt();
//icc_halt();
#else
HALT;
#endif

View file

@ -91,7 +91,7 @@ int syscall_handler(uint32_t sys_nr, ...)
int ret = -EINVAL;
va_list vl;
check_workqueues();
// check_workqueues();
va_start(vl, sys_nr);

View file

@ -103,15 +103,17 @@ static int foo(void* arg)
}
#ifdef CONFIG_ROCKCREEK
int mail_ping(void* arg) {
int i;
static int mail_ping(void* arg) {
// icc_mail_ping();
icc_mail_ping_irq();
// icc_irq_ping();
// icc_halt();
return 0;
}
for(i=0; i<20; i++) {
if (BUILTIN_EXPECT(icc_mail_ping(), 0))
return -1;
udelay(500000);
}
static int mail_noise(void*arg) {
icc_mail_noise(); // generate noise in the mesh
return 0;
}
@ -411,13 +413,11 @@ int test_init(void)
create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO);
create_kernel_task(NULL, join_test, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, producer, NULL);
//create_kernel_task(NULL, consumer, NULL);
//create_kernel_task(NULL, mail_ping, NULL);
//create_kernel_task(NULL, svm_test, NULL);
//create_kernel_task(NULL, producer, , NORMAL_PRIO);
//create_kernel_task(NULL, consumer, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, mail_ping, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, mail_noise, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, svm_test, NULL, NORMAL_PRIO);
//create_user_task(NULL, "/bin/hello", argv);
create_user_task(NULL, "/bin/tests", argv);
//create_user_task(NULL, "/bin/jacobi", argv);

View file

@ -1,3 +1,51 @@
# pid mch-route mch-dest-id mch-offset-base testcase
0x00 0x00 6 0x00 metalsvm.obj
0x01 0x00 6 0x01 metalsvm.obj
0 metalsvm.obj
1 metalsvm.obj
2 metalsvm.obj
3 metalsvm.obj
4 metalsvm.obj
5 metalsvm.obj
6 metalsvm.obj
7 metalsvm.obj
8 metalsvm.obj
9 metalsvm.obj
10 metalsvm.obj
11 metalsvm.obj
12 metalsvm.obj
13 metalsvm.obj
14 metalsvm.obj
15 metalsvm.obj
16 metalsvm.obj
17 metalsvm.obj
18 metalsvm.obj
19 metalsvm.obj
20 metalsvm.obj
21 metalsvm.obj
22 metalsvm.obj
23 metalsvm.obj
24 metalsvm.obj
25 metalsvm.obj
26 metalsvm.obj
27 metalsvm.obj
28 metalsvm.obj
29 metalsvm.obj
30 metalsvm.obj
31 metalsvm.obj
32 metalsvm.obj
33 metalsvm.obj
34 metalsvm.obj
35 metalsvm.obj
36 metalsvm.obj
37 metalsvm.obj
38 metalsvm.obj
39 metalsvm.obj
40 metalsvm.obj
41 metalsvm.obj
42 metalsvm.obj
43 metalsvm.obj
44 metalsvm.obj
45 metalsvm.obj
46 metalsvm.obj
47 metalsvm.obj