1/**
2 * \file
3 * \brief Client for interacting with the name service
4 */
5
6/*
7 * Copyright (c) 2010, 2011, 2012, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
13 * Attn: Systems Group.
14 */
15#include <stdio.h>
16
17#include <barrelfish/barrelfish.h>
18
19#include <xeon_phi/xeon_phi.h>
20#include <xeon_phi/xeon_phi_domain.h>
21#include <xeon_phi/xeon_phi_client.h>
22
23#include <if/octopus_defs.h>
24#include <if/octopus_defs.h>
25//#include <if/monitor_defs.h>
26#include <octopus/getset.h> // for oct_read TODO
27#include <octopus/trigger.h> // for NOP_TRIGGER
28
29#include "xeon_phi_client_internal.h"
30
31/**
32 * \brief builds the iface name representation
33 *
34 * \param iface Name of the domain
35 * \param xid   Xeon Phi ID or XEON_PHI_DOMAIN_HOST the domain is runnig on
36 * \param core  The core the domain is running on
37 *
38 * \returns string with the proper format
39 */
40char *xeon_phi_domain_build_iface(const char *name,
41                                  xphi_id_t xid,
42                                  coreid_t core)
43{
44    char *iface;
45    size_t ifacelen;
46
47    if (core != XEON_PHI_DOMAIN_DONT_CARE) {
48        if (xid != XEON_PHI_DOMAIN_DONT_CARE) {
49            ifacelen = strlen(name) + 8;
50            iface = malloc(ifacelen);
51            if (iface == NULL) {
52                return NULL;
53            }
54            snprintf(iface, ifacelen, "%s.%02x.%02x", name, xid, core);
55        } else {
56            ifacelen = snprintf(NULL, 0, "r'^%s\\.[0-9][0-9]\\.%u'", name, core) + 1;
57            iface = malloc(ifacelen);
58            if (iface == NULL) {
59                return NULL;
60            }
61            snprintf(iface, ifacelen, "r'^%s\\.[0-9][0-9]\\.%u'", name, core);
62        }
63    } else {
64        if (xid != XEON_PHI_DOMAIN_DONT_CARE) {
65            ifacelen = snprintf(NULL, 0, "r'^%s\\.%02x\\.'", name, xid)+1;
66            iface = malloc(ifacelen);
67            if (iface == NULL) {
68                return NULL;
69            }
70            snprintf(iface, ifacelen, "r'^%s\\.%02x\\.'", name, xid);
71        } else {
72            ifacelen = snprintf(NULL, 0, "r'^%s\\.'", name)+1;
73            iface = malloc(ifacelen);
74            if (iface == NULL) {
75                return NULL;
76            }
77            snprintf(iface, ifacelen, "r'^%s\\.'", name);
78        }
79
80    }
81
82    return iface;
83}
84
85/**
86 * \brief Non-blocking name service lookup
87 *
88 * \param iface     Name of the domain
89 * \param retdomid  returns the Xeon Phi Domain ID
90 */
91errval_t xeon_phi_domain_lookup(const char *iface,
92                                xphi_dom_id_t *retdomid)
93{
94#ifdef __k1om__
95    return xeon_phi_client_domain_lookup(iface, retdomid);
96#else
97    errval_t err;
98
99    struct octopus_binding *r = get_octopus_binding();
100    if (r == NULL) {
101        return LIB_ERR_NAMESERVICE_NOT_BOUND;
102    }
103
104    struct octopus_get_response__rx_args reply;
105    err = r->rpc_tx_vtbl.get(r, iface, NOP_TRIGGER, reply.output, &reply.tid, &reply.error_code);
106    if (err_is_fail(err)) {
107        goto out;
108    }
109    err = reply.error_code;
110    if (err_is_fail(err)) {
111        if (err_no(err) == OCT_ERR_NO_RECORD) {
112            err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
113        }
114        goto out;
115    }
116
117    xphi_dom_id_t domid = 0;
118    err = oct_read(reply.output, "_ { domid: %d }", &domid);
119    if (err_is_fail(err) || domid == 0) {
120        err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
121        goto out;
122    }
123
124    if (retdomid != NULL) {
125        *retdomid = domid;
126    }
127
128    out:
129    return err;
130#endif
131}
132
133/**
134 * \brief Blocking name service lookup
135 *
136 * \param iface     Name of the domain
137 * \param retdomid  returns the Xeon Phi Domain ID
138 */
139errval_t xeon_phi_domain_blocking_lookup(const char *iface,
140                                         xphi_dom_id_t *retdomid)
141{
142#ifdef __k1om__
143    return xeon_phi_client_domain_wait(iface, retdomid);
144#else
145    errval_t err;
146
147    struct octopus_binding *r = get_octopus_binding();
148    if (r == NULL) {
149        return LIB_ERR_NAMESERVICE_NOT_BOUND;
150    }
151
152    struct octopus_wait_for_response__rx_args reply;
153    err = r->rpc_tx_vtbl.wait_for(r, iface, reply.record, &reply.error_code);
154    if (err_is_fail(err)) {
155        goto out;
156    }
157    err = reply.error_code;
158    if (err_is_fail(err)) {
159        if (err_no(err) == OCT_ERR_NO_RECORD) {
160            err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
161        }
162        goto out;
163    }
164
165    xphi_dom_id_t domid = 0;
166    err = oct_read(reply.record, "_ { domid: %d }", &domid);
167    if (err_is_fail(err)) {
168        err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
169        goto out;
170    }
171    if (retdomid != NULL) {
172        *retdomid = domid;
173    }
174
175    out:
176    return err;
177#endif
178}
179
180/**
181 * \brief Register with name service
182 *
183 * \param iface     Name of the domain
184 * \param retdomid  returns the Xeon Phi Domain ID
185 */
186errval_t xeon_phi_domain_register(const char *iface,
187                                  xphi_dom_id_t domid)
188{
189#ifdef __k1om__
190    return -1;
191#else
192    errval_t err = SYS_ERR_OK;
193
194    struct octopus_binding *r = get_octopus_binding();
195    if (r == NULL) {
196        return LIB_ERR_NAMESERVICE_NOT_BOUND;
197    }
198
199    // Format record
200    static const char* format = "%s { domid: %"PRIu64" }";
201    size_t len = snprintf(NULL, 0, format, iface, domid);
202    char* record = malloc(len+1);
203    if (record == NULL) {
204        return LIB_ERR_MALLOC_FAIL;
205    }
206    snprintf(record, len+1, format, iface, domid);
207
208    octopus_trigger_id_t tid;
209    errval_t error_code;
210    err = r->rpc_tx_vtbl.set(r, record, 0, NOP_TRIGGER, 0, NULL, &tid, &error_code);
211    if (err_is_fail(err)) {
212        goto out;
213    }
214    err = error_code;
215
216    out:
217    free(record);
218    return err;
219#endif
220}
221
222