<commit_before>/*
 * Copyright (c) 2014 ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
 */

#include <string.h>
#include <barrelfish/barrelfish.h>
#include <barrelfish/nameservice_client.h>

#include <xeon_phi/xeon_phi.h>

#include <xeon_phi/xeon_phi_messaging.h>
#include <xeon_phi/xeon_phi_messaging_client.h>

#include <if/xeon_phi_messaging_defs.h>

#define DEBUG_XPMC(x...) debug_printf(" XPMC | " x)

enum xpm_state
{
    XPM_STATE_NSLOOKUP,
    XPM_STATE_BINDING,
    XPM_STATE_BIND_OK,
    XPM_STATE_BIND_FAIL,
};

/* todo: extend this with array of 8 */
static iref_t xpm_iref[XEON_PHI_NUM_MAX];
struct xeon_phi_messaging_binding *xpm_binding[XEON_PHI_NUM_MAX];

static enum xpm_state conn_state = XPM_STATE_NSLOOKUP;


/*
 * --------------------------------------------------------------------------
 * Handling of OPEN commands
 */

struct xpm_msg_param_open
{
    struct capref frame;
    struct xeon_phi_messaging_binding *b;
    uint8_t type;
    uint8_t xphi_id;
    char iface[44];
};
#ifndef __k1om__
static void xpm_msg_open_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_open *param = a;

    struct event_closure txcont = MKCONT(free, a);

    size_t length = strlen(param->iface)+1;

    err = xeon_phi_messaging_open_iface__tx(param->b,
                                      txcont,
                                      param->frame,
                                      param->type,
                                      param->iface,
                                      length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_open_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#else
static void xpm_msg_open_card_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_open *param = a;

    struct event_closure txcont = MKCONT(free, a);

    size_t length = strlen(param->iface)+1;

    err = xeon_phi_messaging_open_card__tx(param->b,
                                      txcont,
                                      param->xphi_id,
                                      param->frame,
                                      param->type,
                                      param->iface,
                                      length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_open_card_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#endif

/*
 * --------------------------------------------------------------------------
 * Handling of SPAWN commands
 */
struct xpm_msg_param_spawn
{
    struct xeon_phi_messaging_binding *b;
    coreid_t core;
    uint8_t xphi_id;
    char name[55];
};
#ifndef __k1om__
static void xpm_msg_spawn_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_spawn *param = a;

    struct event_closure txcont = MKCONT(free, a);

    size_t length = strlen(param->name)+1;

    err = xeon_phi_messaging_spawn__tx(param->b,
                                       txcont,
                                       param->core,
                                       param->name,
                                       length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_spawn_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#else
static void xpm_msg_spawn_card_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_spawn *param = a;

    struct event_closure txcont = MKCONT(free, a);

    size_t length = strlen(param->name)+1;

    err = xeon_phi_messaging_spawn_card__tx(param->b,
                                       txcont,
                                       param->xphi_id,
                                       param->core,
                                       param->name,
                                       length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_spawn_card_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#endif

static struct xeon_phi_messaging_rx_vtbl xpm_rx_vtbl = {
    .open = NULL
};

/*
 * --------------------------------------------------------------------------
 * Xeon Phi Manager Binding
 */

/**
 * \brief
 *
 * \param
 * \param
 * \param
 */
static void xpm_bind_cb(void *st,
                        errval_t err,
                        struct xeon_phi_messaging_binding *b)
{

    if (err_is_fail(err)) {
        conn_state = XPM_STATE_BIND_FAIL;
        return;
    }

    uint8_t xeon_phi_id = (uint8_t)(uintptr_t)st;

    assert(xpm_binding[xeon_phi_id] == 0);

    b->rx_vtbl = xpm_rx_vtbl;
    b->st = (void *)(uintptr_t)xeon_phi_id;

    xpm_binding[xeon_phi_id] = b;

    DEBUG_XPMC("Binding ok.\n");

    conn_state = XPM_STATE_BIND_OK;
}

/**
 * \brief
 */
static errval_t xpm_connect(uint8_t xeon_phi_id)
{
    errval_t err;

    if (xpm_binding[xeon_phi_id] != NULL) {
        return SYS_ERR_OK;
    }

    char buf[50];
#if !defined(__k1om__)
    snprintf(buf, 50, "%s.%u", XEON_PHI_MESSAGING_NAME, xeon_phi_id);
#else
    snprintf(buf, 50, "%s", XEON_PHI_MESSAGING_NAME);
#endif

    DEBUG_XPMC("Nameservice lookup: %s\n", buf);
    err = nameservice_blocking_lookup(buf, &xpm_iref[xeon_phi_id]);
    if (err_is_fail(err)) {
        return err;
    }

    conn_state = XPM_STATE_BINDING;

    DEBUG_XPMC("binding to iref [%u]... \n", xpm_iref[xeon_phi_id]);
    err = xeon_phi_messaging_bind(xpm_iref[xeon_phi_id], xpm_bind_cb,
                                  (void *)(uintptr_t)xeon_phi_id,
                                  get_default_waitset(),
                                  IDC_BIND_FLAGS_DEFAULT);
    if (err_is_fail(err)) {
        return err;
    }

    while (conn_state == XPM_STATE_BINDING) {
        messages_wait_and_handle_next();
    }

    DEBUG_XPMC("binding to iref [%u] done. \n", xpm_iref[xeon_phi_id]);

    if (conn_state == XPM_STATE_BIND_FAIL) {
        return FLOUNDER_ERR_BIND;
    }

    return SYS_ERR_OK;
}



/*
 * --------------------------------------------------------------------------
 * Public Interface
 */

/**
 * \brief sends a OPEN command message over the Xeon Phi channel
 *
 * \param iface the name of the iface to talk to
 * \param frame capability representing the allocated frame
 * \param type  type of the channel
 *
 * \return SYS_ERR_OK on success
 */
errval_t xeon_phi_messaging_open(uint8_t xeon_phi_id,
                                 char *iface,
                                 struct capref frame,
                                 uint8_t type)
{
    errval_t err;

#ifdef __k1om__
    uint8_t xphi = 0;
#else
    uint8_t xphi = xeon_phi_id;
#endif
    if (xpm_binding[xphi] == NULL) {
        err = xpm_connect(xphi);
        if (err_is_fail(err)) {
            return err;
        }
    }

    struct xpm_msg_param_open *param = malloc(sizeof(struct xpm_msg_param_open));
    if (param == NULL) {
        return LIB_ERR_MALLOC_FAIL;
    }

    param->frame = frame;
    param->type = type;
    param->b = xpm_binding[xphi];
    param->xphi_id = xeon_phi_id;

    snprintf(param->iface, sizeof(param->iface), "%s", iface);

#ifdef __k1om__
    xpm_msg_open_card_tx(param);
#else
    xpm_msg_open_tx(param);
#endif
    return SYS_ERR_OK;
}

/**
 * \brief sends a SPAWN command message over the Xeon Phi channel
 *        to spawn a new domain on the other side
 *
 * \param core  core ID of the core to spawn the program on
 * \param name  path to the program to spawn
 *
 * \returns SYS_ERR_OK on success
 */
errval_t xeon_phi_messaging_spawn(uint8_t xeon_phi_id,
                                  coreid_t core,
                                  char *name)
{
    errval_t err;

    DEBUG_XPMC("Send spawn request %s on core %u.%u\n", name, xeon_phi_id, core);

#ifdef __k1om__<commit_msg>Added: Waiting for sent in xeon phi messaging client.<commit_after>/*
 * Copyright (c) 2014 ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
 */

#include <string.h>
#include <barrelfish/barrelfish.h>
#include <barrelfish/nameservice_client.h>

#include <xeon_phi/xeon_phi.h>

#include <xeon_phi/xeon_phi_messaging.h>
#include <xeon_phi/xeon_phi_messaging_client.h>

#include <if/xeon_phi_messaging_defs.h>

#define DEBUG_XPMC(x...) debug_printf(" XPMC | " x)

enum xpm_state
{
    XPM_STATE_NSLOOKUP,
    XPM_STATE_BINDING,
    XPM_STATE_BIND_OK,
    XPM_STATE_BIND_FAIL,
};

/* todo: extend this with array of 8 */
static iref_t xpm_iref[XEON_PHI_NUM_MAX];
struct xeon_phi_messaging_binding *xpm_binding[XEON_PHI_NUM_MAX];

static enum xpm_state conn_state = XPM_STATE_NSLOOKUP;


/*
 * --------------------------------------------------------------------------
 * Handling of OPEN commands
 */

static volatile uint8_t xpm_msg_open_sent = 0x1;

struct xpm_msg_param_open
{
    struct capref frame;
    struct xeon_phi_messaging_binding *b;
    uint8_t type;
    uint8_t xphi_id;
    char iface[44];
};

static void xpm_msg_open_sent_cb(void *a)
{
    free(a);
    xpm_msg_open_sent = 0x1;
}

#ifndef __k1om__
static void xpm_msg_open_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_open *param = a;

    struct event_closure txcont = MKCONT(xpm_msg_open_sent_cb, a);

    size_t length = strlen(param->iface)+1;

    err = xeon_phi_messaging_open_iface__tx(param->b,
                                      txcont,
                                      param->frame,
                                      param->type,
                                      param->iface,
                                      length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_open_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#else
static void xpm_msg_open_card_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_open *param = a;

    struct event_closure txcont = MKCONT(xpm_msg_open_sent_cb, a);

    size_t length = strlen(param->iface)+1;

    err = xeon_phi_messaging_open_card__tx(param->b,
                                          txcont,
                                          param->xphi_id,
                                          param->frame,
                                          param->type,
                                          param->iface,
                                          length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_open_card_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#endif

/*
 * --------------------------------------------------------------------------
 * Handling of SPAWN commands
 */
struct xpm_msg_param_spawn
{
    struct xeon_phi_messaging_binding *b;
    coreid_t core;
    uint8_t xphi_id;
    char name[55];
};
#ifndef __k1om__
static void xpm_msg_spawn_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_spawn *param = a;

    struct event_closure txcont = MKCONT(free, a);

    size_t length = strlen(param->name)+1;

    err = xeon_phi_messaging_spawn__tx(param->b,
                                       txcont,
                                       param->core,
                                       param->name,
                                       length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_spawn_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#else
static void xpm_msg_spawn_card_tx(void *a)
{
    errval_t err;

    struct xpm_msg_param_spawn *param = a;

    struct event_closure txcont = MKCONT(free, a);

    size_t length = strlen(param->name)+1;

    err = xeon_phi_messaging_spawn_card__tx(param->b,
                                       txcont,
                                       param->xphi_id,
                                       param->core,
                                       param->name,
                                       length);
    if (err_is_fail(err)) {
        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
            txcont = MKCONT(xpm_msg_spawn_card_tx, a);
            err = param->b->register_send(param->b,
                                             get_default_waitset(),
                                             txcont);
            if (err_is_fail(err)) {
                USER_PANIC_ERR(err, "failed to register send\n");
            }
        }
    }
}
#endif

static struct xeon_phi_messaging_rx_vtbl xpm_rx_vtbl = {
    .open = NULL
};

/*
 * --------------------------------------------------------------------------
 * Xeon Phi Manager Binding
 */

/**
 * \brief
 *
 * \param
 * \param
 * \param
 */
static void xpm_bind_cb(void *st,
                        errval_t err,
                        struct xeon_phi_messaging_binding *b)
{

    if (err_is_fail(err)) {
        conn_state = XPM_STATE_BIND_FAIL;
        return;
    }

    uint8_t xeon_phi_id = (uint8_t)(uintptr_t)st;

    assert(xpm_binding[xeon_phi_id] == 0);

    b->rx_vtbl = xpm_rx_vtbl;
    b->st = (void *)(uintptr_t)xeon_phi_id;

    xpm_binding[xeon_phi_id] = b;

    DEBUG_XPMC("Binding ok.\n");

    conn_state = XPM_STATE_BIND_OK;
}

/**
 * \brief
 */
static errval_t xpm_connect(uint8_t xeon_phi_id)
{
    errval_t err;

    if (xpm_binding[xeon_phi_id] != NULL) {
        return SYS_ERR_OK;
    }

    char buf[50];
#if !defined(__k1om__)
    snprintf(buf, 50, "%s.%u", XEON_PHI_MESSAGING_NAME, xeon_phi_id);
#else
    snprintf(buf, 50, "%s", XEON_PHI_MESSAGING_NAME);
#endif

    DEBUG_XPMC("Nameservice lookup: %s\n", buf);
    err = nameservice_blocking_lookup(buf, &xpm_iref[xeon_phi_id]);
    if (err_is_fail(err)) {
        return err;
    }

    conn_state = XPM_STATE_BINDING;

    DEBUG_XPMC("binding to iref [%u]... \n", xpm_iref[xeon_phi_id]);
    err = xeon_phi_messaging_bind(xpm_iref[xeon_phi_id], xpm_bind_cb,
                                  (void *)(uintptr_t)xeon_phi_id,
                                  get_default_waitset(),
                                  IDC_BIND_FLAGS_DEFAULT);
    if (err_is_fail(err)) {
        return err;
    }

    while (conn_state == XPM_STATE_BINDING) {
        messages_wait_and_handle_next();
    }

    DEBUG_XPMC("binding to iref [%u] done. \n", xpm_iref[xeon_phi_id]);

    if (conn_state == XPM_STATE_BIND_FAIL) {
        return FLOUNDER_ERR_BIND;
    }

    return SYS_ERR_OK;
}



/*
 * --------------------------------------------------------------------------
 * Public Interface
 */

/**
 * \brief sends a OPEN command message over the Xeon Phi channel
 *
 * \param iface the name of the iface to talk to
 * \param frame capability representing the allocated frame
 * \param type  type of the channel
 *
 * \return SYS_ERR_OK on success
 */
errval_t xeon_phi_messaging_open(uint8_t xeon_phi_id,
                                 char *iface,
                                 struct capref frame,
                                 uint8_t type)
{
    errval_t err;

#ifdef __k1om__
    uint8_t xphi = 0;
#else
    uint8_t xphi = xeon_phi_id;
#endif
    if (xpm_binding[xphi] == NULL) {
        err = xpm_connect(xphi);
        if (err_is_fail(err)) {
            return err;
        }
    }

    xpm_msg_open_sent = 0x0;

    struct xpm_msg_param_open *param = malloc(sizeof(struct xpm_msg_param_open));
    if (param == NULL) {
        return LIB_ERR_MALLOC_FAIL;
    }

    param->frame = frame;
    param->type = type;
    param->b = xpm_binding[xphi];
    param->xphi_id = xeon_phi_id;

    snprintf(param->iface, sizeof(param->iface), "%s", iface);

#ifdef __k1om__
    xpm_msg_open_card_tx(param);
#else
    xpm_msg_open_tx(param);
#endif

    while(!xpm_msg_open_sent) {
        messages_wait_and_handle_next();
    }

    return SYS_ERR_OK;
}

/**
 * \brief sends a SPAWN command message over the Xeon Phi channel
 *        to spawn a new domain on the other side
 *
 * \param core  core ID of the core to spawn the program on
 * \param name  path to the program to spawn
 *
 * \returns SYS_ERR_OK on success
 */
errval_t xeon_phi_messaging_spawn(uint8_t xeon_phi_id,
                                  coreid_t core,
                                  char *name)
{
    errval_t err;

    DEBUG_XPMC("Send spawn request %s on core %u.%u\n", name, xeon_phi_id, core);

#ifdef __k1om__
{'fraction_non_alphanumeric': 0.12502027794300546, 'fraction_numerical': 0.005028929865354459, 'mean_word_length': 1.5963779306471992, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 94, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7307342', 'n_tokens_mistral': 6319, 'n_tokens_neox': 6020, 'n_words': 1203}