diff --git a/arch/x86/include/asm/iRCCE.h b/arch/x86/include/asm/iRCCE.h index 7c071d5b..7300065c 100644 --- a/arch/x86/include/asm/iRCCE.h +++ b/arch/x86/include/asm/iRCCE.h @@ -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); diff --git a/arch/x86/include/asm/iRCCE.h.old b/arch/x86/include/asm/iRCCE.h.old new file mode 100644 index 00000000..7c071d5b --- /dev/null +++ b/arch/x86/include/asm/iRCCE.h.old @@ -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 + diff --git a/arch/x86/include/asm/iRCCE_lib.h b/arch/x86/include/asm/iRCCE_lib.h index 372b9cdd..ff020884 100644 --- a/arch/x86/include/asm/iRCCE_lib.h +++ b/arch/x86/include/asm/iRCCE_lib.h @@ -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 diff --git a/arch/x86/include/asm/iRCCE_lib.h.old b/arch/x86/include/asm/iRCCE_lib.h.old new file mode 100644 index 00000000..372b9cdd --- /dev/null +++ b/arch/x86/include/asm/iRCCE_lib.h.old @@ -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 +#include + +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 + diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h index 33316d2f..b3910e36 100644 --- a/arch/x86/include/asm/icc.h +++ b/arch/x86/include/asm/icc.h @@ -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 diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index f4cdc60b..4141dded 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -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 diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index 44dd8e61..70f62b1c 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -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) diff --git a/arch/x86/mm/svm.c b/arch/x86/mm/svm.c index 1dd2075f..eb31c08c 100644 --- a/arch/x86/mm/svm.c +++ b/arch/x86/mm/svm.c @@ -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; diff --git a/arch/x86/scc/iRCCE_admin.c b/arch/x86/scc/iRCCE_admin.c index 2a28f09e..9e59d2fb 100644 --- a/arch/x86/scc/iRCCE_admin.c +++ b/arch/x86/scc/iRCCE_admin.c @@ -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; inext; @@ -126,6 +137,7 @@ int iRCCE_finalize(void) { } iRCCE_mail_garbage.first = iRCCE_mail_garbage.last = NULL; + return iRCCE_SUCCESS; } #endif diff --git a/arch/x86/scc/iRCCE_admin.c.old b/arch/x86/scc/iRCCE_admin.c.old new file mode 100644 index 00000000..2a28f09e --- /dev/null +++ b/arch/x86/scc/iRCCE_admin.c.old @@ -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 + +#ifdef CONFIG_ROCKCREEK + +#include + +// 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; inext; + kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) ); + } + + iRCCE_mail_garbage.first = iRCCE_mail_garbage.last = NULL; + return iRCCE_SUCCESS; +} +#endif diff --git a/arch/x86/scc/iRCCE_isend.c b/arch/x86/scc/iRCCE_isend.c index 042de0ce..190ad939 100644 --- a/arch/x86/scc/iRCCE_isend.c +++ b/arch/x86/scc/iRCCE_isend.c @@ -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 ); } diff --git a/arch/x86/scc/iRCCE_mailbox.c b/arch/x86/scc/iRCCE_mailbox.c index 257a12c9..a0521317 100644 --- a/arch/x86/scc/iRCCE_mailbox.c +++ b/arch/x86/scc/iRCCE_mailbox.c @@ -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 @@ -30,6 +38,7 @@ #ifdef CONFIG_ROCKCREEK #include +#include /** * @@ -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; jsent = 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; inext; + 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; inext; + 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 ); diff --git a/arch/x86/scc/iRCCE_mailbox.c.old b/arch/x86/scc/iRCCE_mailbox.c.old new file mode 100644 index 00000000..47935533 --- /dev/null +++ b/arch/x86/scc/iRCCE_mailbox.c.old @@ -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 +#include + + +#ifdef CONFIG_ROCKCREEK +#include + +// 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; isent ) { + 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; inext; + 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; inext; + 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 #include +#define IRQ_STATUS 0xD000 +#define IRQ_MASK 0xD200 +#define IRQ_RESET 0xD400 +#define IRQ_REQUEST 0xD600 +#define IRQ_CONFIG 0xD800 + #include @@ -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; isource != 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; itag) - { - 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; jtag == 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 diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index be3fdd07..62717769 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -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 diff --git a/kernel/init.c b/kernel/init.c index 2d374f52..68ab79b5 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -221,7 +221,7 @@ int initd(void* arg) network_init(); list_root(); test_init(); - + return 0; } diff --git a/kernel/main.c b/kernel/main.c index 6a5b9e79..6a18cdc8 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -96,7 +96,7 @@ int main(void) while(1) { #ifdef CONFIG_ROCKCREEK - icc_halt(); + //icc_halt(); #else HALT; #endif diff --git a/kernel/syscall.c b/kernel/syscall.c index 6eaecd28..611b721e 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -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); diff --git a/kernel/tests.c b/kernel/tests.c index d51d645c..0fd7cde9 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -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); diff --git a/tools/metalsvm.mt b/tools/metalsvm.mt index e08b520d..ecb9a2c1 100644 --- a/tools/metalsvm.mt +++ b/tools/metalsvm.mt @@ -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 + +