/* * Spawns a dequeuer thread that constantly tries to dequeue, * and the main thread enqueues 1..n_to_enqueue values. Dequeuer thread * will exit after it dequeues a zero or after TIMELIMIT seconds, * whichever comes first. * * delay_mode controls the interval between successive enqueues. * 0 means enqueue as fast as possible * 1 means random small delays * 2 means large delay (0.5s) in the beginning, then fast enqueue * 3 means large delay, then random small delays. */ void test_queue_parallel_1 (int q_size, int n_to_enqueue, int delay_mode) { struct l_queue *q = create_queues(1, q_size); pthread_t dqr; pthread_create(&dqr, NULL, eternal_dqr, (void *) q); switch(delay_mode) { case 0: eqr0(q, n_to_enqueue); break; case 1: eqr1(q, n_to_enqueue); break; case 2: eqr2(q, n_to_enqueue); break; case 3: eqr3(q, n_to_enqueue); break; } pthread_join(dqr, NULL); destroy_queues(1, q); return; }
/* init_conn: * This just chains to the channel initialiser, basically. */ static int init_conn (NET_CONN *conn, const char *addr) { struct conn_data_t *data; conn->peer_addr[0] = '\0'; conn->data = data = malloc (sizeof *data); if (!data) return 1; if (create_queues (conn)) { free (data); return 2; } data->conns = NULL; data->referer = NULL; data->chan = net_openchannel (conn->type, addr); if (!data->chan) { destroy_queues (conn); free (data); return 3; } return 0; /* success */ }
/* poll_listen: * Here we check for an incoming connection, and if there is one we * fill in `newconn' with our data pointer for it and the addresses, * and return nonzero. Otherwise return 0. */ static int poll_listen (NET_CONN *conn, NET_CONN *newconn) { struct conn_data_t *data; char buffer[12], buffer2[8+NET_MAX_ADDRESS_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 }; char addr[NET_MAX_ADDRESS_LENGTH]; int x; int count = 32; /* maximum number of packets to process */ while (net_query (((struct conn_data_t *)conn->data)->chan) && count-- > 0) { if ((net_receive (((struct conn_data_t *)conn->data)->chan, buffer, 12, addr) == 12) && !memcmp (buffer, "connect", 8)) { newconn->data = data = malloc (sizeof *data); if (!data) continue; if (create_queues (newconn)) { free (data); continue; } data->conns = NULL; x = get_channel ( ((struct conn_data_t *)conn->data)->conns, addr, (buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + buffer[11], conn->type, NULL, &data->chan, data ); if (x) { data->referer = conn->data; /* tell new channel where to send in future */ net_assigntarget (data->chan, addr); /* send reply now with address of new channel, through * listening conn so it can get through NATs */ net_assigntarget (((struct conn_data_t *)conn->data)->chan, addr); strcpy (buffer2+8, net_getlocaladdress (data->chan)); net_send (((struct conn_data_t *)conn->data)->chan, buffer2, 8+NET_MAX_ADDRESS_LENGTH); } if (x >= 0) { destroy_queues (newconn); free (data); continue; } strcpy (newconn->peer_addr, addr); return 1; } } return 0; }
int scheduler_suite_term(void) { odp_pool_t pool; if (destroy_queues() != 0) { fprintf(stderr, "error: failed to destroy queues\n"); return -1; } pool = odp_pool_lookup(MSG_POOL_NAME); if (odp_pool_destroy(pool) != 0) fprintf(stderr, "error: failed to destroy pool\n"); return 0; }
static int destroy_conn (NET_CONN *conn) { struct conn_data_t *data = conn->data; if (data->referer) { /* remove us from refering list in listener connection */ struct conns_list *prev = NULL, *list = data->referer->conns; while (list) { if (list->chan == data->chan) { struct conns_list *old = list; if (prev) prev->next = list->next; else data->referer->conns = list->next; list = list->next; free(old->addr); free(old); } else { prev = list; list = list->next; } } } net_closechannel (data->chan); destroy_queues (conn); destroy_conns_list (data->conns); free (data); return 0; }
void serial_queue(int n_packets, int n_src, int q_depth, long mean, int seed, int distr) { Packet_t **rcvd_packets = malloc (n_packets * n_src * sizeof(Packet_t *)); PacketSource_t *source = createPacketSource (mean, n_src, seed); int packet_ctr = 0; long fp_sum = 0; StopWatch_t watch; startTimer(&watch); Packet_t *(*pkt_fn)(PacketSource_t *, int) = distr ? getUniformPacket : getExponentialPacket; struct l_queue *queues = create_queues (n_src, q_depth); for (int i = 0; i < n_packets; i++) { for (int j = 0; j < n_src; j++) { Packet_t *pkt = pkt_fn (source, j); rcvd_packets[packet_ctr] = pkt; enq (queues + j, (void *) pkt); packet_ctr++; deq (queues + j, (void **) &pkt); fp_sum += getFingerprint (pkt->iterations, pkt->seed); } } destroy_queues (n_src, queues); stopTimer(&watch); deletePacketSource (source); // Free all the packets... for (int i = 0; i < packet_ctr; i++) free (rcvd_packets[i]); free (rcvd_packets); #ifdef PERF printf("%f\n", getElapsedTime(&watch)); #else printf("%ld\n", fp_sum); #endif return; }
/* * Tests serial correctness of the queue. Takes the queue capacity as a parameter * * This function will wait for input on stdin. Input of the form "e (number)" * will enqueue the number, and input consisting of "d" will dequeue and print * to stdout. Function exits on "x". * * Unsuccessful enqueueing will output a line containing "F", unsuccessful dequeuing * will output a line containing "E". */ void test_queue_serial(int q_size) { struct l_queue *q = create_queues(1, q_size); char *line_in = calloc(500, sizeof(char)); long i = 0; while (1) { if(!fgets(line_in, 500, stdin)) break; for (int j = 0; j < 500; j++) { if (line_in[j] == '\n') { line_in[j] = '\0'; break; } } if (!strcmp(line_in, "x")) break; if (line_in[0] == 'e') { i = strtol (line_in + 2, NULL, 10); if (enq (q, (void *) i)) { printf("F\n"); } } else { if (deq (q, (void **) &i)) { printf("E\n"); } else { printf("%ld\n", i); } } fflush(stdout); } free (line_in); destroy_queues(1, q); return; }
static int eth_open(struct net_device *dev) { struct port *port = netdev_priv(dev); struct npe *npe = port->npe; struct msg msg; int i, err; if (!npe_running(npe)) { err = npe_load_firmware(npe, npe_name(npe), &dev->dev); if (err) return err; if (npe_recv_message(npe, &msg, "ETH_GET_STATUS")) { printk(KERN_ERR "%s: %s not responding\n", dev->name, npe_name(npe)); return -EIO; } port->firmware[0] = msg.byte4; port->firmware[1] = msg.byte5; port->firmware[2] = msg.byte6; port->firmware[3] = msg.byte7; } memset(&msg, 0, sizeof(msg)); msg.cmd = NPE_VLAN_SETRXQOSENTRY; msg.eth_id = port->id; msg.byte5 = port->plat->rxq | 0x80; msg.byte7 = port->plat->rxq << 4; for (i = 0; i < 8; i++) { msg.byte3 = i; if (npe_send_recv_message(port->npe, &msg, "ETH_SET_RXQ")) return -EIO; } msg.cmd = NPE_EDB_SETPORTADDRESS; msg.eth_id = PHYSICAL_ID(port->id); msg.byte2 = dev->dev_addr[0]; msg.byte3 = dev->dev_addr[1]; msg.byte4 = dev->dev_addr[2]; msg.byte5 = dev->dev_addr[3]; msg.byte6 = dev->dev_addr[4]; msg.byte7 = dev->dev_addr[5]; if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAC")) return -EIO; memset(&msg, 0, sizeof(msg)); msg.cmd = NPE_FW_SETFIREWALLMODE; msg.eth_id = port->id; if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE")) return -EIO; if ((err = request_queues(port)) != 0) return err; if ((err = init_queues(port)) != 0) { destroy_queues(port); release_queues(port); return err; } port->speed = 0; /* force "link up" message */ phy_start(port->phydev); for (i = 0; i < ETH_ALEN; i++) __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]); __raw_writel(0x08, &port->regs->random_seed); __raw_writel(0x12, &port->regs->partial_empty_threshold); __raw_writel(0x30, &port->regs->partial_full_threshold); __raw_writel(0x08, &port->regs->tx_start_bytes); __raw_writel(0x15, &port->regs->tx_deferral); __raw_writel(0x08, &port->regs->tx_2part_deferral[0]); __raw_writel(0x07, &port->regs->tx_2part_deferral[1]); __raw_writel(0x80, &port->regs->slot_time); __raw_writel(0x01, &port->regs->int_clock_threshold); /* Populate queues with buffers, no failure after this point */ for (i = 0; i < TX_DESCS; i++) queue_put_desc(port->plat->txreadyq, tx_desc_phys(port, i), tx_desc_ptr(port, i)); for (i = 0; i < RX_DESCS; i++) queue_put_desc(RXFREE_QUEUE(port->id), rx_desc_phys(port, i), rx_desc_ptr(port, i)); __raw_writel(TX_CNTRL1_RETRIES, &port->regs->tx_control[1]); __raw_writel(DEFAULT_TX_CNTRL0, &port->regs->tx_control[0]); __raw_writel(0, &port->regs->rx_control[1]); __raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]); napi_enable(&port->napi); eth_set_mcast_list(dev); netif_start_queue(dev); qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY, eth_rx_irq, dev); if (!ports_open) { qmgr_set_irq(TXDONE_QUEUE, QUEUE_IRQ_SRC_NOT_EMPTY, eth_txdone_irq, NULL); qmgr_enable_irq(TXDONE_QUEUE); } ports_open++; /* we may already have RX data, enables IRQ */ napi_schedule(&port->napi); return 0; }
static int eth_close(struct net_device *dev) { struct port *port = netdev_priv(dev); struct msg msg; int buffs = RX_DESCS; /* allocated RX buffers */ int i; ports_open--; qmgr_disable_irq(port->plat->rxq); napi_disable(&port->napi); netif_stop_queue(dev); while (queue_get_desc(RXFREE_QUEUE(port->id), port, 0) >= 0) buffs--; memset(&msg, 0, sizeof(msg)); msg.cmd = NPE_SETLOOPBACK_MODE; msg.eth_id = port->id; msg.byte3 = 1; if (npe_send_recv_message(port->npe, &msg, "ETH_ENABLE_LOOPBACK")) printk(KERN_CRIT "%s: unable to enable loopback\n", dev->name); i = 0; do { /* drain RX buffers */ while (queue_get_desc(port->plat->rxq, port, 0) >= 0) buffs--; if (!buffs) break; if (qmgr_stat_empty(TX_QUEUE(port->id))) { /* we have to inject some packet */ struct desc *desc; u32 phys; int n = queue_get_desc(port->plat->txreadyq, port, 1); BUG_ON(n < 0); desc = tx_desc_ptr(port, n); phys = tx_desc_phys(port, n); desc->buf_len = desc->pkt_len = 1; wmb(); queue_put_desc(TX_QUEUE(port->id), phys, desc); } udelay(1); } while (++i < MAX_CLOSE_WAIT); if (buffs) printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)" " left in NPE\n", dev->name, buffs); #if DEBUG_CLOSE if (!buffs) printk(KERN_DEBUG "Draining RX queue took %i cycles\n", i); #endif buffs = TX_DESCS; while (queue_get_desc(TX_QUEUE(port->id), port, 1) >= 0) buffs--; /* cancel TX */ i = 0; do { while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0) buffs--; if (!buffs) break; } while (++i < MAX_CLOSE_WAIT); if (buffs) printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) " "left in NPE\n", dev->name, buffs); #if DEBUG_CLOSE if (!buffs) printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i); #endif msg.byte3 = 0; if (npe_send_recv_message(port->npe, &msg, "ETH_DISABLE_LOOPBACK")) printk(KERN_CRIT "%s: unable to disable loopback\n", dev->name); phy_stop(port->phydev); if (!ports_open) qmgr_disable_irq(TXDONE_QUEUE); destroy_queues(port); release_queues(port); return 0; }
double parallel_dispatcher #else long parallel_dispatcher #endif (int n_packets, int n_src, int q_depth, long mean, int seed, #ifdef TESTING int n_lazy, #endif int distr) { // This array holds packets so we can free them in the end. Shouldn't be too big... // also we're putting packet memory management outside the timing for all three. Packet_t **rcvd_packets = malloc (n_packets * n_src * sizeof(Packet_t *)); PacketSource_t *source = createPacketSource (mean, n_src, seed); StopWatch_t watch; startTimer(&watch); struct l_queue *queues = create_queues (n_src, q_depth); int n_workers_done = 0; int packet_ctr = 0; long total_fp_sum = 0; pthread_t *workers = calloc (n_src, sizeof(pthread_t)); struct thread_data *worker_data = calloc (n_src, sizeof(struct thread_data)); for (int i = 0; i < n_src; i++) { worker_data[i].q = queues + i; #ifdef TESTING if (i >= n_lazy) worker_data[i].do_work = true; #endif pthread_create (workers + i, NULL, worker_fn, (void *) (worker_data + i)); } Packet_t *(*pkt_fn)(PacketSource_t *, int) = distr ? &getUniformPacket : &getExponentialPacket; while (n_workers_done < n_src) { for (int i = 0; i < n_src; i++) { int n_enqs = get_n_enqueues(queues + i); if (n_enqs == n_packets + 1) continue; if (!check_free(queues + i)) continue; if (n_enqs == n_packets) { enq(queues + i, NULL); } else { Packet_t *pkt = pkt_fn (source, i); enq (queues + i, (void *) pkt); rcvd_packets[packet_ctr] = pkt; packet_ctr += 1; } if (get_n_enqueues(queues + i) == n_packets + 1) n_workers_done += 1; } #ifdef TESTING if (n_workers_done == n_src - n_lazy) break; #endif } for (int i = 0; i < n_src; i++) { long this_fp = 0; pthread_join (workers[i], (void **) &this_fp); total_fp_sum += this_fp; #ifdef TESTING printf("%d\n", get_n_enqueues(queues + i) - 1); #endif } free (worker_data); destroy_queues (n_src, queues); stopTimer(&watch); deletePacketSource (source); // Free all the packets... for (int i = 0; i < packet_ctr; i++) free (rcvd_packets[i]); free (rcvd_packets); #ifdef PERF return getElapsedTime(&watch); #else return total_fp_sum; #endif }