Ejemplo n.º 1
0
/** Creates a string representation of a Header Field
 *
 * The format used to represent the field is:
 * hpack_header_field@@@e POINTER @e NAME: @e VALUE [ @e REPRESENTATION | Name: @e TYPE_OF_NAME | Value: @e TYPE_OF_VALUE ]
 *
 * @pre @a header needs to have at the very least been [initialized](@ref hpack_header_field_init)
 * @pre @a output chula buffer needs to have been [initialized](@ref chula_buffer_init)
 *
 * @param[in]   header    Header Field to represent.
 * @param[out]  output    Where to output the representation.
 *
 * @return If the operation was successful.
 * @retval ret_ok     The operation was completed successfully.
 * @retval ret_nomem  There was no memory to complete the operation.
 *
 */
ret_t
hpack_header_field_repr (hpack_header_field_t *header,
                         chula_buffer_t       *output)
{
    ret_t ret;

    ret = chula_buffer_add_va (output, "hpack_header_field@%x - ", POINTER_TO_INT(header));

    /* Represent the name-value pair. */
    ret += chula_buffer_add_buffer (output, &header->name);
    ret += chula_buffer_add_str    (output, ": ");
    ret += chula_buffer_add_buffer (output, &header->value);
    ret += chula_buffer_add_str    (output, " [");

    /* Represent the flags. */
    ret += chula_buffer_add_buffer (output,
                                    &hpack_header_field_representations_repr[header->flags.rep]);
    ret += chula_buffer_add_str    (output, " | Name: ");
    ret += chula_buffer_add_buffer (output,
                                    &hpack_header_field_field_type_repr[header->flags.name]);
    ret += chula_buffer_add_str    (output, " | Value: ");
    ret += chula_buffer_add_buffer (output,
                                    &hpack_header_field_field_type_repr[header->flags.value]);
    ret += chula_buffer_add_str    (output, "]");
    ret += chula_buffer_add_str    (output, CRLF);

    return ret;
}
Ejemplo n.º 2
0
END_TEST

START_TEST (_buf)
{
    ret_t           ret;
    void           *p;
    chula_avl_t     avl;
    chula_buffer_t  uno  = CHULA_BUF_INIT;
    chula_buffer_t  dos  = CHULA_BUF_INIT;
    chula_buffer_t  tres = CHULA_BUF_INIT;

    chula_avl_init (&avl);
    chula_buffer_add_str (&uno,  "uno");
    chula_buffer_add_str (&dos,  "dos");
    chula_buffer_add_str (&tres, "tres");

    ret = chula_avl_add (&avl, &uno, INT_TO_POINTER(1));
    ch_assert (ret == ret_ok);
    ret = chula_avl_add (&avl, &dos, INT_TO_POINTER(2));
    ch_assert (ret == ret_ok);
    ret = chula_avl_add (&avl, &tres, INT_TO_POINTER(3));
    ch_assert (ret == ret_ok);

    chula_avl_get (&avl, &dos, &p);
    ch_assert (POINTER_TO_INT(p) == 2);
    chula_avl_get (&avl, &tres, &p);
    ch_assert (POINTER_TO_INT(p) == 3);
    chula_avl_get (&avl, &uno, &p);
    ch_assert (POINTER_TO_INT(p) == 1);

    chula_avl_del (&avl, &dos, NULL);
    chula_avl_get (&avl, &uno, &p);
    ch_assert (POINTER_TO_INT(p) == 1);

    p = NULL;
    ret = chula_avl_get (&avl, &dos, &p);
    ch_assert (ret != ret_ok);
    ch_assert (p == NULL);

    ret = chula_avl_check (AVL_GENERIC(&avl));
    ch_assert (ret == ret_ok);

    chula_buffer_mrproper (&uno);
    chula_buffer_mrproper (&dos);
    chula_buffer_mrproper (&tres);
    chula_avl_mrproper (AVL_GENERIC(&avl), NULL);
}
Ejemplo n.º 3
0
END_TEST

START_TEST (_ptr)
{
    ret_t        ret;
    void        *p;
    chula_avl_t  avl;

    chula_avl_init (&avl);

    ret = chula_avl_add_ptr (&avl, "uno", INT_TO_POINTER(1));
    ch_assert (ret == ret_ok);
    ret = chula_avl_add_ptr (&avl, "dos", INT_TO_POINTER(2));
    ch_assert (ret == ret_ok);
    ret = chula_avl_add_ptr (&avl, "tres", INT_TO_POINTER(3));
    ch_assert (ret == ret_ok);

    chula_avl_get_ptr (&avl, "dos", &p);
    ch_assert (POINTER_TO_INT(p) == 2);
    chula_avl_get_ptr (&avl, "tres", &p);
    ch_assert (POINTER_TO_INT(p) == 3);
    chula_avl_get_ptr (&avl, "uno", &p);
    ch_assert (POINTER_TO_INT(p) == 1);

    chula_avl_set_case (&avl, true);
    chula_avl_get_ptr (&avl, "TrEs", &p);
    ch_assert (POINTER_TO_INT(p) == 3);
    chula_avl_set_case (&avl, false);

    chula_avl_del_ptr (&avl, "dos", NULL);
    chula_avl_get_ptr (&avl, "uno", &p);
    ch_assert (POINTER_TO_INT(p) == 1);

    p = NULL;
    ret = chula_avl_get_ptr (&avl, "dos", &p);
    ch_assert (ret != ret_ok);
    ch_assert (p == NULL);

    ret = chula_avl_check (AVL_GENERIC(&avl));
    ch_assert (ret == ret_ok);

    chula_avl_mrproper (AVL_GENERIC(&avl), NULL);
}
Ejemplo n.º 4
0
void  percent_formatter(GtkTreeViewColumn *tree_column,
  GtkCellRenderer   *cell, 
  GtkTreeModel      *tree_model,
  GtkTreeIter       *iter, 
  gpointer           data)
{
  gfloat f;
  gchar text[64];
  gtk_tree_model_get(tree_model, iter, POINTER_TO_INT(data), &f, -1);
  sprintf(text, "%.1f%%", f);
  g_object_set(cell, "text", text, NULL);
}
Ejemplo n.º 5
0
END_TEST

static ret_t
while_func (chula_buffer_t *key,
            void           *value,
            void           *param)
{
    UNUSED(key);

    *((int *)param) += POINTER_TO_INT(value);
    return ret_ok;
}
Ejemplo n.º 6
0
static void cb_notify_conn(struct ev_loop *l, struct ev_io *watcher,
		int revents) {
	rpc_worker_thread *worker = watcher->data;
	uint64_t n;
	read(worker->notify_fd, &n, sizeof(n));
	if (n != 1) {
		perror("read notify data error");
	}
	//new conn;
	int cfd = POINTER_TO_INT(rpc_queue_pop(worker->queue));
	rpc_conn *c = rpc_conn_new(cfd, worker->loop);
	c->thread = worker;
}
Ejemplo n.º 7
0
void cb_add(rpc_conn *conn, rpc_code code, pointer output, size_t output_len,
		void* data) {
	if (code != RPC_OK) {
		fprintf(stderr, "call error %s\n", rpc_code_format(code));
		exit(1);
	}
	int result = *(int*) output;
	int i = POINTER_TO_INT(data);
	if (result != (2 * i + 1)) {
		fprintf(stderr, "i is %d,result:%d should %d\n", i, result, 2 * i + 1);
		exit(1);
	}
}
Ejemplo n.º 8
0
static int key_cmp(const void *key, const void *data) {
    int a;
    test_t *b;

    a = POINTER_TO_INT(key);
    b = (test_t *) data;

    if (a < b->key) {
        return -1;
    } else if (a > b->key) {
        return 1;
    }

    return 0;
}
Ejemplo n.º 9
0
static void worker_notify_cb(struct ev_loop *l,struct ev_io *watcher,int revents){
    zero_worker_thread *worker = watcher->data;
    uint64_t n;
    read(worker->notify_fd,&n,sizeof(n));
    if (n != 1){
        perror("notify data error");
    }
    // we can handle the client sock here
    //
    int cfd = POINTER_TO_INT(zero_queue_pop(worker->queue));
    char buf[1024];
    read(cfd,buf,sizeof(buf));
    //printf("i got the data %s",buf);
    write(cfd,buf,sizeof(buf));
    close(cfd);
}
Ejemplo n.º 10
0
int tmp007_init_interrupt(struct device *dev)
{
	struct tmp007_data *drv_data = dev->driver_data;
	int rc;

	rc = tmp007_reg_update(drv_data, TMP007_REG_CONFIG,
			       TMP007_ALERT_EN_BIT, TMP007_ALERT_EN_BIT);
	if (rc != 0) {
		SYS_LOG_DBG("Failed to enable interrupt pin!");
		return -EIO;
	}

	/* setup gpio interrupt */
	drv_data->gpio = device_get_binding(CONFIG_TMP007_GPIO_DEV_NAME);
	if (drv_data->gpio == NULL) {
		SYS_LOG_DBG("Failed to get pointer to %s device!",
		    CONFIG_TMP007_GPIO_DEV_NAME);
		return -EINVAL;
	}

	gpio_pin_configure(drv_data->gpio, CONFIG_TMP007_GPIO_PIN_NUM,
			   GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL |
			   GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);

	gpio_init_callback(&drv_data->gpio_cb,
			   tmp007_gpio_callback,
			   BIT(CONFIG_TMP007_GPIO_PIN_NUM));

	rc = gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb);
	if (rc != 0) {
		SYS_LOG_DBG("Failed to set gpio callback!");
		return -EIO;
	}

#if defined(CONFIG_TMP007_TRIGGER_OWN_FIBER)
	nano_sem_init(&drv_data->gpio_sem);

	fiber_start(drv_data->fiber_stack, CONFIG_TMP007_FIBER_STACK_SIZE,
		    (nano_fiber_entry_t)tmp007_fiber, POINTER_TO_INT(dev),
		    0, CONFIG_TMP007_FIBER_PRIORITY, 0);
#elif defined(CONFIG_TMP007_TRIGGER_GLOBAL_FIBER)
	drv_data->work.handler = tmp007_fiber_cb;
	drv_data->work.arg = dev;
#endif

	return 0;
}
Ejemplo n.º 11
0
int hts221_init_interrupt(struct device *dev)
{
	struct hts221_data *drv_data = dev->driver_data;

	/* setup data ready gpio interrupt */
	drv_data->gpio = device_get_binding(CONFIG_HTS221_GPIO_DEV_NAME);
	if (drv_data->gpio == NULL) {
		SYS_LOG_ERR("Cannot get pointer to %s device.",
			    CONFIG_HTS221_GPIO_DEV_NAME);
		return -EINVAL;
	}

	gpio_pin_configure(drv_data->gpio, CONFIG_HTS221_GPIO_PIN_NUM,
			   GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
			   GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);

	gpio_init_callback(&drv_data->gpio_cb,
			   hts221_gpio_callback,
			   BIT(CONFIG_HTS221_GPIO_PIN_NUM));

	if (gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb) < 0) {
		SYS_LOG_ERR("Could not set gpio callback.");
		return -EIO;
	}

	/* enable data-ready interrupt */
	if (i2c_reg_write_byte(drv_data->i2c, HTS221_I2C_ADDR,
			       HTS221_REG_CTRL3, HTS221_DRDY_EN) < 0) {
		SYS_LOG_ERR("Could not enable data-ready interrupt.");
		return -EIO;
	}

#if defined(CONFIG_HTS221_TRIGGER_OWN_THREAD)
	k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);

	k_thread_spawn(drv_data->thread_stack, CONFIG_HTS221_THREAD_STACK_SIZE,
		    (k_thread_entry_t)hts221_thread, POINTER_TO_INT(dev),
		    0, NULL, K_PRIO_COOP(CONFIG_HTS221_THREAD_PRIORITY), 0, 0);
#elif defined(CONFIG_HTS221_TRIGGER_GLOBAL_THREAD)
	drv_data->work.handler = hts221_work_cb;
	drv_data->dev = dev;
#endif

	gpio_pin_enable_callback(drv_data->gpio, CONFIG_HTS221_GPIO_PIN_NUM);

	return 0;
}
Ejemplo n.º 12
0
static inline int quark_se_clock_control_off(struct device *dev,
        clock_control_subsys_t sub_system)
{
    struct quark_se_clock_control_config *info = dev->config->config_info;
    uint32_t subsys = POINTER_TO_INT(sub_system);

    if (sub_system == CLOCK_CONTROL_SUBSYS_ALL) {
        DBG("Disabling all clock gates on dev %p\n", dev);
        sys_write32(0x00000000, info->base_address);

        return DEV_OK;
    }

    DBG("clock gate on dev %p subsystem %u\n", dev, subsys);

    return sys_test_and_clear_bit(info->base_address, subsys);
}
Ejemplo n.º 13
0
static inline int quark_se_clock_control_off(struct device *dev,
					     clock_control_subsys_t sub_system)
{
	const struct quark_se_clock_control_config *info =
		dev->config->config_info;
	u32_t subsys = POINTER_TO_INT(sub_system);

	if (sub_system == CLOCK_CONTROL_SUBSYS_ALL) {
		SYS_LOG_DBG("Disabling all clock gates on dev %p", dev);
		WRITE(0x00000000, info->base_address);

		return 0;
	}

	SYS_LOG_DBG("clock gate on dev %p subsystem %u", dev, subsys);

	return TEST_CLEAR_BIT(info->base_address, subsys);
}
Ejemplo n.º 14
0
static int gpio_sch_set_callback(struct device *dev, gpio_callback_t callback)
{
	struct gpio_sch_data *gpio = dev->driver_data;

	gpio->callback = callback;

	/* Start the fiber only when relevant */
	if (callback && (gpio->cb_enabled || gpio->port_cb)) {
		if (!gpio->poll) {
			DBG("Starting SCH GPIO polling fiber\n");
			gpio->poll = 1;
			fiber_start(gpio->polling_stack,
					GPIO_SCH_POLLING_STACK_SIZE,
					_gpio_sch_poll_status,
					POINTER_TO_INT(dev), 0, 0, 0);
		}
	} else {
		gpio->poll = 0;
	}

	return 0;
}
Ejemplo n.º 15
0
int sx9500_setup_interrupt(struct device *dev)
{
	struct sx9500_data *data = dev->driver_data;
	struct device *gpio;

#ifdef CONFIG_SX9500_TRIGGER_OWN_THREAD
	k_sem_init(&data->sem, 0, UINT_MAX);
#else
	data->work.handler = sx9500_work_cb;
	data->dev = dev;
#endif

	gpio = device_get_binding(CONFIG_SX9500_GPIO_CONTROLLER);
	if (!gpio) {
		SYS_LOG_DBG("sx9500: gpio controller %s not found",
			    CONFIG_SX9500_GPIO_CONTROLLER);
		return -EINVAL;
	}

	gpio_pin_configure(gpio, CONFIG_SX9500_GPIO_PIN,
			   GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
			   GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE);

	gpio_init_callback(&data->gpio_cb,
			   sx9500_gpio_cb,
			   BIT(CONFIG_SX9500_GPIO_PIN));

	gpio_add_callback(gpio, &data->gpio_cb);
	gpio_pin_enable_callback(gpio, CONFIG_SX9500_GPIO_PIN);

#ifdef CONFIG_SX9500_TRIGGER_OWN_THREAD
	k_thread_spawn(sx9500_thread_stack, CONFIG_SX9500_THREAD_STACK_SIZE,
			  sx9500_thread_main, POINTER_TO_INT(dev), 0, NULL,
			  K_PRIO_COOP(CONFIG_SX9500_THREAD_PRIORITY), 0, 0);
#endif

	return 0;
}
Ejemplo n.º 16
0
int bma280_init_interrupt(struct device *dev)
{
	struct bma280_data *drv_data = dev->driver_data;
	int rc;

	/* set latched interrupts */
	rc = i2c_reg_write_byte(drv_data->i2c, BMA280_I2C_ADDRESS,
				BMA280_REG_INT_RST_LATCH,
				BMA280_BIT_INT_LATCH_RESET |
				BMA280_INT_MODE_LATCH);
	if (rc != 0) {
		SYS_LOG_DBG("Could not set latched interrupts");
		return -EIO;
	}

	/* setup data ready gpio interrupt */
	drv_data->gpio = device_get_binding(CONFIG_BMA280_GPIO_DEV_NAME);
	if (drv_data->gpio == NULL) {
		SYS_LOG_DBG("Cannot get pointer to %s device",
		    CONFIG_BMA280_GPIO_DEV_NAME);
		return -EINVAL;
	}

	gpio_pin_configure(drv_data->gpio, CONFIG_BMA280_GPIO_PIN_NUM,
			   GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL |
			   GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);

	gpio_init_callback(&drv_data->gpio_cb,
			   bma280_gpio_callback,
			   BIT(CONFIG_BMA280_GPIO_PIN_NUM));

	rc = gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb);
	if (rc != 0) {
		SYS_LOG_DBG("Could not set gpio callback");
		return -EIO;
	}

	/* map data ready interrupt to INT1 */
	rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS,
				 BMA280_REG_INT_MAP_1,
				 BMA280_INT_MAP_1_BIT_DATA,
				 BMA280_INT_MAP_1_BIT_DATA);
	if (rc != 0) {
		SYS_LOG_DBG("Could not map data ready interrupt pin");
		return -EIO;
	}

	/* map any-motion interrupt to INT1 */
	rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS,
				 BMA280_REG_INT_MAP_0,
				 BMA280_INT_MAP_0_BIT_SLOPE,
				 BMA280_INT_MAP_0_BIT_SLOPE);
	if (rc != 0) {
		SYS_LOG_DBG("Could not map any-motion interrupt pin");
		return -EIO;
	}

	/* disable data ready interrupt */
	rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS,
				 BMA280_REG_INT_EN_1,
				 BMA280_BIT_DATA_EN, 0);
	if (rc != 0) {
		SYS_LOG_DBG("Could not disable data ready interrupt");
		return -EIO;
	}

	/* disable any-motion interrupt */
	rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS,
				 BMA280_REG_INT_EN_0,
				 BMA280_SLOPE_EN_XYZ, 0);
	if (rc != 0) {
		SYS_LOG_DBG("Could not disable data ready interrupt");
		return -EIO;
	}

#if defined(CONFIG_BMA280_TRIGGER_OWN_FIBER)
	nano_sem_init(&drv_data->gpio_sem);

	fiber_start(drv_data->fiber_stack, CONFIG_BMA280_FIBER_STACK_SIZE,
		    (nano_fiber_entry_t)bma280_fiber, POINTER_TO_INT(dev),
		    0, CONFIG_BMA280_FIBER_PRIORITY, 0);
#elif defined(CONFIG_BMA280_TRIGGER_GLOBAL_FIBER)
	drv_data->work.handler = bma280_fiber_cb;
	drv_data->work.arg = dev;
#endif

	gpio_pin_enable_callback(drv_data->gpio, CONFIG_BMA280_GPIO_PIN_NUM);

	return 0;
}
Ejemplo n.º 17
0
/* This is called by contiki/ip/tcpip.c:tcpip_uipcall() when packet
 * is processed.
 */
PROCESS_THREAD(tcp, ev, data, buf, user_data)
{
	PROCESS_BEGIN();

	while(1) {
		PROCESS_YIELD_UNTIL(ev == tcpip_event);

		if (POINTER_TO_INT(data) == TCP_WRITE_EVENT) {
			/* We want to send data to peer. */
			struct net_context *context = user_data;

			if (!context) {
				continue;
			}

			do {
				context = user_data;
				if (!context || !buf) {
					break;
				}

				if (!context->ps.net_buf ||
				    context->ps.net_buf != buf) {
					NET_DBG("psock init %p buf %p\n",
						&context->ps, buf);
					PSOCK_INIT(&context->ps, buf);
				}

				handle_tcp_connection(&context->ps,
						      POINTER_TO_INT(data),
						      buf);

				PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event);

				if (POINTER_TO_INT(data) != TCP_WRITE_EVENT) {
					goto read_data;
				}
			} while(!(uip_closed(buf)  ||
				  uip_aborted(buf) ||
				  uip_timedout(buf)));

			context = user_data;

			if (context &&
			    context->tcp_type == NET_TCP_TYPE_CLIENT) {
				NET_DBG("\nConnection closed.\n");
				ip_buf_sent_status(buf) = -ECONNRESET;
			}

			continue;
		}

	read_data:
		/* We are receiving data from peer. */
		if (buf && uip_newdata(buf)) {
			struct net_buf *clone;

			if (!uip_len(buf)) {
				continue;
			}

			/* Note that uIP stack will reuse the buffer when
			 * sending ACK to peer host. The sending will happen
			 * right after this function returns. Because of this
			 * we cannot use the same buffer to pass data to
			 * application.
			 */
			clone = net_buf_clone(buf);
			if (!clone) {
				NET_ERR("No enough RX buffers, "
					"packet %p discarded\n", buf);
				continue;
			}

			ip_buf_appdata(clone) = uip_buf(clone) +
				(ip_buf_appdata(buf) - (void *)uip_buf(buf));
			ip_buf_appdatalen(clone) = uip_len(buf);
			ip_buf_len(clone) = ip_buf_len(buf);
			ip_buf_context(clone) = user_data;
			uip_set_conn(clone) = uip_conn(buf);
			uip_flags(clone) = uip_flags(buf);
			uip_flags(clone) |= UIP_CONNECTED;

			NET_DBG("packet received context %p buf %p len %d "
				"appdata %p appdatalen %d\n",
				ip_buf_context(clone),
				clone,
				ip_buf_len(clone),
				ip_buf_appdata(clone),
				ip_buf_appdatalen(clone));

			nano_fifo_put(net_context_get_queue(user_data), clone);

			/* We let the application to read the data now */
			fiber_yield();
		}
	}

	PROCESS_END();
}
Ejemplo n.º 18
0
void foreach_cb(void *item, void *data)
{
    int i = POINTER_TO_INT(item);
    int *dest = (int*) data;
    *dest = *dest + i;
}
Ejemplo n.º 19
0
int main(int argc, char *argv[])
{
    FILE *out=0;		/* Output data file 			*/
    char s[255]; 		/* Generic string			*/
    char *memtmp;
    char *memtmp1;
    MPI_Status status;

    int ii, i, j, k, n, nq,	/* Loop indices				*/
	bufoffset = 0,		/* Align buffer to this			*/
	bufalign = 16*1024,	/* Boundary to align buffer to		*/
	nrepeat01, nrepeat12,	/* Number of time to do the transmission*/
	nrepeat012,
	len,			/* Number of bytes to be transmitted	*/
	inc = 1,		/* Increment value			*/
	pert,			/* Perturbation value			*/
        ipert,                  /* index of the perturbation loop	*/
	start = 0,		/* Starting value for signature curve 	*/
	end = MAXINT,		/* Ending value for signature curve	*/
	printopt = 1,		/* Debug print statements flag		*/
	middle_rank = 0,        /* rank 0, 1 or 2 where 2-0-1 or 0-1-2 or 1-2-0 */
	tint;
    
    ArgStruct	args01, args12, args012;/* Argumentsfor all the calls	*/
    
    double t, t0, t1,           /* Time variables			*/
	tlast01, tlast12, tlast012,/* Time for the last transmission	*/
	latency01, latency12,	/* Network message latency		*/
	latency012, tdouble;    /* Network message latency to go from 0 -> 1 -> 2 */
#ifdef CREATE_DIFFERENCE_CURVES
    int itrial, ntrials;
    double *dtrials;
#endif

    Data *bwdata01, *bwdata12, *bwdata012;/* Bandwidth curve data 	*/
    
    BOOL bNoCache = FALSE;
    BOOL bSavePert = FALSE;
    BOOL bUseMegaBytes = FALSE;

    MPI_Init(&argc, &argv);
    
    MPI_Comm_size(MPI_COMM_WORLD, &g_nNproc);
    MPI_Comm_rank(MPI_COMM_WORLD, &g_nIproc);
    
    if (g_nNproc != 3)
    {
	if (g_nIproc == 0)
	    PrintOptions();
	MPI_Finalize();
	exit(0);
    }

    GetOptDouble(&argc, &argv, "-time", &g_STOPTM);
    GetOptInt(&argc, &argv, "-reps", &g_NSAMP);
    GetOptInt(&argc, &argv, "-start", &start);
    GetOptInt(&argc, &argv, "-end", &end);
    bNoCache = GetOpt(&argc, &argv, "-nocache");
    bUseMegaBytes = GetOpt(&argc, &argv, "-mb");
    if (GetOpt(&argc, &argv, "-noprint"))
	printopt = 0;
    bSavePert = GetOpt(&argc, &argv, "-pert");
    GetOptInt(&argc, &argv, "-middle", &middle_rank);
    if (middle_rank < 0 || middle_rank > 2)
	middle_rank = 0;

    bwdata01 = malloc((g_NSAMP+1) * sizeof(Data));
    bwdata12 = malloc((g_NSAMP+1) * sizeof(Data));
    bwdata012 = malloc((g_NSAMP+1) * sizeof(Data));

    if (g_nIproc == 0)
	strcpy(s, "adapt.out");
    GetOptString(&argc, &argv, "-out", s);
    
    if (start > end)
    {
	fprintf(stdout, "Start MUST be LESS than end\n");
	exit(420132);
    }

    Setup(middle_rank, &args01, &args12, &args012);

    if (g_nIproc == 0)
    {
	if ((out = fopen(s, "w")) == NULL)
	{
	    fprintf(stdout,"Can't open %s for output\n", s);
	    exit(1);
	}
    }

    /* Calculate latency */
    switch (g_proc_loc)
    {
    case LEFT_PROCESS:
	latency01 = TestLatency(&args01);
	/*printf("[0] latency01 = %0.9f\n", latency01);fflush(stdout);*/
	RecvTime(&args01, &latency12);
	/*printf("[0] latency12 = %0.9f\n", latency12);fflush(stdout);*/
	break;
    case MIDDLE_PROCESS:
	latency01 = TestLatency(&args01);
	/*printf("[1] latency01 = %0.9f\n", latency01);fflush(stdout);*/
	SendTime(&args12, &latency01);
	latency12 = TestLatency(&args12);
	/*printf("[1] latency12 = %0.9f\n", latency12);fflush(stdout);*/
	SendTime(&args01, &latency12);
	break;
    case RIGHT_PROCESS:
	RecvTime(&args12, &latency01);
	/*printf("[2] latency01 = %0.9f\n", latency01);fflush(stdout);*/
	latency12 = TestLatency(&args12);
	/*printf("[2] latency12 = %0.9f\n", latency12);fflush(stdout);*/
	break;
    }

    latency012 = TestLatency012(&args012);

    if ((g_nIproc == 0) && printopt)
    {
	printf("Latency%d%d_ : %0.9f\n", g_left_rank, g_middle_rank, latency01);
	printf("Latency_%d%d : %0.9f\n", g_middle_rank, g_right_rank, latency12);
	printf("Latency%d%d%d : %0.9f\n", g_left_rank, g_middle_rank, g_right_rank, latency012);
	fflush(stdout);
	printf("Now starting main loop\n");
	fflush(stdout);
    }
    tlast01 = latency01;
    tlast12 = latency12;
    tlast012 = latency012;
    inc = (start > 1) ? start/2: inc;
    args01.bufflen = start;
    args12.bufflen = start;
    args012.bufflen = start;

#ifdef CREATE_DIFFERENCE_CURVES
    /* print the header line of the output file */
    if (g_nIproc == 0)
    {
	fprintf(out, "bytes\tMbits/s\ttime\tMbits/s\ttime");
	for (ii=1, itrial=0; itrial<MAX_NUM_O12_TRIALS; ii <<= 1, itrial++)
	    fprintf(out, "\t%d", ii);
	fprintf(out, "\n");
	fflush(out);
    }
    ntrials = MAX_NUM_O12_TRIALS;
    dtrials = malloc(sizeof(double)*ntrials);
#endif

    /* Main loop of benchmark */
    for (nq = n = 0, len = start; 
         n < g_NSAMP && tlast012 < g_STOPTM && len <= end; 
	 len = len + inc, nq++)
    {
	if (nq > 2)
	    inc = (nq % 2) ? inc + inc : inc;

	/* clear the old values */
	for (itrial = 0; itrial < ntrials; itrial++)
	{
	    dtrials[itrial] = LONGTIME;
	}

	/* This is a perturbation loop to test nearby values */
	for (ipert = 0, pert = (inc > PERT + 1) ? -PERT : 0;
	     pert <= PERT; 
	     ipert++, n++, pert += (inc > PERT + 1) ? PERT : PERT + 1)
	{


	    /*****************************************************/
	    /*         Run a trial between rank 0 and 1          */
	    /*****************************************************/

	    MPI_Barrier(MPI_COMM_WORLD);


	    if (g_proc_loc == RIGHT_PROCESS)
		goto skip_01_trial;

	    /* Calculate howmany times to repeat the experiment. */
	    if (args01.tr)
	    {
		if (args01.bufflen == 0)
		    nrepeat01 = args01.latency_reps;
		else
		    nrepeat01 = (int)(MAX((RUNTM / ((double)args01.bufflen /
			           (args01.bufflen - inc + 1.0) * tlast01)), TRIALS));
		SendReps(&args01, &nrepeat01);
	    }
	    else
	    {
		RecvReps(&args01, &nrepeat01);
	    }

	    /* Allocate the buffer */
	    args01.bufflen = len + pert;
	    /* printf("allocating %d bytes\n", args01.bufflen * nrepeat01 + bufalign); */
	    if (bNoCache)
	    {
		if ((args01.sbuff = (char *)malloc(args01.bufflen * nrepeat01 + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    else
	    {
		if ((args01.sbuff = (char *)malloc(args01.bufflen + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    /* if ((args01.rbuff = (char *)malloc(args01.bufflen * nrepeat01 + bufalign)) == (char *)NULL) */
	    if ((args01.rbuff = (char *)malloc(args01.bufflen + bufalign)) == (char *)NULL)
	    {
		fprintf(stdout,"Couldn't allocate memory\n");
		fflush(stdout);
		break;
	    }

	    /* save the original pointers in case alignment moves them */
	    memtmp = args01.sbuff;
	    memtmp1 = args01.rbuff;

	    /* Possibly align the data buffer */
	    if (!bNoCache)
	    {
		if (bufalign != 0)
		{
		    args01.sbuff += (bufalign - (POINTER_TO_INT(args01.sbuff) % bufalign) + bufoffset) % bufalign;
		    /* args01.rbuff += (bufalign - ((MPI_Aint)args01.rbuff % bufalign) + bufoffset) % bufalign; */
		}
	    }
	    args01.rbuff += (bufalign - (POINTER_TO_INT(args01.rbuff) % bufalign) + bufoffset) % bufalign;
	    
	    if (args01.tr && printopt)
	    {
		fprintf(stdout,"%3d: %9d bytes %4d times --> ",
		    n, args01.bufflen, nrepeat01);
		fflush(stdout);
	    }
	    
	    /* Finally, we get to transmit or receive and time */
	    if (args01.tr)
	    {
		bwdata01[n].t = LONGTIME;
		t1 = 0;
		for (i = 0; i < TRIALS; i++)
		{
		    if (bNoCache)
		    {
			if (bufalign != 0)
			{
			    args01.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args01.sbuff) % bufalign) + bufoffset) % bufalign);
			    /* args01.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args01.rbuff % bufalign) + bufoffset) % bufalign); */
			}
			else
			{
			    args01.sbuff = memtmp;
			    /* args01.rbuff = memtmp1; */
			}
		    }
		    
		    Sync(&args01);
		    t0 = MPI_Wtime();
		    for (j = 0; j < nrepeat01; j++)
		    {
			MPI_Send(args01.sbuff,  args01.bufflen, MPI_BYTE,  args01.nbor, MSG_TAG_01, MPI_COMM_WORLD);
			MPI_Recv(args01.rbuff,  args01.bufflen, MPI_BYTE,  args01.nbor, MSG_TAG_01, MPI_COMM_WORLD, &status);
			if (bNoCache)
			{
			    args01.sbuff += args01.bufflen;
			    /* args01.rbuff += args01.bufflen; */
			}
		    }
		    t = (MPI_Wtime() - t0)/(2 * nrepeat01);

		    t1 += t;
		    bwdata01[n].t = MIN(bwdata01[n].t, t);
		}
		SendTime(&args01, &bwdata01[n].t);
	    }
	    else
	    {
		bwdata01[n].t = LONGTIME;
		t1 = 0;
		for (i = 0; i < TRIALS; i++)
		{
		    if (bNoCache)
		    {
			if (bufalign != 0)
			{
			    args01.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args01.sbuff) % bufalign) + bufoffset) % bufalign);
			    /* args01.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args01.rbuff % bufalign) + bufoffset) % bufalign); */
			}
			else
			{
			    args01.sbuff = memtmp;
			    /* args01.rbuff = memtmp1; */
			}
		    }
		    
		    Sync(&args01);
		    t0 = MPI_Wtime();
		    for (j = 0; j < nrepeat01; j++)
		    {
			MPI_Recv(args01.rbuff,  args01.bufflen, MPI_BYTE,  args01.nbor, MSG_TAG_01, MPI_COMM_WORLD, &status);
			MPI_Send(args01.sbuff,  args01.bufflen, MPI_BYTE,  args01.nbor, MSG_TAG_01, MPI_COMM_WORLD);
			if (bNoCache)
			{
			    args01.sbuff += args01.bufflen;
			    /* args01.rbuff += args01.bufflen; */
			}
		    }
		    t = (MPI_Wtime() - t0)/(2 * nrepeat01);
		}
		RecvTime(&args01, &bwdata01[n].t);
	    }
	    tlast01 = bwdata01[n].t;
	    bwdata01[n].bits = args01.bufflen * CHARSIZE;
	    bwdata01[n].bps = bwdata01[n].bits / (bwdata01[n].t * 1024 * 1024);
	    bwdata01[n].repeat = nrepeat01;
	    
	    if (args01.tr)
	    {
		if (bSavePert)
		{
		    if (args01.iproc == 0)
		    {
			if (bUseMegaBytes)
			    fprintf(out, "%d\t%f\t%0.9f\t", bwdata01[n].bits / 8, bwdata01[n].bps / 8, bwdata01[n].t);
			else
			    fprintf(out, "%d\t%f\t%0.9f\t", bwdata01[n].bits / 8, bwdata01[n].bps, bwdata01[n].t);
			fflush(out);
		    }
		    else
		    {
			MPI_Send(&bwdata01[n].bits, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
			MPI_Send(&bwdata01[n].bps, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
			MPI_Send(&bwdata01[n].t, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
		    }
		}
	    }
	    
	    free(memtmp);
	    free(memtmp1);
	    
	    if (args01.tr && printopt)
	    {
		if (bUseMegaBytes)
		    printf(" %6.2f MBps in %0.9f sec\n", bwdata01[n].bps / 8, tlast01);
		else
		    printf(" %6.2f Mbps in %0.9f sec\n", bwdata01[n].bps, tlast01);
		fflush(stdout);
	    }

skip_01_trial:
	    if (g_proc_loc == RIGHT_PROCESS && g_nIproc == 0 && bSavePert)
	    {
		MPI_Recv(&tint, 1, MPI_INT, g_left_rank, 1, MPI_COMM_WORLD, &status);
		fprintf(out, "%d\t", tint/8);
		MPI_Recv(&tdouble, 1, MPI_DOUBLE, g_left_rank, 1, MPI_COMM_WORLD, &status);
		if (bUseMegaBytes)
		    tdouble = tdouble / 8.0;
		fprintf(out, "%f\t", tdouble);
		MPI_Recv(&tdouble, 1, MPI_DOUBLE, g_left_rank, 1, MPI_COMM_WORLD, &status);
		fprintf(out, "%0.9f\t", tdouble);
		fflush(out);
	    }


	    /*****************************************************/
	    /*         Run a trial between rank 1 and 2          */
	    /*****************************************************/

	    MPI_Barrier(MPI_COMM_WORLD);


	    if (g_proc_loc == LEFT_PROCESS)
		goto skip_12_trial;

	    /* Calculate howmany times to repeat the experiment. */
	    if (args12.tr)
	    {
		if (args12.bufflen == 0)
		    nrepeat12 = args12.latency_reps;
		else
		    nrepeat12 = (int)(MAX((RUNTM / ((double)args12.bufflen /
			           (args12.bufflen - inc + 1.0) * tlast12)), TRIALS));
		SendReps(&args12, &nrepeat12);
	    }
	    else
	    {
		RecvReps(&args12, &nrepeat12);
	    }
	    
	    /* Allocate the buffer */
	    args12.bufflen = len + pert;
	    /* printf("allocating %d bytes\n", args12.bufflen * nrepeat12 + bufalign); */
	    if (bNoCache)
	    {
		if ((args12.sbuff = (char *)malloc(args12.bufflen * nrepeat12 + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    else
	    {
		if ((args12.sbuff = (char *)malloc(args12.bufflen + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    /* if ((args12.rbuff = (char *)malloc(args12.bufflen * nrepeat12 + bufalign)) == (char *)NULL) */
	    if ((args12.rbuff = (char *)malloc(args12.bufflen + bufalign)) == (char *)NULL)
	    {
		fprintf(stdout,"Couldn't allocate memory\n");
		fflush(stdout);
		break;
	    }

	    /* save the original pointers in case alignment moves them */
	    memtmp = args12.sbuff;
	    memtmp1 = args12.rbuff;
	    
	    /* Possibly align the data buffer */
	    if (!bNoCache)
	    {
		if (bufalign != 0)
		{
		    args12.sbuff += (bufalign - (POINTER_TO_INT(args12.sbuff) % bufalign) + bufoffset) % bufalign;
		    /* args12.rbuff += (bufalign - ((MPI_Aint)args12.rbuff % bufalign) + bufoffset) % bufalign; */
		}
	    }
	    args12.rbuff += (bufalign - (POINTER_TO_INT(args12.rbuff) % bufalign) + bufoffset) % bufalign;
	    
	    if (args12.tr && printopt)
	    {
		printf("%3d: %9d bytes %4d times --> ", n, args12.bufflen, nrepeat12);
		fflush(stdout);
	    }
	    
	    /* Finally, we get to transmit or receive and time */
	    if (args12.tr)
	    {
		bwdata12[n].t = LONGTIME;
		t1 = 0;
		for (i = 0; i < TRIALS; i++)
		{
		    if (bNoCache)
		    {
			if (bufalign != 0)
			{
			    args12.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args12.sbuff) % bufalign) + bufoffset) % bufalign);
			    /* args12.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args12.rbuff % bufalign) + bufoffset) % bufalign); */
			}
			else
			{
			    args12.sbuff = memtmp;
			    /* args12.rbuff = memtmp1; */
			}
		    }
		    
		    Sync(&args12);
		    t0 = MPI_Wtime();
		    for (j = 0; j < nrepeat12; j++)
		    {
			MPI_Send(args12.sbuff,  args12.bufflen, MPI_BYTE,  args12.nbor, MSG_TAG_12, MPI_COMM_WORLD);
			MPI_Recv(args12.rbuff,  args12.bufflen, MPI_BYTE,  args12.nbor, MSG_TAG_12, MPI_COMM_WORLD, &status);
			if (bNoCache)
			{
			    args12.sbuff += args12.bufflen;
			    /* args12.rbuff += args12.bufflen; */
			}
		    }
		    t = (MPI_Wtime() - t0)/(2 * nrepeat12);

		    t1 += t;
		    bwdata12[n].t = MIN(bwdata12[n].t, t);
		}
		SendTime(&args12, &bwdata12[n].t);
	    }
	    else
	    {
		bwdata12[n].t = LONGTIME;
		t1 = 0;
		for (i = 0; i < TRIALS; i++)
		{
		    if (bNoCache)
		    {
			if (bufalign != 0)
			{
			    args12.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args12.sbuff) % bufalign) + bufoffset) % bufalign);
			    /* args12.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args12.rbuff % bufalign) + bufoffset) % bufalign); */
			}
			else
			{
			    args12.sbuff = memtmp;
			    /* args12.rbuff = memtmp1; */
			}
		    }
		    
		    Sync(&args12);
		    t0 = MPI_Wtime();
		    for (j = 0; j < nrepeat12; j++)
		    {
			MPI_Recv(args12.rbuff,  args12.bufflen, MPI_BYTE,  args12.nbor, MSG_TAG_12, MPI_COMM_WORLD, &status);
			MPI_Send(args12.sbuff,  args12.bufflen, MPI_BYTE,  args12.nbor, MSG_TAG_12, MPI_COMM_WORLD);
			if (bNoCache)
			{
			    args12.sbuff += args12.bufflen;
			    /* args12.rbuff += args12.bufflen; */
			}
		    }
		    t = (MPI_Wtime() - t0)/(2 * nrepeat12);
		}
		RecvTime(&args12, &bwdata12[n].t);
	    }
	    tlast12 = bwdata12[n].t;
	    bwdata12[n].bits = args12.bufflen * CHARSIZE;
	    bwdata12[n].bps = bwdata12[n].bits / (bwdata12[n].t * 1024 * 1024);
	    bwdata12[n].repeat = nrepeat12;

	    if (args12.tr)
	    {
		if (bSavePert)
		{
		    if (g_nIproc == 0)
		    {
			if (bUseMegaBytes)
			    fprintf(out,"%f\t%0.9f\t", bwdata12[n].bps / 8, bwdata12[n].t);
			else
			    fprintf(out,"%f\t%0.9f\t", bwdata12[n].bps, bwdata12[n].t);
			fflush(out);
		    }
		    else
		    {
			MPI_Send(&bwdata12[n].bps, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
			MPI_Send(&bwdata12[n].t, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
		    }
		}
	    }
	    
	    free(memtmp);
	    free(memtmp1);
	    
	    if (args12.tr && printopt)
	    {
		if (bUseMegaBytes)
		    printf(" %6.2f MBps in %0.9f sec\n", bwdata12[n].bps / 8, tlast12);
		else
		    printf(" %6.2f Mbps in %0.9f sec\n", bwdata12[n].bps, tlast12);
		fflush(stdout);
	    }

skip_12_trial:
	    if (g_proc_loc == LEFT_PROCESS && g_nIproc == 0 && bSavePert)
	    {
		MPI_Recv(&tdouble, 1, MPI_DOUBLE, g_middle_rank, 1, MPI_COMM_WORLD, &status);
		if (bUseMegaBytes)
		    tdouble = tdouble / 8.0;
		fprintf(out, "%f\t", tdouble);
		MPI_Recv(&tdouble, 1, MPI_DOUBLE, g_middle_rank, 1, MPI_COMM_WORLD, &status);
		fprintf(out, "%0.9f\t", tdouble);
		fflush(out);
	    }


#ifdef CREATE_DIFFERENCE_CURVES
	    /*****************************************************/
	    /*         Run a trial between rank 0, 1 and 2       */
	    /*****************************************************/

	    MPI_Barrier(MPI_COMM_WORLD);


	    /* Calculate howmany times to repeat the experiment. */
	    if (g_nIproc == 0)
	    {
		if (args012.bufflen == 0)
		    nrepeat012 = g_latency012_reps;
		else
		    nrepeat012 = (int)(MAX((RUNTM / ((double)args012.bufflen /
			           (args012.bufflen - inc + 1.0) * tlast012)), TRIALS));
		MPI_Bcast(&nrepeat012, 1, MPI_INT, 0, MPI_COMM_WORLD);
	    }
	    else
	    {
		MPI_Bcast(&nrepeat012, 1, MPI_INT, 0, MPI_COMM_WORLD);
	    }

	    /* Allocate the buffer */
	    args012.bufflen = len + pert;
	    /* printf("allocating %d bytes\n", args12.bufflen * nrepeat012 + bufalign); */
	    if (bNoCache)
	    {
		if ((args012.sbuff = (char *)malloc(args012.bufflen * nrepeat012 + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    else
	    {
		if ((args012.sbuff = (char *)malloc(args012.bufflen + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    /* if ((args012.rbuff = (char *)malloc(args012.bufflen * nrepeat012 + bufalign)) == (char *)NULL) */
	    if ((args012.rbuff = (char *)malloc(args012.bufflen + bufalign)) == (char *)NULL)
	    {
		fprintf(stdout,"Couldn't allocate memory\n");
		fflush(stdout);
		break;
	    }

	    /* save the original pointers in case alignment moves them */
	    memtmp = args012.sbuff;
	    memtmp1 = args012.rbuff;
	    
	    /* Possibly align the data buffer */
	    if (!bNoCache)
	    {
		if (bufalign != 0)
		{
		    args012.sbuff += (bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign;
		    /* args12.rbuff += (bufalign - ((MPI_Aint)args12.rbuff % bufalign) + bufoffset) % bufalign; */
		}
	    }
	    args012.rbuff += (bufalign - (POINTER_TO_INT(args012.rbuff) % bufalign) + bufoffset) % bufalign;
	    
	    if (g_nIproc == 0 && printopt)
	    {
		printf("%3d: %9d bytes %4d times --> ", n, args012.bufflen, nrepeat012);
		fflush(stdout);
	    }

	    for (itrial=0, ii=1; ii <= nrepeat012 && itrial < ntrials; ii <<= 1, itrial++)
	    {
		/* Finally, we get to transmit or receive and time */
		switch (g_proc_loc)
		{
		case LEFT_PROCESS:
		    bwdata012[n].t = LONGTIME;
		    t1 = 0;
		    for (i = 0; i < TRIALS; i++)
		    {
			if (bNoCache)
			{
			    if (bufalign != 0)
			    {
				args012.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign);
				/* args012.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args012.rbuff % bufalign) + bufoffset) % bufalign); */
			    }
			    else
			    {
				args012.sbuff = memtmp;
				/* args012.rbuff = memtmp1; */
			    }
			}

			Sync012(&args012);
			t0 = MPI_Wtime();
			for (j = 0; j < nrepeat012; j++)
			{
			    MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD);
			    MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD, &status);
			    if (bNoCache)
			    {
				args012.sbuff += args012.bufflen;
				/* args012.rbuff += args012.bufflen; */
			    }
			}
			t = (MPI_Wtime() - t0)/(2 * nrepeat012);

			t1 += t;
			bwdata012[n].t = MIN(bwdata012[n].t, t);
		    }
		    MPI_Bcast(&bwdata012[n].t, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
		    break;
		case MIDDLE_PROCESS:
		    bwdata012[n].t = LONGTIME;
		    t1 = 0;
		    for (i = 0; i < TRIALS; i++)
		    {
			if (bNoCache)
			{
			    if (bufalign != 0)
			    {
				args012.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign);
				/* args012.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args012.rbuff % bufalign) + bufoffset) % bufalign); */
			    }
			    else
			    {
				args012.sbuff = memtmp;
				/* args012.rbuff = memtmp1; */
			    }
			}

			Sync012(&args012);
			t0 = MPI_Wtime();

			/******* use the ii variable here !!! ******/

			for (j = 0; j <= nrepeat012-ii; j+=ii)
			{
			    for (k=0; k<ii; k++)
			    {
				MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor2, MSG_TAG_012, MPI_COMM_WORLD);
				MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor2, MSG_TAG_012, MPI_COMM_WORLD, &status);
			    }
			    /* do the left process second because it does the timing and needs to include time to send to the right process. */
			    for (k=0; k<ii; k++)
			    {
				MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD, &status);
				MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD);
			    }
			    if (bNoCache)
			    {
				args012.sbuff += args012.bufflen;
				/* args012.rbuff += args012.bufflen; */
			    }
			}
			j = nrepeat012 % ii;
			for (k=0; k < j; k++)
			{
			    MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor2, MSG_TAG_012, MPI_COMM_WORLD);
			    MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor2, MSG_TAG_012, MPI_COMM_WORLD, &status);
			}
			/* do the left process second because it does the timing and needs to include time to send to the right process. */
			for (k=0; k < j; k++)
			{
			    MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD, &status);
			    MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD);
			}
			t = (MPI_Wtime() - t0)/(2 * nrepeat012);
		    }
		    MPI_Bcast(&bwdata012[n].t, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
		    break;
		case RIGHT_PROCESS:
		    bwdata012[n].t = LONGTIME;
		    t1 = 0;
		    for (i = 0; i < TRIALS; i++)
		    {
			if (bNoCache)
			{
			    if (bufalign != 0)
			    {
				args012.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign);
				/* args012.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args012.rbuff % bufalign) + bufoffset) % bufalign); */
			    }
			    else
			    {
				args012.sbuff = memtmp;
				/* args012.rbuff = memtmp1; */
			    }
			}

			Sync012(&args012);
			t0 = MPI_Wtime();
			for (j = 0; j < nrepeat012; j++)
			{
			    MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD, &status);
			    MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD);
			    if (bNoCache)
			    {
				args012.sbuff += args012.bufflen;
				/* args012.rbuff += args012.bufflen; */
			    }
			}
			t = (MPI_Wtime() - t0)/(2 * nrepeat012);
		    }
		    MPI_Bcast(&bwdata012[n].t, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
		    break;
		}
		tlast012 = bwdata012[n].t;
		bwdata012[n].bits = args012.bufflen * CHARSIZE;
		bwdata012[n].bps = bwdata012[n].bits / (bwdata012[n].t * 1024 * 1024);
		bwdata012[n].repeat = nrepeat012;
		if (itrial < ntrials)
		{
		    dtrials[itrial] = MIN(dtrials[itrial], bwdata012[n].t);
		}

		if (g_nIproc == 0)
		{
		    if (bSavePert)
		    {
			fprintf(out, "\t%0.9f", bwdata012[n].t);
			fflush(out);
		    }
		    if (printopt)
		    {
			printf(" %0.9f", tlast012);
			fflush(stdout);
		    }
		}
	    }
	    if (g_nIproc == 0)
	    {
		if (bSavePert)
		{
		    fprintf(out, "\n");
		    fflush(out);
		}
		if (printopt)
		{
		    printf("\n");
		    fflush(stdout);
		}
	    }
	    
	    free(memtmp);
	    free(memtmp1);
#endif

#ifdef CREATE_SINGLE_CURVE
	    /*****************************************************/
	    /*         Run a trial between rank 0, 1 and 2       */
	    /*****************************************************/

	    MPI_Barrier(MPI_COMM_WORLD);


	    /* Calculate howmany times to repeat the experiment. */
	    if (g_nIproc == 0)
	    {
		if (args012.bufflen == 0)
		    nrepeat012 = g_latency012_reps;
		else
		    nrepeat012 = (int)(MAX((RUNTM / ((double)args012.bufflen /
			           (args012.bufflen - inc + 1.0) * tlast012)), TRIALS));
		MPI_Bcast(&nrepeat012, 1, MPI_INT, 0, MPI_COMM_WORLD);
	    }
	    else
	    {
		MPI_Bcast(&nrepeat012, 1, MPI_INT, 0, MPI_COMM_WORLD);
	    }

	    /* Allocate the buffer */
	    args012.bufflen = len + pert;
	    /* printf("allocating %d bytes\n", args12.bufflen * nrepeat012 + bufalign); */
	    if (bNoCache)
	    {
		if ((args012.sbuff = (char *)malloc(args012.bufflen * nrepeat012 + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    else
	    {
		if ((args012.sbuff = (char *)malloc(args012.bufflen + bufalign)) == (char *)NULL)
		{
		    fprintf(stdout,"Couldn't allocate memory\n");
		    fflush(stdout);
		    break;
		}
	    }
	    /* if ((args012.rbuff = (char *)malloc(args012.bufflen * nrepeat012 + bufalign)) == (char *)NULL) */
	    if ((args012.rbuff = (char *)malloc(args012.bufflen + bufalign)) == (char *)NULL)
	    {
		fprintf(stdout,"Couldn't allocate memory\n");
		fflush(stdout);
		break;
	    }

	    /* save the original pointers in case alignment moves them */
	    memtmp = args012.sbuff;
	    memtmp1 = args012.rbuff;
	    
	    /* Possibly align the data buffer */
	    if (!bNoCache)
	    {
		if (bufalign != 0)
		{
		    args012.sbuff += (bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign;
		    /* args12.rbuff += (bufalign - ((MPI_Aint)args12.rbuff % bufalign) + bufoffset) % bufalign; */
		}
	    }
	    args012.rbuff += (bufalign - (POINTER_TO_INT(args012.rbuff) % bufalign) + bufoffset) % bufalign;
	    
	    if (g_nIproc == 0 && printopt)
	    {
		printf("%3d: %9d bytes %4d times --> ", n, args012.bufflen, nrepeat012);
		fflush(stdout);
	    }
	    
	    /* Finally, we get to transmit or receive and time */
	    switch (g_proc_loc)
	    {
	    case LEFT_PROCESS:
		bwdata012[n].t = LONGTIME;
		t1 = 0;
		for (i = 0; i < TRIALS; i++)
		{
		    if (bNoCache)
		    {
			if (bufalign != 0)
			{
			    args012.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign);
			    /* args012.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args012.rbuff % bufalign) + bufoffset) % bufalign); */
			}
			else
			{
			    args012.sbuff = memtmp;
			    /* args012.rbuff = memtmp1; */
			}
		    }
		    
		    Sync012(&args012);
		    t0 = MPI_Wtime();
		    for (j = 0; j < nrepeat012; j++)
		    {
			MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD);
			MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD, &status);
			if (bNoCache)
			{
			    args012.sbuff += args012.bufflen;
			    /* args012.rbuff += args012.bufflen; */
			}
		    }
		    t = (MPI_Wtime() - t0)/(2 * nrepeat012);

		    t1 += t;
		    bwdata012[n].t = MIN(bwdata012[n].t, t);
		}
		MPI_Bcast(&bwdata012[n].t, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
		break;
	    case MIDDLE_PROCESS:
		bwdata012[n].t = LONGTIME;
		t1 = 0;
		for (i = 0; i < TRIALS; i++)
		{
		    if (bNoCache)
		    {
			if (bufalign != 0)
			{
			    args012.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign);
			    /* args012.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args012.rbuff % bufalign) + bufoffset) % bufalign); */
			}
			else
			{
			    args012.sbuff = memtmp;
			    /* args012.rbuff = memtmp1; */
			}
		    }
		    
		    Sync012(&args012);
		    t0 = MPI_Wtime();
		    for (j = 0; j < nrepeat012; j++)
		    {
			MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD, &status);
			MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor2, MSG_TAG_012, MPI_COMM_WORLD);
			MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor2, MSG_TAG_012, MPI_COMM_WORLD, &status);
			MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD);
			if (bNoCache)
			{
			    args012.sbuff += args012.bufflen;
			    /* args012.rbuff += args012.bufflen; */
			}
		    }
		    t = (MPI_Wtime() - t0)/(2 * nrepeat012);
		}
		MPI_Bcast(&bwdata012[n].t, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
		break;
	    case RIGHT_PROCESS:
		bwdata012[n].t = LONGTIME;
		t1 = 0;
		for (i = 0; i < TRIALS; i++)
		{
		    if (bNoCache)
		    {
			if (bufalign != 0)
			{
			    args012.sbuff = memtmp + ((bufalign - (POINTER_TO_INT(args012.sbuff) % bufalign) + bufoffset) % bufalign);
			    /* args012.rbuff = memtmp1 + ((bufalign - ((MPI_Aint)args012.rbuff % bufalign) + bufoffset) % bufalign); */
			}
			else
			{
			    args012.sbuff = memtmp;
			    /* args012.rbuff = memtmp1; */
			}
		    }
		    
		    Sync012(&args012);
		    t0 = MPI_Wtime();
		    for (j = 0; j < nrepeat012; j++)
		    {
			MPI_Recv(args012.rbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD, &status);
			MPI_Send(args012.sbuff, args012.bufflen, MPI_BYTE, args012.nbor, MSG_TAG_012, MPI_COMM_WORLD);
			if (bNoCache)
			{
			    args012.sbuff += args012.bufflen;
			    /* args012.rbuff += args012.bufflen; */
			}
		    }
		    t = (MPI_Wtime() - t0)/(2 * nrepeat012);
		}
		MPI_Bcast(&bwdata012[n].t, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
		break;
	    }
	    tlast012 = bwdata012[n].t;
	    bwdata012[n].bits = args012.bufflen * CHARSIZE;
	    bwdata012[n].bps = bwdata012[n].bits / (bwdata012[n].t * 1024 * 1024);
	    bwdata012[n].repeat = nrepeat012;

	    if (g_nIproc == 0)
	    {
		if (bSavePert)
		{
		    if (bUseMegaBytes)
			fprintf(out, "%f\t%0.9f\n", bwdata012[n].bps / 8, bwdata012[n].t);
		    else
			fprintf(out, "%f\t%0.9f\n", bwdata012[n].bps, bwdata012[n].t);
		    fflush(out);
		}
	    }
	    
	    free(memtmp);
	    free(memtmp1);
	    
	    if (g_nIproc == 0 && printopt)
	    {
		if (bUseMegaBytes)
		    printf(" %6.2f MBps in %0.9f sec\n", bwdata012[n].bps / 8, tlast012);
		else
		    printf(" %6.2f Mbps in %0.9f sec\n", bwdata012[n].bps, tlast012);
		fflush(stdout);
	    }
#endif

	} /* End of perturbation loop */

	if (!bSavePert)/* && g_nIproc == 0)*/
	{
	    /* if we didn't save all of the perturbation loops, find the max and save it */
	    int index01 = 1, index12 = 1;
	    double dmax01 = bwdata01[n-1].bps;
	    double dmax12 = bwdata12[n-1].bps;
#ifdef CREATE_SINGLE_CURVE
	    int index012 = 1;
	    double dmax012 = bwdata012[n-1].bps;
#endif
	    for (; ipert > 1; ipert--)
	    {
		if (bwdata01[n-ipert].bps > dmax01)
		{
		    index01 = ipert;
		    dmax01 = bwdata01[n-ipert].bps;
		}
		if (bwdata12[n-ipert].bps > dmax12)
		{
		    index12 = ipert;
		    dmax12 = bwdata12[n-ipert].bps;
		}
#ifdef CREATE_SINGLE_CURVE
		if (bwdata012[n-ipert].bps > dmax012)
		{
		    index012 = ipert;
		    dmax012 = bwdata012[n-ipert].bps;
		}
#endif
	    }
	    /* get the left stuff out */
	    MPI_Bcast(&index01, 1, MPI_INT, g_left_rank, MPI_COMM_WORLD);
	    MPI_Bcast(&bwdata01[n-index01].bits, 1, MPI_INT, g_left_rank, MPI_COMM_WORLD);
	    MPI_Bcast(&bwdata01[n-index01].bps, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
	    MPI_Bcast(&bwdata01[n-index01].t, 1, MPI_DOUBLE, g_left_rank, MPI_COMM_WORLD);
	    /* get the right stuff out */
	    MPI_Bcast(&index12, 1, MPI_INT, g_middle_rank, MPI_COMM_WORLD);
	    MPI_Bcast(&bwdata12[n-index12].bps, 1, MPI_DOUBLE, g_middle_rank, MPI_COMM_WORLD);
	    MPI_Bcast(&bwdata12[n-index12].t, 1, MPI_DOUBLE, g_middle_rank, MPI_COMM_WORLD);
	    if (g_nIproc == 0)
	    {
		if (bUseMegaBytes)
		{
		    fprintf(out, "%d\t%f\t%0.9f\t", bwdata01[n-index01].bits / 8, bwdata01[n-index01].bps / 8, bwdata01[n-index01].t);
		    fprintf(out, "%f\t%0.9f\t", bwdata12[n-index12].bps / 8, bwdata12[n-index12].t);
#ifdef CREATE_SINGLE_CURVE
		    fprintf(out, "%f\t%0.9f\n", bwdata012[n-index012].bps / 8, bwdata012[n-index012].t);
#endif
		}
		else
		{
		    fprintf(out, "%d\t%f\t%0.9f\t", bwdata01[n-index01].bits / 8, bwdata01[n-index01].bps, bwdata01[n-index01].t);
		    fprintf(out, "%f\t%0.9f\t", bwdata12[n-index12].bps, bwdata12[n-index12].t);
#ifdef CREATE_SINGLE_CURVE
		    fprintf(out, "%f\t%0.9f\n", bwdata012[n-index012].bps, bwdata012[n-index012].t);
#endif
		}
#ifdef CREATE_DIFFERENCE_CURVES
		for (itrial = 0; itrial < ntrials && dtrials[itrial] != LONGTIME; itrial++)
		{
		    fprintf(out, "%0.9f\t", dtrials[itrial]);
		}
		fprintf(out, "\n");
#endif
		fflush(out);
	    }
	}
    } /* End of main loop  */
	
    if (g_nIproc == 0)
	fclose(out);
    /* THE_END:		 */
    MPI_Finalize();
    free(bwdata01);
    free(bwdata12);
    free(bwdata012);
    return 0;
}