Added: Xeon Phi Manager
[barrelfish] / usr / xeon_phi_manager / service.c
1 /*
2  * Copyright (c) 2014 ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8  */
9 #include <stdio.h>
10 #include <barrelfish/barrelfish.h>
11 #include <barrelfish/nameservice_client.h>
12 #include <xeon_phi/xeon_phi_manager_client.h>
13
14 #include <if/xeon_phi_manager_defs.h>
15
16 #include "service.h"
17 #include "cardmanager.h"
18
19 enum xpm_svc_state
20 {
21     XPM_SVC_STATE_EXPORTING,
22     XPM_SVC_STATE_EXPORT_OK,
23     XPM_SVC_STATE_EXPORT_FAIL,
24     XPM_SVC_STATE_NS_REGISTERING,
25     XPM_SVC_STATE_NS_REGISTER_OK,
26     XPM_SVC_STATE_NS_REGISTER_FAIL,
27     XPM_SVC_STATE_RUNNING
28 };
29
30 static enum xpm_svc_state svc_state = XPM_SVC_STATE_EXPORTING;
31
32 static iref_t manager_iref;
33
34 /**
35  * --------------------------------------------------------------------------
36  * Registration protocol
37  */
38
39 struct reg_data
40 {
41     errval_t err;
42     uint8_t id;
43     iref_t *cards;
44     uint8_t num;
45     struct xeon_phi_manager_binding *b;
46 };
47
48 struct reg_data reg_data_fail = {
49     // TODO: ERROR CODE
50     .err = -1
51 };
52
53 static void register_response_sent_cb(void *a)
54 {
55     if (a != &reg_data_fail) {
56         free(a);
57     }
58 }
59
60 static void register_response_send(void *a)
61 {
62     errval_t err;
63
64     struct reg_data *rd = a;
65
66     DEBUG_SVC("Registration response: id=%x, num=%x\n", rd->id, rd->num);
67
68     struct event_closure txcont = MKCONT(register_response_sent_cb, a);
69     size_t n = rd->num * sizeof(iref_t);
70     uint8_t *irefs = (uint8_t *) rd->cards;
71     err = xeon_phi_manager_register_response__tx(rd->b,
72                                                  txcont,
73                                                  rd->id,
74                                                  irefs,
75                                                  n,
76                                                  rd->err);
77     if (err_is_fail(err)) {
78         if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
79             txcont = MKCONT(register_response_send, a);
80         }
81         struct waitset *ws = get_default_waitset();
82         err = rd->b->register_send(rd->b, ws, txcont);
83         if (err_is_fail(err)) {
84             DEBUG_ERR(err, "register_send on binding failed!");
85             register_response_sent_cb(a);
86         }
87     }
88 }
89
90 static void register_call_recv(struct xeon_phi_manager_binding *_binding,
91                                iref_t svc)
92 {
93     DEBUG_SVC("New registration: iref=%x\n", svc);
94
95     struct reg_data *reply = malloc(sizeof(struct reg_data));
96     if (!reply) {
97         register_response_send(&reg_data_fail);
98     }
99     reply->b = _binding;
100     reply->err = cm_new_xeon_phi(_binding, svc, &reply->id);
101     if (err_is_fail(reply->err)) {
102         register_response_send(reply);
103     }
104
105     reply->err = cm_get_irefs(&reply->cards, &reply->num);
106     if (err_is_fail(reply->err)) {
107         register_response_send(reply);
108     }
109
110     register_response_send(reply);
111 }
112
113 static struct xeon_phi_manager_rx_vtbl xpm_rx_vtbl = {
114     .register_call = register_call_recv
115 };
116
117 /*
118  * --------------------------------------------------------------------------
119  * Export and Connect functions
120  */
121
122 static errval_t svc_connect_cb(void *st,
123                                struct xeon_phi_manager_binding *b)
124 {
125     DEBUG_SVC("connect request\n");
126     b->rx_vtbl = xpm_rx_vtbl;
127
128     return SYS_ERR_OK;
129 }
130
131 /**
132  * \brief
133  */
134 static void svc_export_cb(void *st,
135                           errval_t err,
136                           iref_t iref)
137 {
138     DEBUG_SVC("exported\n");
139     if (err_is_fail(err)) {
140         svc_state = XPM_SVC_STATE_EXPORT_FAIL;
141         return;
142     }
143
144     manager_iref = iref;
145
146     svc_state = XPM_SVC_STATE_NS_REGISTERING;
147
148     err = nameservice_register(XEON_PHI_MANAGER_SERVICE_NAME, iref);
149     if (err_is_fail(err)) {
150         svc_state = XPM_SVC_STATE_NS_REGISTER_FAIL;
151     }
152     DEBUG_SVC("ns registered\n");
153     svc_state = XPM_SVC_STATE_NS_REGISTER_OK;
154 }
155
156 /**
157  * \brief   starts Xeon Phi manager service
158  *
159  * \return  SYS_ERR_OK on succes
160  */
161 errval_t service_start(void)
162 {
163     DEBUG_SVC("starting service...\n");
164     errval_t err;
165
166     struct waitset *ws = get_default_waitset();
167
168     err = xeon_phi_manager_export(NULL,
169                                   svc_export_cb,
170                                   svc_connect_cb,
171                                   ws,
172                                   IDC_EXPORT_FLAGS_DEFAULT);
173     if (err_is_fail(err)) {
174         return err;
175     }
176
177     while (svc_state == XPM_SVC_STATE_EXPORTING) {
178         messages_wait_and_handle_next();
179     }
180
181     if (svc_state == XPM_SVC_STATE_EXPORT_FAIL) {
182         return FLOUNDER_ERR_BIND;
183     } else if (svc_state == XPM_SVC_STATE_NS_REGISTER_FAIL) {
184         return LIB_ERR_NAMESERVICE_CLIENT_INIT;
185     }
186
187     DEBUG_SVC("Service up and running.\n");
188
189     svc_state = XPM_SVC_STATE_RUNNING;
190     messages_handler_loop();
191
192     DEBUG_SVC("Message handler terminated.\n");
193     return -1;
194 }