static int cos_net_tcp_recv(struct intern_connection *ic, void *data, int sz) { int xfer_amnt = 0; assert(ic->conn_type == TCP); /* If there is data available, get it */ if (ic->incoming_size > 0) { struct packet_queue *pq; struct tcp_pcb *tp; char *data_start; int data_left; pq = ic->incoming; assert(pq); data_start = ((char*)pq->data) + ic->incoming_offset; data_left = pq->len - ic->incoming_offset; assert(data_left > 0 && (u32_t)data_left <= pq->len); /* Consume all of first packet? */ if (data_left <= sz) { ic->incoming = pq->next; if (ic->incoming_last == pq) { assert(NULL == ic->incoming); ic->incoming_last = NULL; } memcpy(data, data_start, data_left); xfer_amnt = data_left; ic->incoming_offset = 0; #ifdef TEST_TIMING ic->ts_start = timing_record(APP_RECV, pq->ts_start); #endif free(pq); } /* Consume part of first packet */ else { memcpy(data, data_start, sz); xfer_amnt = sz; ic->incoming_offset += sz; assert(ic->incoming_offset >= 0 && (u32_t)ic->incoming_offset < pq->len); } ic->incoming_size -= xfer_amnt; tp = ic->conn.tp; tcp_recved(tp, xfer_amnt); } return xfer_amnt; }
static err_t cos_net_stack_send(struct netif *ni, struct pbuf *p, struct ip_addr *ip) { int tot_len = 0, sz; char *buff; cbuf_t cb; /* assuming the net lock is taken here */ assert(p && p->ref == 1); assert(p->type == PBUF_RAM); buff = cbuf_alloc(MTU, &cb); assert(buff); while (p) { if (p->len + tot_len > MTU) BUG(); memcpy(buff + tot_len, p->payload, p->len); tot_len += p->len; #ifdef TCP_SEND_COPY #ifdef TEST_TIMING if ((p->type == PBUF_REF || p->type == PBUF_ROM)) { struct packet_queue *pq; pq = net_packet_pq(p->payload); timing_record(SEND, pq->ts_start); } #endif #endif assert(p->type != PBUF_POOL); assert(p->ref == 1); p = p->next; } sz = parent_twrite(cos_spd_id(), ip_td, cb, tot_len); if (sz <= 0) { printc("<<transmit returns %d -> %d>>\n", sz, tot_len); } tcp_twrite_cnt++; assert(sz > 0); cbuf_free(buff); /* cannot deallocate packets here as we might need to * retransmit them. */ return ERR_OK; }
void timing_basic_alltoall_nelements( int DIM1, int procs, int loop, char* testname, MPI_Comm local_communicator) { float* send_array; float* recv_array; int myrank; int base, typesize, bytes, i; char method[50]; send_array = malloc( DIM1 * procs * sizeof(float)); recv_array = malloc( DIM1 * procs * sizeof(float)); MPI_Comm_rank( local_communicator, &myrank ); base = myrank * DIM1 + 1; utilities_fill_unique_array_1D_float( &send_array[0], DIM1, base ); if ( myrank == 0 ) { snprintf(method, 50, "reference"); MPI_Type_size( MPI_FLOAT, &typesize ); bytes = typesize * DIM1 * procs; timing_init( testname, &method[0], bytes ); } for( i=0 ; i<loop ; i++ ) { MPI_Alltoall(&send_array[0], DIM1, MPI_FLOAT, &recv_array[0], DIM1, MPI_FLOAT, local_communicator ); MPI_Alltoall(&recv_array[0], DIM1, MPI_FLOAT, &send_array[0], DIM1, MPI_FLOAT, local_communicator ); if ( myrank == 0 ) { timing_record(3); } } if ( myrank == 0 ) { timing_print( 1 ); } free(send_array); free(recv_array); }
void timing_basic_ping_pong_nelements( int DIM1, int loop, char* testname, MPI_Comm local_communicator) { float* array; int myrank; int base, typesize, bytes, i; char method[50]; array = malloc( DIM1 * sizeof(float)); MPI_Comm_rank( local_communicator, &myrank ); base = myrank * DIM1 + 1; utilities_fill_unique_array_1D_float( &array[0], DIM1, base ); if ( myrank == 0 ) { snprintf(&method[0], 50, "reference"); MPI_Type_size( MPI_FLOAT, &typesize ); bytes = typesize * DIM1; timing_init( testname, &method[0], bytes ); } for( i=0 ; i<loop ; i++ ){ if ( myrank == 0 ) { MPI_Send( &array[0], DIM1, MPI_FLOAT, 1, itag, local_communicator ); MPI_Recv( &array[0], DIM1, MPI_FLOAT, 1, itag, local_communicator, MPI_STATUS_IGNORE ); timing_record(3); } else { MPI_Recv( &array[0], DIM1, MPI_FLOAT, 0, itag, local_communicator, MPI_STATUS_IGNORE ); MPI_Send( &array[0], DIM1, MPI_FLOAT, 0, itag, local_communicator ); } } if ( myrank == 0 ) { timing_print( 1 ); } free(array); }
static err_t cos_net_lwip_tcp_recv(void *arg, struct tcp_pcb *tp, struct pbuf *p, err_t err) { struct intern_connection *ic; struct packet_queue *pq, *last; void *headers; struct pbuf *first; ic = (struct intern_connection*)arg; assert(NULL != ic); assert(TCP == ic->conn_type); if (NULL == p) { assert(ic->conn.tp == tp); /* * This should call our registered error function * above with ERR_ABRT, which will make progress * towards closing the connection. * * Later, when the app calls some function in the API, * TCP_CLOSED will be seen and the internal connection * will be deallocated, and the application notified. */ tcp_abort(tp); assert(ic->conn_type == TCP_CLOSED && NULL == ic->conn.tp); /* tcp_close(tp); // Jiguo: aggressive close */ return ERR_CLSD; } first = p; while (p) { struct pbuf *q; if (p->ref != 1) printc("pbuf with len %d, totlen %d and refcnt %d", p->len, p->tot_len, p->ref); assert(p->len > 0); assert(p->type == PBUF_ROM || p->type == PBUF_REF); headers = cos_net_header_start(p, TCP); assert (NULL != headers); pq = net_packet_pq(headers); pq->data = p->payload; pq->len = p->len; pq->next = NULL; #ifdef TEST_TIMING pq->ts_start = timing_record(RECV, pq->ts_start); #endif assert((NULL == ic->incoming) == (NULL == ic->incoming_last)); /* Is the queue empty? */ if (NULL == ic->incoming) { assert(NULL == ic->incoming_last); ic->incoming = ic->incoming_last = pq; } else { last = ic->incoming_last; last->next = pq; ic->incoming_last = pq; } ic->incoming_size += p->len; //assert(1 == p->ref); q = p->next; p->payload = p->alloc_track = NULL; assert(NULL != q || p->len == p->tot_len); assert(p->ref == 1); p = q; } /* Just make sure lwip is doing what we think its doing */ assert(first->ref == 1); /* This should deallocate the entire chain */ pbuf_free(first); /* printc("thd in %ld tcp_recv call trigger evt id %d\n", cos_get_thd_id(), ic->data); */ if (-1 != ic->data && evt_trigger(cos_spd_id(), ic->data)) BUG(); tcp_recv_cnt++; /* /\* If the thread blocked waiting for a packet, wake it up *\/ */ /* if (RECVING == ic->thd_status) { */ /* ic->thd_status = ACTIVE; */ /* assert(ic->thd_status == ACTIVE); /\* Detect races *\/ */ /* if (sched_wakeup(cos_spd_id(), ic->tid)) BUG(); */ /* } */ return ERR_OK; }
int net_send(spdid_t spdid, net_connection_t nc, void *data, int sz) { struct intern_connection *ic; u16_t tid = cos_get_thd_id(); int ret = sz; // if (!cos_argreg_buff_intern(data, sz)) return -EFAULT; if (!net_conn_valid(nc)) return -EINVAL; if (sz > MAX_SEND) return -EMSGSIZE; // NET_LOCK_TAKE(); ic = net_conn_get_internal(nc); if (NULL == ic) { ret = -EINVAL; goto err; } if (tid != ic->tid) { ret = -EPERM; goto err; } switch (ic->conn_type) { case UDP: { struct udp_pcb *up; struct pbuf *p; /* There's no blocking in the UDP case, so this is simple */ up = ic->conn.up; p = pbuf_alloc(PBUF_TRANSPORT, sz, PBUF_ROM); if (NULL == p) { ret = -ENOMEM; goto err; } p->payload = data; if (ERR_OK != udp_send(up, p)) { pbuf_free(p); /* IP/port must not be set */ ret = -ENOTCONN; goto err; } pbuf_free(p); break; } case TCP: { struct tcp_pcb *tp; #define TCP_SEND_COPY #ifdef TCP_SEND_COPY void *d; struct packet_queue *pq; #endif tp = ic->conn.tp; if (tcp_sndbuf(tp) < sz) { ret = 0; break; } #ifdef TCP_SEND_COPY pq = malloc(sizeof(struct packet_queue) + sz); if (unlikely(NULL == pq)) { ret = -ENOMEM; goto err; } #ifdef TEST_TIMING pq->ts_start = timing_record(APP_PROC, ic->ts_start); #endif pq->headers = NULL; d = net_packet_data(pq); memcpy(d, data, sz); if (ERR_OK != (ret = tcp_write(tp, d, sz, 0))) { #else if (ERR_OK != (ret = tcp_write(tp, data, sz, TCP_WRITE_FLAG_COPY))) { #endif free(pq); printc("tcp_write returned %d (sz %d, tcp_sndbuf %d, ERR_MEM: %d)", ret, sz, tcp_sndbuf(tp), ERR_MEM); BUG(); } /* No implementation of nagle's algorithm yet. Send * out the packet immediately if possible. */ if (ERR_OK != (ret = tcp_output(tp))) { printc("tcp_output returned %d, ERR_MEM: %d", ret, ERR_MEM); BUG(); } ret = sz; break; } case TCP_CLOSED: ret = -EPIPE; break; default: BUG(); } err: // NET_LOCK_RELEASE(); return ret; } /************************ LWIP integration: **************************/ struct ip_addr ip, mask, gw; struct netif cos_if; static void cos_net_interrupt(char *packet, int sz) { void *d; int len; struct pbuf *p; struct ip_hdr *ih; struct packet_queue *pq; #ifdef TEST_TIMING unsigned long long ts; #endif // printc(">>> %d\n", net_lock.lock_id); NET_LOCK_TAKE(); // printc("<<< %d\n", net_lock.lock_id); assert(packet); ih = (struct ip_hdr*)packet; if (unlikely(4 != IPH_V(ih))) goto done; len = ntohs(IPH_LEN(ih)); if (unlikely(len != sz || len > MTU)) { printc("len %d != %d or > %d", len, sz, MTU); goto done; } p = pbuf_alloc(PBUF_IP, len, PBUF_ROM); if (unlikely(!p)) { prints("OOM in interrupt: allocation of pbuf failed.\n"); goto done; } /* For now, we're going to do an additional copy. Currently, * packets should be small, so this shouldn't hurt that badly. * This is done because 1) we are freeing the packet * elsewhere, 2) we want to malloc some (small) packets to * save space and free up the ring buffers, 3) it is difficult * to know in (1) which deallocation method (free or return to * ring buff) to use */ pq = malloc(len + sizeof(struct packet_queue)); if (unlikely(NULL == pq)) { printc("OOM in interrupt: allocation of packet data (%d bytes) failed.\n", len); pbuf_free(p); goto done; } pq->headers = d = net_packet_data(pq); #ifdef TEST_TIMING #ifdef TCP_SEND_COPY ts = pq->ts_start = timing_timestamp(); #endif #endif memcpy(d, packet, len); p->payload = p->alloc_track = d; /* hand off packet ownership here... */ if (ERR_OK != cos_if.input(p, &cos_if)) { prints("net: failure in IP input."); pbuf_free(p); goto done; } #ifdef TEST_TIMING timing_record(UPCALL_PROC, ts); #endif done: NET_LOCK_RELEASE(); return; }
int main (int argc, char **argv) { char *ch; if (argc != 2) { fputs("Invalid number of arguments\n", stderr); fputs("usage: hspwrap EXEFILE\n", stderr); exit(EXIT_FAILURE); } ch = getenv("HSP_BCAST_CHUNK_SIZE"); if (ch) { sscanf(ch, "%zu", &bcast_chunk_size); } else { bcast_chunk_size = 4L << 20; } ch = getenv("HSP_INPUT_FORMAT"); if (!ch || ch[0] == '\0' || ch[0] == 'l') { info("Input format: Lines\n"); input_fmt = 'l'; } else if (ch[0] == 'f') { info("Input format: FASTA\n"); input_fmt = 'f'; } else { fputs("Invalid input format specified\n", stderr); exit(EXIT_FAILURE); } // Pre-fork process pool (even on master) #ifndef TIMING_MODE sleep(1); pool_ctl = process_pool_fork(); trace("Process pool created.\n"); sleep(1); #endif // Initialize MPI int rank, ranks; if (MPI_Init(NULL, NULL) != MPI_SUCCESS) { fprintf(stderr, "Error initialize MPI.\n"); return EXIT_FAILURE; } MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &ranks); trace("MPI Initialized.\n"); // Initialize our state timing_init(&timing); if (rank) { slave_init(rank, ranks-1, NUM_PROCS); } else { print_banner_slant(stderr); master_init(); } // Broadcast binary files first if (rank) { slave_broadcast_work_file("exefile"); } else { master_broadcast_file(getenv("HSP_EXEFILE")); } // Distribute DB files MPI_Barrier(MPI_COMM_WORLD); timing_record(&timing.db_start); char *dbdir = getenv("HSP_DBDIR"); char *dbfiles = strdup(getenv("HSP_DBFILES")); char *fn, path[PATH_MAX]; for (fn = strtok(dbfiles, ":"); fn; fn = strtok(NULL, ":")) { snprintf(path, sizeof(path), "%s/%s", dbdir, fn); if (rank) { timing.db_kbytes += slave_broadcast_shared_file(path)/1024; } else { timing.db_kbytes += master_broadcast_file(path)/1024; } } free(dbfiles); MPI_Barrier(MPI_COMM_WORLD); timing_record(&timing.db_end); #ifdef TIMING_MODE if (!rank) { timing_print(&timing); } MPI_Finalize(); return 0; #endif // FIXME: The order of things is generally wrong. Should be: // Fork Forker, MPI_Init, PS Ctl, EXE/DB distro, forking, main loop #if 0 // Now print some stats if (rank) { MPI_Barrier(MPI_COMM_WORLD); printf("Rank %d Processes: %d", rank, ps_ctl->nprocesses); printf(" Process ID: %d", getpid()); printf(" Files: %d (", ps_ctl->ft.nfiles); for (i=0; i<ps_ctl->ft.nfiles; ++i) { printf("%s, ", ps_ctl->ft.file[i].name); } puts(")"); } else { printf("Ranks: %d\n\n", ranks); MPI_Barrier(MPI_COMM_WORLD); } #endif if (rank) { slave_main(argv[1]); } else { master_main(ranks-1); timing_print(&timing); } return 0; }