Exemple #1
0
/*
 * 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;
}
Exemple #2
0
/* 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 */
}
Exemple #3
0
/* 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;
}
Exemple #4
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;
}
Exemple #5
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;
}
Exemple #6
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;
}
Exemple #7
0
/*
 * 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;
}
Exemple #8
0
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;
}
Exemple #9
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;
}
Exemple #10
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
}