Merge branch 'master' into network
This commit is contained in:
commit
227031a41c
22 changed files with 1111 additions and 204 deletions
|
@ -30,12 +30,29 @@
|
|||
#ifndef IRCCE_H
|
||||
#define IRCCE_H
|
||||
|
||||
#include <asm/RCCE.h>
|
||||
#include "RCCE.h"
|
||||
|
||||
#define iRCCE_SUCCESS RCCE_SUCCESS
|
||||
#define iRCCE_PENDING -1
|
||||
#define iRCCE_RESERVED -2
|
||||
#define iRCCE_NOT_ENQUEUED -3
|
||||
#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)
|
||||
|
@ -94,15 +111,33 @@ typedef struct _iRCCE_WAIT_LIST {
|
|||
} 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 function:
|
||||
// Initialize/Finalize functions:
|
||||
int iRCCE_init(void);
|
||||
int iRCCE_finalize(void);
|
||||
//
|
||||
// Non-blocking send/recv functions:
|
||||
int iRCCE_isend(char *, size_t, int, iRCCE_SEND_REQUEST *);
|
||||
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);
|
||||
|
@ -133,6 +168,18 @@ int iRCCE_wait_any(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST **, iRCCE_RECV_REQUEST
|
|||
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:
|
||||
|
|
|
@ -29,6 +29,23 @@
|
|||
|
||||
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
|
||||
|
|
|
@ -39,21 +39,17 @@ typedef struct {
|
|||
|
||||
extern bootinfo_t* bootinfo;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t tag;
|
||||
uint32_t length;
|
||||
} icc_header_t;
|
||||
|
||||
#define ICC_TYPE_IP (1 << 0)
|
||||
#define ICC_TYPE_SVM (1 << 1)
|
||||
#define ICC_TYPE_PINGREQUEST (1 << 2)
|
||||
#define ICC_TYPE_PINGRESPONSE (1 << 3)
|
||||
#define ICC_TAG_IP 0
|
||||
#define ICC_TAG_SVM 1
|
||||
#define ICC_TAG_PINGREQUEST 2
|
||||
#define ICC_TAG_PINGRESPONSE 3
|
||||
|
||||
int icc_init(void);
|
||||
int icc_ping(int ue);
|
||||
void icc_check(void);
|
||||
int icc_halt(void);
|
||||
int icc_send_irq(int ue);
|
||||
void icc_mail_check(void);
|
||||
int icc_mail_ping(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -93,6 +93,11 @@ inline static void outportl(unsigned short _port, unsigned int _data)
|
|||
asm volatile("outl %1, %0"::"dN"(_port), "a"(_data));
|
||||
}
|
||||
|
||||
inline static void uart_putchar(unsigned char _data)
|
||||
{
|
||||
outportb(0x2F8, _data);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -235,7 +235,9 @@ void irq_handler(struct state *s)
|
|||
void (*handler) (struct state * s);
|
||||
|
||||
// at first, we check our work queues
|
||||
check_workqueues();
|
||||
// if( s->int_no == 124 ) {
|
||||
check_workqueues();
|
||||
// }
|
||||
|
||||
/*
|
||||
* Find out if we have a custom handler to run for this
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/time.h>
|
||||
#include <metalsvm/processor.h>
|
||||
#include <metalsvm/tasks.h>
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/RCCE_lib.h>
|
||||
#endif
|
||||
|
@ -104,6 +105,8 @@ void udelay(uint32_t usecs)
|
|||
mb();
|
||||
end = rdtsc();
|
||||
diff = end > start ? end - start : start - end;
|
||||
if ((diff < deadline) && (deadline - diff > 50000))
|
||||
check_workqueues();
|
||||
} while(diff < deadline);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
C_source := icc.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c
|
||||
C_source := icc.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c iRCCE_mailbox.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c
|
||||
ASM_source :=
|
||||
MODULE := arch_x86_scc
|
||||
|
||||
|
|
|
@ -47,6 +47,27 @@ 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
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
@ -56,12 +77,55 @@ int iRCCE_init(void) {
|
|||
int i;
|
||||
|
||||
for(i=0; i<RCCE_MAXNP; i++) {
|
||||
iRCCE_irecv_queue[i] = NULL;
|
||||
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
|
||||
|
|
|
@ -50,7 +50,9 @@ static int iRCCE_push_recv_request(iRCCE_RECV_REQUEST *request) {
|
|||
char padline[RCCE_LINE_SIZE]; // copy buffer, used if message not multiple of line size
|
||||
int test; // flag for calling iRCCE_test_flag()
|
||||
|
||||
if(request->finished) return(iRCCE_SUCCESS);
|
||||
if(request->finished) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if(request->label == 1) goto label1;
|
||||
if(request->label == 2) goto label2;
|
||||
|
@ -167,6 +169,25 @@ static void iRCCE_init_recv_request(
|
|||
return;
|
||||
}
|
||||
|
||||
int iRCCE_irecv_search_source() {
|
||||
int i, j;
|
||||
int res =iRCCE_ANY_SOURCE;
|
||||
|
||||
for( i=0; i<RCCE_NP*3; ++i ){
|
||||
j =i%RCCE_NP;
|
||||
if ( j == RCCE_IAM )
|
||||
continue;
|
||||
|
||||
// only take source if recv-queue is empty
|
||||
if( (!iRCCE_irecv_queue[j]) && (RCCE_probe(RCCE_sent_flag[j])) ) {
|
||||
res = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_irecv
|
||||
|
@ -176,7 +197,48 @@ static void iRCCE_init_recv_request(
|
|||
static iRCCE_RECV_REQUEST blocking_irecv_request;
|
||||
int iRCCE_irecv(char *privbuf, size_t size, int source, iRCCE_RECV_REQUEST *request) {
|
||||
|
||||
if(request == NULL) request = &blocking_irecv_request;
|
||||
if(request == NULL){
|
||||
request = &blocking_irecv_request;
|
||||
|
||||
// find source (blocking)
|
||||
if( source == iRCCE_ANY_SOURCE ){
|
||||
int i, res;
|
||||
for( i=0;;i=(++i)%RCCE_NP ){
|
||||
if ( (!iRCCE_irecv_queue[i]) && (i != RCCE_IAM) && (res = RCCE_probe(RCCE_sent_flag[i])) ){
|
||||
source = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( source == iRCCE_ANY_SOURCE ) {
|
||||
source = iRCCE_irecv_search_source(); // first try to find a source
|
||||
|
||||
if( source == iRCCE_ANY_SOURCE ){ // queue request if no source available
|
||||
|
||||
iRCCE_init_recv_request(privbuf, RCCE_buff_ptr, RCCE_chunk,
|
||||
&RCCE_ready_flag[RCCE_IAM], NULL,
|
||||
size, iRCCE_ANY_SOURCE, request);
|
||||
|
||||
// put anysource-request in irecv_any_source_queue
|
||||
if( iRCCE_irecv_any_source_queue == NULL ){
|
||||
iRCCE_irecv_any_source_queue = request;
|
||||
}
|
||||
else {
|
||||
if( iRCCE_irecv_any_source_queue->next == NULL ) {
|
||||
iRCCE_irecv_any_source_queue->next = request;
|
||||
}
|
||||
else {
|
||||
iRCCE_RECV_REQUEST* run = iRCCE_irecv_any_source_queue;
|
||||
while( run->next != NULL ) run = run->next;
|
||||
run->next = request;
|
||||
}
|
||||
}
|
||||
return iRCCE_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
if (source<0 || source >= RCCE_NP)
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
|
@ -211,10 +273,10 @@ int iRCCE_irecv(char *privbuf, size_t size, int source, iRCCE_RECV_REQUEST *requ
|
|||
run->next = request;
|
||||
}
|
||||
|
||||
if(request == &blocking_irecv_request) {
|
||||
iRCCE_irecv_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
if(request == &blocking_irecv_request) {
|
||||
iRCCE_irecv_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
|
@ -243,29 +305,98 @@ int iRCCE_irecv_test(iRCCE_RECV_REQUEST *request, int *test) {
|
|||
}
|
||||
}
|
||||
|
||||
source = request->source;
|
||||
// does request still have no source?
|
||||
if( request->source == iRCCE_ANY_SOURCE ) {
|
||||
request->source = iRCCE_irecv_search_source();
|
||||
|
||||
if(request->finished) {
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
if( request->source == iRCCE_ANY_SOURCE ) {
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_RESERVED;
|
||||
}
|
||||
else { // take request out of wait_any_source-list
|
||||
|
||||
// find request in queue
|
||||
if( request == iRCCE_irecv_any_source_queue ) {
|
||||
iRCCE_irecv_any_source_queue = iRCCE_irecv_any_source_queue->next;
|
||||
}
|
||||
else {
|
||||
iRCCE_RECV_REQUEST* run = iRCCE_irecv_any_source_queue;
|
||||
while( run->next != request ) run = run->next;
|
||||
run->next = request->next;
|
||||
}
|
||||
|
||||
request->next = NULL;
|
||||
request->sent = &RCCE_sent_flag[request->source]; // set senders flag
|
||||
source = request->source;
|
||||
|
||||
// queue request in iRCCE_irecv_queue
|
||||
if(iRCCE_irecv_queue[source] == NULL) {
|
||||
|
||||
if(iRCCE_push_recv_request(request) == iRCCE_SUCCESS) {
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
else {
|
||||
iRCCE_irecv_queue[source] = request;
|
||||
|
||||
if(request == &blocking_irecv_request) {
|
||||
iRCCE_irecv_wait(request);
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(iRCCE_irecv_queue[source]->next == NULL) {
|
||||
iRCCE_irecv_queue[source]->next = request;
|
||||
}
|
||||
else {
|
||||
iRCCE_RECV_REQUEST *run = iRCCE_irecv_queue[source];
|
||||
while(run->next != NULL) run = run->next;
|
||||
run->next = request;
|
||||
}
|
||||
|
||||
if(request == &blocking_irecv_request) {
|
||||
iRCCE_irecv_wait(request);
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
source = request->source;
|
||||
|
||||
if(request->finished) {
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if(iRCCE_irecv_queue[source] != request) {
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
|
||||
iRCCE_push_recv_request(request);
|
||||
|
||||
if(request->finished) {
|
||||
iRCCE_irecv_queue[source] = request->next;
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if(iRCCE_irecv_queue[source] != request) {
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_RESERVED);
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
|
||||
iRCCE_push_recv_request(request);
|
||||
|
||||
if(request->finished) {
|
||||
iRCCE_irecv_queue[source] = request->next;
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
if (test) (*test) = 0;
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
|
||||
|
||||
|
@ -297,6 +428,40 @@ static int iRCCE_irecv_push_source(int source) {
|
|||
}
|
||||
|
||||
int iRCCE_irecv_push(void) {
|
||||
iRCCE_RECV_REQUEST* help_request;
|
||||
|
||||
// first check sourceless requests
|
||||
if( iRCCE_irecv_any_source_queue != NULL) {
|
||||
while( iRCCE_irecv_any_source_queue != NULL ) {
|
||||
iRCCE_irecv_any_source_queue->source = iRCCE_irecv_search_source();
|
||||
|
||||
if( iRCCE_irecv_any_source_queue->source == iRCCE_ANY_SOURCE ) {
|
||||
|
||||
break;
|
||||
}
|
||||
// source found for first request in iRCCE_irecv_any_source_queue
|
||||
else {
|
||||
// set senders flag
|
||||
iRCCE_irecv_any_source_queue->sent = &RCCE_sent_flag[iRCCE_irecv_any_source_queue->source];
|
||||
|
||||
// take request out of irecv_any_source_queue
|
||||
help_request = iRCCE_irecv_any_source_queue;
|
||||
iRCCE_irecv_any_source_queue = iRCCE_irecv_any_source_queue->next;
|
||||
help_request->next = NULL;
|
||||
|
||||
// put request into irecv_queue
|
||||
if(iRCCE_irecv_queue[help_request->source] == NULL) {
|
||||
iRCCE_irecv_queue[help_request->source] = help_request;
|
||||
}
|
||||
else {
|
||||
iRCCE_RECV_REQUEST *run = iRCCE_irecv_queue[help_request->source];
|
||||
while(run->next != NULL) run = run->next;
|
||||
run->next = help_request;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int i, j;
|
||||
int retval = iRCCE_SUCCESS;
|
||||
|
@ -310,7 +475,7 @@ int iRCCE_irecv_push(void) {
|
|||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
return (iRCCE_irecv_any_source_queue == NULL)? retval : iRCCE_RESERVED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
@ -352,6 +517,24 @@ int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *request, int *test) {
|
|||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
|
||||
// does request have any source specified?
|
||||
if( request->source == iRCCE_ANY_SOURCE ) {
|
||||
for( run = iRCCE_irecv_any_source_queue; run->next != NULL; run = run->next ) {
|
||||
if( run->next == request ) {
|
||||
run->next = run->next->next;
|
||||
|
||||
if (test) (*test) = 1;
|
||||
return iRCCE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (test) (*test) = 0;
|
||||
return iRCCE_NOT_ENQUEUED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
source = request->source;
|
||||
|
||||
if(iRCCE_irecv_queue[source] == NULL) {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//***************************************************************************************
|
||||
//******************************************************************************
|
||||
// Non-blocking send routines.
|
||||
//***************************************************************************************
|
||||
//******************************************************************************
|
||||
//
|
||||
// Author: Rob F. Van der Wijngaart
|
||||
// Intel Corporation
|
||||
// Date: 008/30/2010
|
||||
//
|
||||
//***************************************************************************************
|
||||
//******************************************************************************
|
||||
//
|
||||
// Copyright 2010 Intel Corporation
|
||||
//
|
||||
|
@ -34,6 +34,8 @@
|
|||
// [2010-12-09] added cancel functions for non-blocking send/recv requests
|
||||
// by Carsten Clauss
|
||||
//
|
||||
// [2011-06-29] added the support of using IPIs
|
||||
// by Simon Pickartz, Stefan Lankes
|
||||
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
|
@ -41,6 +43,8 @@
|
|||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#include <asm/iRCCE_lib.h>
|
||||
#include <asm/SCC_API.h>
|
||||
#include <asm/icc.h>
|
||||
|
||||
static int iRCCE_push_send_request(iRCCE_SEND_REQUEST *request) {
|
||||
|
||||
|
@ -158,56 +162,121 @@ static void iRCCE_init_send_request(
|
|||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_isend
|
||||
// FUNCTION: iRCCE_isend_general
|
||||
//--------------------------------------------------------------------------------------
|
||||
// non-blocking send function; returns a handle of type iRCCE_SEND_REQUEST
|
||||
//--------------------------------------------------------------------------------------
|
||||
static iRCCE_SEND_REQUEST blocking_isend_request;
|
||||
int iRCCE_isend(char *privbuf, size_t size, int dest, iRCCE_SEND_REQUEST *request) {
|
||||
static int iRCCE_isend_general(char *privbuf, size_t size, int dest, iRCCE_SEND_REQUEST *request) {
|
||||
|
||||
if(request == NULL) request = &blocking_isend_request;
|
||||
|
||||
if (dest<0 || dest >= RCCE_NP)
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
else {
|
||||
iRCCE_init_send_request(privbuf, RCCE_buff_ptr, RCCE_chunk,
|
||||
&RCCE_ready_flag[dest], &RCCE_sent_flag[RCCE_IAM],
|
||||
size, dest, request);
|
||||
|
||||
if(iRCCE_isend_queue == NULL) {
|
||||
iRCCE_init_send_request(privbuf, RCCE_buff_ptr, RCCE_chunk,
|
||||
&RCCE_ready_flag[dest], &RCCE_sent_flag[RCCE_IAM],
|
||||
size, dest, request);
|
||||
|
||||
if(iRCCE_push_send_request(request) == iRCCE_SUCCESS) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
else {
|
||||
iRCCE_isend_queue = request;
|
||||
if(iRCCE_isend_queue == NULL) {
|
||||
|
||||
if(request == &blocking_isend_request) {
|
||||
iRCCE_isend_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
if(iRCCE_push_send_request(request) == iRCCE_SUCCESS) {
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
else {
|
||||
if(iRCCE_isend_queue->next == NULL) {
|
||||
iRCCE_isend_queue->next = request;
|
||||
}
|
||||
else {
|
||||
iRCCE_SEND_REQUEST *run = iRCCE_isend_queue;
|
||||
while(run->next != NULL) run = run->next;
|
||||
run->next = request;
|
||||
}
|
||||
iRCCE_isend_queue = request;
|
||||
|
||||
if(request == &blocking_isend_request) {
|
||||
iRCCE_isend_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_RESERVED);
|
||||
return(iRCCE_PENDING);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(iRCCE_isend_queue->next == NULL) {
|
||||
iRCCE_isend_queue->next = request;
|
||||
}
|
||||
else {
|
||||
iRCCE_SEND_REQUEST *run = iRCCE_isend_queue;
|
||||
while(run->next != NULL) run = run->next;
|
||||
run->next = request;
|
||||
}
|
||||
|
||||
if(request == &blocking_isend_request) {
|
||||
iRCCE_isend_wait(request);
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
return(iRCCE_RESERVED);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FUNCTION: iRCCE_isend
|
||||
//------------------------------------------------------------------------------
|
||||
// wrapper function to differentiate between anylength and normal call
|
||||
//------------------------------------------------------------------------------
|
||||
static iRCCE_SEND_REQUEST blocking_isend_request;
|
||||
int iRCCE_isend(
|
||||
char *privbuf,
|
||||
ssize_t size,
|
||||
int dest,
|
||||
iRCCE_SEND_REQUEST *request
|
||||
) {
|
||||
if(request == NULL) request = &blocking_isend_request;
|
||||
|
||||
if (dest<0 || dest >= RCCE_NP) {
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
}
|
||||
else {
|
||||
// anylength call
|
||||
if( size < 0 ){
|
||||
// convert size to positive range */
|
||||
int send_size = -size;
|
||||
|
||||
// use header payload
|
||||
if( send_size <= iRCCE_MAIL_HEADER_PAYLOAD ) {
|
||||
iRCCE_init_send_request(privbuf, RCCE_buff_ptr,
|
||||
RCCE_chunk, &RCCE_ready_flag[dest],
|
||||
&RCCE_sent_flag[RCCE_IAM],
|
||||
send_size, dest, request);
|
||||
request->finished = 1;
|
||||
|
||||
iRCCE_mail_send( send_size,
|
||||
iRCCE_ANYLENGTH_PIGGYBACK,
|
||||
0, privbuf, dest );
|
||||
NOP8;
|
||||
NOP8;
|
||||
icc_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 );
|
||||
return iRCCE_isend_general( privbuf, send_size,
|
||||
dest, request );
|
||||
}
|
||||
}
|
||||
// normal call
|
||||
else if( size > 0 ) {
|
||||
return iRCCE_isend_general( privbuf, size,
|
||||
dest, request );
|
||||
}
|
||||
// do nothing
|
||||
else {
|
||||
iRCCE_init_send_request(privbuf, RCCE_buff_ptr,
|
||||
RCCE_chunk, &RCCE_ready_flag[dest],
|
||||
&RCCE_sent_flag[RCCE_IAM],
|
||||
size, dest, request);
|
||||
request->finished = 1;
|
||||
return(iRCCE_SUCCESS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
482
arch/x86/scc/iRCCE_mailbox.c
Normal file
482
arch/x86/scc/iRCCE_mailbox.c
Normal file
|
@ -0,0 +1,482 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
/**
|
||||
*
|
||||
* @file contains implementation of the mailbox system
|
||||
* @author Simon Pickartz
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// 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 ) {
|
||||
if( i == RCCE_IAM ) continue;
|
||||
// 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
|
|
@ -177,6 +177,18 @@ int iRCCE_recv(char *privbuf, size_t size, int source) {
|
|||
iRCCE_isend_push();
|
||||
}
|
||||
|
||||
|
||||
// determine source of request if given source = iRCCE_ANY_SOURCE
|
||||
if ( source==iRCCE_ANY_SOURCE ){
|
||||
int i, res;
|
||||
for( i=0;;i=(++i)%RCCE_NP ){
|
||||
if ( (i != RCCE_IAM) && (res = RCCE_probe(RCCE_sent_flag[i])) ){
|
||||
source = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source<0 || source >= RCCE_NP)
|
||||
return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID));
|
||||
else {
|
||||
|
|
|
@ -172,7 +172,7 @@ int icc_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline int icc_send_irq(int ue)
|
||||
int icc_send_irq(int ue)
|
||||
{
|
||||
int tmp, x, y, z, addr;
|
||||
|
||||
|
@ -195,123 +195,103 @@ inline 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)
|
||||
if (do_send) {
|
||||
do_send = (iRCCE_isend_push() == iRCCE_PENDING);
|
||||
icc_check();
|
||||
iRCCE_irecv_push();
|
||||
}
|
||||
icc_mail_check();
|
||||
|
||||
irq_nested_enable(flags);
|
||||
} while(do_send);
|
||||
|
||||
HALT;
|
||||
NOP1;
|
||||
} while(do_send);
|
||||
#else
|
||||
// iRCCE is not thread save => disable interrupts
|
||||
flags = irq_nested_disable();
|
||||
icc_mail_check();
|
||||
irq_nested_enable(flags);
|
||||
NOP1;
|
||||
#endif
|
||||
//HALT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static volatile uint64_t ping_start = 0;
|
||||
static icc_header_t ping_request = {ICC_TYPE_PINGREQUEST, 0, 0};
|
||||
static icc_header_t ping_response = {ICC_TYPE_PINGRESPONSE, 0, 0};
|
||||
|
||||
int icc_ping(int ue)
|
||||
{
|
||||
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;
|
||||
|
||||
if (BUILTIN_EXPECT(ue == my_ue, 0))
|
||||
return -EINVAL;
|
||||
if (BUILTIN_EXPECT((ue < 0) || (ue >= num_ues), 0))
|
||||
return -EINVAL;
|
||||
|
||||
while(ping_start) {
|
||||
NOP8;
|
||||
}
|
||||
|
||||
ping_start = rdtsc();
|
||||
|
||||
// iRCCE is not thread save => disable interrupts
|
||||
if (my_ue)
|
||||
return -1;
|
||||
|
||||
kprintf( "Hello from mail_ping ... \n" );
|
||||
|
||||
// disable interrupts
|
||||
flags = irq_nested_disable();
|
||||
|
||||
iRCCE_isend((char*) &ping_request, sizeof(icc_header_t), ue, NULL);
|
||||
// start timer
|
||||
*timer = rdtsc();
|
||||
|
||||
/* send ping request */
|
||||
iRCCE_mail_send(sizeof(uint64_t), ICC_TAG_PINGREQUEST, 0, payload, remote_rank);
|
||||
|
||||
// wait some time
|
||||
NOP8;
|
||||
icc_send_irq(remote_rank);
|
||||
|
||||
// wake up receiver
|
||||
icc_send_irq(ue);
|
||||
/* check for incoming messages */
|
||||
icc_mail_check();
|
||||
|
||||
// enable interrupts
|
||||
irq_nested_enable(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void interpret_header(icc_header_t* header, int recv_ue)
|
||||
void icc_mail_check(void)
|
||||
{
|
||||
//kprintf("Got ICC message %d from %d\n", header->type, recv_ue);
|
||||
iRCCE_MAIL_HEADER* header = NULL;
|
||||
int res;
|
||||
uint64_t timer;
|
||||
//char* recv_buffer;
|
||||
|
||||
switch(header->type)
|
||||
{
|
||||
case ICC_TYPE_PINGREQUEST: {
|
||||
|
||||
iRCCE_isend((char*) &ping_response, sizeof(icc_header_t), recv_ue, NULL);
|
||||
|
||||
// wait some time
|
||||
// empty mailbox and interpret headers
|
||||
while( (res = iRCCE_mail_recv( &header )) == iRCCE_SUCCESS ) {
|
||||
switch(header->tag)
|
||||
{
|
||||
case ICC_TAG_PINGREQUEST:
|
||||
iRCCE_mail_send( header->size, ICC_TAG_PINGRESPONSE, 0, header->payload, header->source );
|
||||
NOP8;
|
||||
|
||||
// wake up remote core
|
||||
icc_send_irq(recv_ue);
|
||||
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;
|
||||
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 );
|
||||
}
|
||||
break;
|
||||
case ICC_TYPE_PINGRESPONSE:
|
||||
kprintf("Receive ping response. Ticks: %d\n", rdtsc()-ping_start);
|
||||
ping_start = 0;
|
||||
break;
|
||||
default:
|
||||
kprintf("Receive unknown ICC message (%d)\n", header->type);
|
||||
else if( header->tag == iRCCE_ANYLENGTH_PIGGYBACK ) {
|
||||
iRCCE_mail_send( 0, 2, 0, NULL, header->source );
|
||||
}*/
|
||||
|
||||
iRCCE_mail_release( &header );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* By entering this function, interrupts are already disables
|
||||
* => No race by using the static variables
|
||||
*/
|
||||
void icc_check(void)
|
||||
{
|
||||
static icc_header_t header[MAX_SCC_CORES];
|
||||
static iRCCE_RECV_REQUEST request[MAX_SCC_CORES];
|
||||
static int8_t first_call = 1;
|
||||
int i, ret;
|
||||
|
||||
if (first_call) {
|
||||
first_call = 0;
|
||||
|
||||
for(i=0; i<num_ues; i++) {
|
||||
if (i == my_ue)
|
||||
continue;
|
||||
|
||||
iRCCE_irecv((char*) (header+i), sizeof(icc_header_t), i, request+i);
|
||||
}
|
||||
}
|
||||
|
||||
// pushes the progress of non-blocking communication requests
|
||||
iRCCE_irecv_push();
|
||||
|
||||
for(i=0; i<num_ues; i++) {
|
||||
if (i == my_ue)
|
||||
continue;
|
||||
|
||||
ret = iRCCE_irecv_test(request+i, NULL);
|
||||
if (ret == iRCCE_SUCCESS) {
|
||||
interpret_header(header+i, i);
|
||||
iRCCE_irecv((char*) (header+i), sizeof(icc_header_t), i, request+i);
|
||||
}
|
||||
}
|
||||
|
||||
// pushes the progress of non-blocking communication requests
|
||||
iRCCE_isend_push();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@ extern "C" {
|
|||
#define CONFIG_PCI
|
||||
#define CONFIG_LWIP
|
||||
#define CONFIG_VGA
|
||||
//#define CONFIG_UART
|
||||
#define CONFIG_KEYBOARD
|
||||
#define CONFIG_MULTIBOOT
|
||||
//#define CONFIG_ROCKCREEK
|
||||
|
@ -63,11 +64,6 @@ extern "C" {
|
|||
#define SHMADD
|
||||
#define SHMDBG
|
||||
//#define SHMADD_CACHEABLE
|
||||
/* default values for 16 GB system */
|
||||
#define PRIVATE_MEM1_START 0x00000000
|
||||
#define PRIVATE_MEM1_END 0x13FFFFFF
|
||||
#define PRIVATE_MEM2_START 0xFF000000
|
||||
#define PRIVATE_MEM2_END 0xFFFFFFFF
|
||||
#define SCC_BOOTINFO 0x80000
|
||||
|
||||
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||
|
|
|
@ -143,7 +143,7 @@ static inline void check_workqueues(void)
|
|||
uint32_t flags = irq_nested_disable();
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
icc_check();
|
||||
icc_mail_check();
|
||||
#endif
|
||||
|
||||
irq_nested_enable(flags);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <lwip/stats.h>
|
||||
#include <lwip/udp.h>
|
||||
#include <lwip/tcp.h>
|
||||
#include <lwip/tcpip.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/timers.h>
|
||||
|
@ -116,7 +117,7 @@ int STDCALL network_task(void* arg)
|
|||
|
||||
// start echo and ping server
|
||||
echo_init();
|
||||
//ping_init();
|
||||
ping_init();
|
||||
|
||||
while(!done) {
|
||||
#ifdef CONFIG_PCI
|
||||
|
@ -142,14 +143,14 @@ int network_shutdown(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tcp_init_ok(void* e)
|
||||
static void tcp_init_ok(void* e)
|
||||
{
|
||||
kprintf("TCP/IP init COMPLETE!!!!!!");
|
||||
kprintf("TCP/IP init COMPLETE!!");
|
||||
}
|
||||
|
||||
int network_init(void)
|
||||
{
|
||||
tcpip_init(tcp_init_ok,NULL);
|
||||
tcpip_init(tcp_init_ok, NULL);
|
||||
kprintf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
mmnif_open();
|
||||
kprintf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
|
@ -159,7 +160,7 @@ int network_init(void)
|
|||
|
||||
#if defined(CONFIG_LWIP)
|
||||
// Initialize lwIP modules
|
||||
lwip_init();
|
||||
tcpip_init(tcp_init_ok, NULL);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK))
|
||||
|
|
|
@ -86,7 +86,6 @@ int main(void)
|
|||
kprintf("This is MetalSVM %s Build %u, %u\n",
|
||||
METALSVM_VERSION, &__BUILD_DATE, &__BUILD_TIME);
|
||||
popbg();
|
||||
|
||||
system_init();
|
||||
irq_init();
|
||||
timer_init();
|
||||
|
@ -103,7 +102,6 @@ int main(void)
|
|||
irq_enable();
|
||||
|
||||
kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end);
|
||||
|
||||
system_calibration();
|
||||
network_init();
|
||||
|
||||
|
@ -115,7 +113,6 @@ int main(void)
|
|||
// sleep(5);
|
||||
// list_root();
|
||||
test_init();
|
||||
|
||||
per_core(current_task)->status = TASK_IDLE;
|
||||
reschedule();
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include <metalsvm/processor.h>
|
||||
#include <lwip/opt.h>
|
||||
|
||||
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
|
||||
#if LWIP_RAW || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include <lwip/mem.h>
|
||||
#include <lwip/raw.h>
|
||||
|
@ -198,19 +198,20 @@ ping_recv(int s)
|
|||
static void
|
||||
ping_thread(void *arg)
|
||||
{
|
||||
int s;
|
||||
int s, i;
|
||||
int timeout = PING_RCV_TIMEO;
|
||||
ip_addr_t ping_target;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
|
||||
LWIP_DEBUGF( PING_DEBUG, ("ping: invalid socket\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
while (1) {
|
||||
for(i=0; i<10; i++) {
|
||||
ping_target = PING_TARGET;
|
||||
|
||||
if (ping_send(s, &ping_target) == ERR_OK) {
|
||||
|
@ -227,6 +228,8 @@ ping_thread(void *arg)
|
|||
}
|
||||
sys_msleep(PING_DELAY);
|
||||
}
|
||||
|
||||
lwip_close(s);
|
||||
}
|
||||
|
||||
#else /* PING_USE_SOCKETS */
|
||||
|
|
|
@ -95,13 +95,13 @@ static int STDCALL foo(void* arg)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
static int STDCALL ping(void* arg)
|
||||
{
|
||||
int STDCALL mail_ping(void* arg) {
|
||||
int i;
|
||||
|
||||
for(i=0; i<20; i++) {
|
||||
icc_ping(1);
|
||||
HALT;
|
||||
if (BUILTIN_EXPECT(icc_mail_ping(), 0))
|
||||
return -1;
|
||||
udelay(500000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -125,7 +125,9 @@ static int STDCALL join_test(void* arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LWIP
|
||||
void ping_send_now();
|
||||
#endif
|
||||
|
||||
__inline int get_core_no(void)
|
||||
{
|
||||
|
@ -260,7 +262,7 @@ void* client_task(void* e)
|
|||
|
||||
close(sd);
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,7 +275,6 @@ int test_init(void)
|
|||
create_kernel_task(NULL,client_task,NULL);
|
||||
|
||||
#if 0
|
||||
|
||||
char* argv[] = {"/bin/tests", NULL};
|
||||
|
||||
sem_init(&producing, 1);
|
||||
|
@ -284,12 +285,12 @@ int test_init(void)
|
|||
//create_kernel_task(NULL, join_test, NULL);
|
||||
//create_kernel_task(NULL, producer, NULL);
|
||||
//create_kernel_task(NULL, consumer, NULL);
|
||||
//create_kernel_task(NULL, ping, NULL);
|
||||
//create_kernel_task(NULL, mail_ping, NULL);
|
||||
//create_user_task(NULL, "/bin/hello", argv);
|
||||
create_user_task(NULL, "/bin/tests", argv);
|
||||
//create_user_task(NULL, "/bin/jacobi", argv);
|
||||
//create_user_task(NULL, "/bin/jacobi", argv);
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,15 +24,19 @@
|
|||
#include <metalsvm/semaphore.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#ifdef CONFIG_VGA
|
||||
#include <asm/vga.h>
|
||||
#endif
|
||||
|
||||
#define NO_EARLY_PRINT 0
|
||||
#define VGA_EARLY_PRINT 1
|
||||
#define UART_EARLY_PRINT 2
|
||||
|
||||
#ifdef CONFIG_VGA
|
||||
static uint32_t early_print = VGA_EARLY_PRINT;
|
||||
#elif defined(CONFIG_UART)
|
||||
static uint32_t early_print = UART_EARLY_PRINT;
|
||||
#else
|
||||
static uint32_t early_print = NO_EARLY_PRINT;
|
||||
#endif
|
||||
|
@ -56,8 +60,12 @@ int kputchar(int c)
|
|||
kmessages[pos % KMSG_SIZE] = (unsigned char) c;
|
||||
#ifdef CONFIG_VGA
|
||||
if (early_print == VGA_EARLY_PRINT)
|
||||
vga_putchar(c);
|
||||
vga_putchar(c);
|
||||
#endif
|
||||
#ifdef CONFIG_UART
|
||||
if (early_print == UART_EARLY_PRINT)
|
||||
uart_putchar(c);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -73,6 +81,10 @@ int kputs(const char *str)
|
|||
#ifdef CONFIG_VGA
|
||||
if (early_print == VGA_EARLY_PRINT)
|
||||
vga_putchar(str[i]);
|
||||
#endif
|
||||
#ifdef CONFIG_UART
|
||||
if (early_print == UART_EARLY_PRINT)
|
||||
uart_putchar(str[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -84,8 +84,15 @@
|
|||
*/
|
||||
#define LWIP_CHECKSUM_ON_COPY 1
|
||||
|
||||
/**
|
||||
* IP_FORWARD==1: Enables the ability to forward IP packets across network
|
||||
* interfaces. If you are going to run lwIP on a device with only one network
|
||||
* interface, define this to 0.
|
||||
*/
|
||||
#define IP_FORWARD 1
|
||||
|
||||
/* DEBUG options */
|
||||
#define LWIP_DEBUG 0
|
||||
#define LWIP_DEBUG 1
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
|
@ -94,7 +101,8 @@
|
|||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#define INET_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_ON
|
||||
#define TIMERS_DEBUG LWIP_DBG_OFF
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
|
||||
#endif
|
||||
|
|
49
mm/memory.c
49
mm/memory.c
|
@ -30,6 +30,9 @@
|
|||
#include <asm/multiboot.h>
|
||||
#endif
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/RCCE.h>
|
||||
#include <asm/RCCE_lib.h>
|
||||
#include <asm/SCC_API.h>
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
||||
|
@ -93,6 +96,7 @@ int mmu_init(void)
|
|||
size_t kernel_size;
|
||||
unsigned int i;
|
||||
size_t addr;
|
||||
int ret;
|
||||
|
||||
// at first, set default value of the bitmap
|
||||
memset(bitmap, 0xFF, sizeof(uint8_t)*BITMAP_SIZE);
|
||||
|
@ -148,15 +152,8 @@ int mmu_init(void)
|
|||
}
|
||||
}
|
||||
#elif defined(CONFIG_ROCKCREEK)
|
||||
for(addr=PRIVATE_MEM1_START; addr<PRIVATE_MEM1_END; addr+=PAGE_SIZE) {
|
||||
page_clear_mark(addr >> PAGE_SHIFT);
|
||||
if (addr > addr + PAGE_SIZE)
|
||||
break;
|
||||
atomic_int32_inc(&total_pages);
|
||||
atomic_int32_inc(&total_available_pages);
|
||||
}
|
||||
|
||||
for(addr=PRIVATE_MEM2_START; addr<PRIVATE_MEM2_END; addr+=PAGE_SIZE) {
|
||||
/* of course, the first twenty slots belong to the private memory */
|
||||
for(addr=0x00; addr<20*0x1000000; addr+=PAGE_SIZE) {
|
||||
page_clear_mark(addr >> PAGE_SHIFT);
|
||||
if (addr > addr + PAGE_SIZE)
|
||||
break;
|
||||
|
@ -164,6 +161,15 @@ int mmu_init(void)
|
|||
atomic_int32_inc(&total_available_pages);
|
||||
}
|
||||
|
||||
// Note: The last slot belongs always to the private memory.
|
||||
for(addr=0xFF000000; addr<0xFFFFFFFF; addr+=PAGE_SIZE) {
|
||||
page_clear_mark(addr >> PAGE_SHIFT);
|
||||
if (addr > addr + PAGE_SIZE)
|
||||
break;
|
||||
atomic_int32_inc(&total_pages);
|
||||
atomic_int32_inc(&total_available_pages);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the bootinfo as used.
|
||||
*/
|
||||
|
@ -200,7 +206,30 @@ int mmu_init(void)
|
|||
if ((size_t) &kernel_end & (PAGE_SIZE-1))
|
||||
alloc_start++;
|
||||
|
||||
return paging_init();
|
||||
ret = paging_init();
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
/*
|
||||
* Now, we are able to read the FPGA registers and to
|
||||
* determine the number of slots for private memory.
|
||||
*/
|
||||
uint32_t slots = *((volatile uint32_t*) (FPGA_BASE + 0x8244));
|
||||
if (slots == 0)
|
||||
slots = 21;
|
||||
|
||||
kprintf("MetalSVM use %d slots for private memory\n", slots);
|
||||
|
||||
// define the residual private slots as free
|
||||
for(addr=20*0x1000000; addr<(slots-1)*0x1000000; addr+=PAGE_SIZE) {
|
||||
page_clear_mark(addr >> PAGE_SHIFT);
|
||||
if (addr > addr + PAGE_SIZE)
|
||||
break;
|
||||
atomic_int32_inc(&total_pages);
|
||||
atomic_int32_inc(&total_available_pages);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue