Merge remote branch 'origin/mailbox_integration' into demo
This commit is contained in:
commit
c81c83e9ff
20 changed files with 1480 additions and 176 deletions
|
@ -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);
|
||||
|
|
201
arch/x86/include/asm/iRCCE.h.old
Normal file
201
arch/x86/include/asm/iRCCE.h.old
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
56
arch/x86/include/asm/iRCCE_lib.h.old
Normal file
56
arch/x86/include/asm/iRCCE_lib.h.old
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
131
arch/x86/scc/iRCCE_admin.c.old
Normal file
131
arch/x86/scc/iRCCE_admin.c.old
Normal 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
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
474
arch/x86/scc/iRCCE_mailbox.c.old
Normal file
474
arch/x86/scc/iRCCE_mailbox.c.old
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -221,7 +221,7 @@ int initd(void* arg)
|
|||
network_init();
|
||||
list_root();
|
||||
test_init();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ int main(void)
|
|||
|
||||
while(1) {
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
icc_halt();
|
||||
//icc_halt();
|
||||
#else
|
||||
HALT;
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue