00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <l4/sys/types.h>
00043 #include <l4/sys/ipc.h>
00044 #include <l4/env/errno.h>
00045 #include <l4/util/macros.h>
00046 #include <l4/thread/thread.h>
00047
00048
00049 #include <l4/dsi/dsi.h>
00050 #include "__sync.h"
00051 #include "__socket.h"
00052 #include "__thread.h"
00053 #include "__debug.h"
00054 #include "__config.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 static inline void
00069 __wakeup_and_map(dsi_socket_t * socket,dsi_packet_t * packet)
00070 {
00071 void *addr;
00072 l4_addr_t offs;
00073 l4_addr_t size;
00074 int ret,i;
00075 l4_msgdope_t result;
00076
00077 if (packet->sg_len > 1)
00078 Panic("DSI: map scatter gather list not yet supported!");
00079
00080 offs = socket->sg_lists[packet->sg_list].addr;
00081 addr = socket->data_area + offs;
00082 size = socket->sg_lists[packet->sg_list].size;
00083
00084
00085 i = 12;
00086 while (size > (1U << i))
00087 i++;
00088
00089 if (size != (1U << i))
00090 Panic("DSI: unaligned pages not supported yet!");
00091
00092 LOGdL(DEBUG_MAP_PACKET,"map packet %u, size %lu (%d)",packet->no,size,i);
00093 LOGdL(DEBUG_MAP_PACKET,"addr 0x%08lx, offset 0x%08lx",(unsigned long)addr,offs);
00094
00095
00096 ret = l4_ipc_send(socket->remote_socket.work_th,L4_IPC_SHORT_FPAGE,
00097 offs,l4_fpage((l4_addr_t)addr,i,
00098 L4_FPAGE_RW,L4_FPAGE_MAP).fpage,
00099 L4_IPC_SEND_TIMEOUT_0,&result);
00100 if (ret)
00101 LOG_Error("DSI: IPC error in wakeup 0x%02x",ret);
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static inline void
00113 __wakeup_and_copy(dsi_socket_t * socket,dsi_packet_t * packet)
00114 {
00115 l4_addr_t offs;
00116 l4_size_t size;
00117 int ret;
00118 struct {
00119 l4_umword_t rcv_fpage;
00120 l4_msgdope_t size_dope;
00121 l4_msgdope_t send_dope;
00122 l4_umword_t dw0;
00123 l4_umword_t dw1;
00124 l4_strdope_t buf;
00125 } msg_buf;
00126 l4_msgdope_t result;
00127
00128 if (packet->sg_len > 1)
00129 Panic("DSI: copy scatter gather list not yet supported!");
00130
00131 offs = socket->sg_lists[packet->sg_list].addr;
00132 size = socket->sg_lists[packet->sg_list].size;
00133
00134 LOGdL(DEBUG_COPY_PACKET,"copy packet");
00135 LOGdL(DEBUG_COPY_PACKET,"addr 0x%08lx, size %u",
00136 (unsigned)socket->data_area + offs,size);
00137
00138
00139 msg_buf.size_dope = L4_IPC_DOPE(2,1);
00140 msg_buf.send_dope = L4_IPC_DOPE(2,1);
00141 msg_buf.buf.snd_str = (l4_addr_t)socket->data_area + offs;
00142 msg_buf.buf.snd_size = size;
00143 ret = l4_ipc_send(socket->remote_socket.work_th,&msg_buf,
00144 0,0,L4_IPC_SEND_TIMEOUT_0,&result);
00145 if (ret)
00146 LOG_Error("DSI: IPC error in wakeup 0x%02x", ret);
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156 void
00157 dsi_sync_thread_send(void * data)
00158 {
00159 dsi_socket_t * socket;
00160 dsi_packet_t * packet;
00161 l4_threadid_t parent = l4thread_l4_id(l4thread_get_parent());
00162 int ret;
00163 l4_umword_t dw0,dw1;
00164 l4_msgdope_t result;
00165 l4_threadid_t src;
00166
00167 LOGdL(DEBUG_SYNC_SEND,"up, parent "l4util_idfmt, l4util_idstr(parent));
00168
00169
00170 Assert(data != NULL);
00171 socket = (dsi_socket_t *)data;
00172
00173
00174 ret = l4_ipc_receive(parent,L4_IPC_SHORT_MSG,&dw0,&dw1,
00175 L4_IPC_NEVER,&result);
00176 if (ret || (dw0 != DSI_SYNC_CONNECTED))
00177 {
00178 Panic("DSI: sync setup IPC failed (0x%02X)!",ret);
00179 return;
00180 }
00181 Assert(data == (void *)dw1);
00182
00183 LOGdL(DEBUG_SYNC_SEND,"connected.");
00184 LOGdL(DEBUG_SYNC_SEND,"remote socket %d, work "l4util_idfmt,
00185 socket->remote_socket.socket,
00186 l4util_idstr(socket->remote_socket.work_th));
00187
00188
00189 while (1)
00190 {
00191 ret = l4_ipc_wait(&src,L4_IPC_SHORT_MSG,&dw0,&dw1,
00192 L4_IPC_NEVER,&result);
00193
00194 if (!ret)
00195 {
00196 LOGdL(DEBUG_SYNC_SEND,"msg from "l4util_idfmt, l4util_idstr(src));
00197 LOGdL(DEBUG_SYNC_SEND,"dw0 = %lu, dw1 = %lu",dw0,dw1);
00198
00199 switch (dw0)
00200 {
00201 case DSI_SYNC_COMMITED:
00202 if (l4_task_equal(src,socket->work_th))
00203 {
00204
00205
00206
00207
00208
00209 LOGdL(DEBUG_SYNC_SEND,"wakeup receiver, packet %ld",dw1);
00210
00211 packet = &socket->packets[dw1];
00212
00213
00214 if (packet->flags & DSI_PACKET_RX_WAITING)
00215 {
00216 LOGdL(DEBUG_SYNC_SEND,"receiver already waiting");
00217 LOGdL(DEBUG_SYNC_SEND,"wakeup "l4util_idfmt,
00218 l4util_idstr(socket->remote_socket.work_th));
00219
00220 if (socket->flags & DSI_SOCKET_MAP)
00221 __wakeup_and_map(socket,packet);
00222 else if (socket->flags & DSI_SOCKET_COPY)
00223 __wakeup_and_copy(socket,packet);
00224 else
00225 {
00226
00227 ret = l4_ipc_send(socket->remote_socket.work_th,
00228 L4_IPC_SHORT_MSG,0,0,
00229 L4_IPC_SEND_TIMEOUT_0,
00230 &result);
00231 if (ret)
00232 LOG_Error("DSI: IPC error in wakeup 0x%02x", ret);
00233 }
00234
00235
00236 packet->flags &= (~DSI_PACKET_RX_WAITING);
00237 }
00238 else
00239 {
00240
00241 LOGdL(DEBUG_SYNC_SEND,"receiver not yet waiting");
00242
00243
00244 packet->flags |= DSI_PACKET_RX_PENDING;
00245
00246 }
00247
00248
00249 } else goto e_inv_sender;
00250 break;
00251 case DSI_SYNC_WAIT:
00252 if (l4_task_equal(src,socket->remote_socket.work_th))
00253 {
00254
00255
00256
00257
00258 LOGdL(DEBUG_SYNC_SEND,"receiver waits for packet %ld",dw1);
00259
00260 packet = &socket->packets[dw1];
00261
00262
00263 if (packet->flags & DSI_PACKET_RX_PENDING)
00264 {
00265 LOGdL(DEBUG_SYNC_SEND,"notification pending");
00266 LOGdL(DEBUG_SYNC_SEND,"wakeup "l4util_idfmt,
00267 l4util_idstr(src));
00268
00269 if (socket->flags & DSI_SOCKET_MAP)
00270 __wakeup_and_map(socket,packet);
00271 else if (socket->flags & DSI_SOCKET_COPY)
00272 __wakeup_and_copy(socket,packet);
00273 else
00274 {
00275
00276 ret = l4_ipc_send(socket->remote_socket.work_th,
00277 L4_IPC_SHORT_MSG,0,0,
00278 L4_IPC_SEND_TIMEOUT_0,
00279 &result);
00280 if (ret)
00281 LOG_Error("DSI: IPC error in reply 0x%02x",ret);
00282 }
00283
00284
00285 packet->flags &= (~DSI_PACKET_RX_PENDING);
00286 }
00287 else
00288 {
00289
00290 LOGdL(DEBUG_SYNC_SEND,"set wait flag");
00291
00292 packet->flags |= DSI_PACKET_RX_WAITING;
00293
00294
00295 socket->remote_socket.work_th = src;
00296 }
00297 } else goto e_inv_sender;
00298 break;
00299
00300 case DSI_SYNC_RELEASE:
00301 if (l4_task_equal(src,socket->remote_socket.work_th))
00302 {
00303
00304
00305
00306 packet = &socket->packets[dw1];
00307
00308 LOGdL(DEBUG_SYNC,"released packet %u (idx %lu)",
00309 packet->no,dw1);
00310
00311
00312 if (socket->release_callback)
00313 socket->release_callback(socket,packet);
00314
00315 #if RELEASE_DO_CALL
00316
00317 ret = l4_ipc_send(src,L4_IPC_SHORT_MSG,0,0,
00318 L4_IPC_SEND_TIMEOUT_0,
00319 &result);
00320 if (ret)
00321 LOG_Error("DSI: sync notification reply failed (0x%02x)!",
00322 ret);
00323 #endif
00324 } else goto e_inv_sender;
00325 break;
00326
00327 case DSI_SYNC_MAP:
00328 if (l4_task_equal(src,socket->remote_socket.work_th))
00329 {
00330
00331 __wakeup_and_map(socket,&socket->packets[dw1]);
00332 } else goto e_inv_sender;
00333 break;
00334
00335 case DSI_SYNC_COPY:
00336 if (l4_task_equal(src,socket->remote_socket.work_th))
00337 {
00338
00339 __wakeup_and_copy(socket,&socket->packets[dw1]);
00340 } else goto e_inv_sender;
00341 break;
00342 default:
00343 LOG_Error("DSI: invalid command (%ld) from "l4util_idfmt, dw0,
00344 l4util_idstr(src));
00345 }
00346 continue;
00347
00348 e_inv_sender:
00349 LOG_Error("DSI: ignoring message from "l4util_idfmt,
00350 l4util_idstr(src));
00351
00352 }
00353
00354 LOG_Error("DSI: IPC error in sender sync thread 0x%02x",ret);
00355 }
00356
00357
00358 Panic("DSI: left sync loop!");
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 void
00370 dsi_sync_thread_receive(void * data)
00371 {
00372 dsi_socket_t * socket;
00373 dsi_packet_t * packet;
00374 l4_threadid_t parent = l4thread_l4_id(l4thread_get_parent());
00375 int ret;
00376 l4_umword_t dw0,dw1;
00377 l4_msgdope_t result;
00378 l4_threadid_t src;
00379
00380 LOGdL(DEBUG_SYNC_RECEIVE,"up, parent "l4util_idfmt, l4util_idstr(parent));
00381
00382
00383 Assert(data != NULL);
00384 socket = (dsi_socket_t *)data;
00385
00386
00387 ret = l4_ipc_receive(parent,L4_IPC_SHORT_MSG,&dw0,&dw1,
00388 L4_IPC_NEVER,&result);
00389 if (ret || (dw0 != DSI_SYNC_CONNECTED))
00390 {
00391 Panic("DSI: sync setup IPC failed (0x%02X)!",ret);
00392 return;
00393 }
00394 Assert(data == (void *)dw1);
00395
00396 LOGdL(DEBUG_SYNC_RECEIVE,"connected.");
00397 LOGdL(DEBUG_SYNC_RECEIVE,"remote socket %d, work "l4util_idfmt,
00398 socket->remote_socket.socket,
00399 l4util_idstr(socket->remote_socket.work_th));
00400
00401
00402 while (1)
00403 {
00404 ret = l4_ipc_wait(&src,L4_IPC_SHORT_MSG,&dw0,&dw1,
00405 L4_IPC_NEVER,&result);
00406
00407 if (!ret)
00408 {
00409 LOGdL(DEBUG_SYNC_RECEIVE,"msg from "l4util_idfmt, l4util_idstr(src));
00410 LOGdL(DEBUG_SYNC_RECEIVE,"dw0 = %lu, dw1 = %lu",dw0,dw1);
00411
00412 switch (dw0)
00413 {
00414 case DSI_SYNC_COMMITED:
00415 if (l4_task_equal(src,socket->work_th))
00416 {
00417
00418
00419
00420
00421
00422 LOGdL(DEBUG_SYNC_RECEIVE,"wakeup sender, packet %ld",dw1);
00423
00424 packet = &socket->packets[dw1];
00425
00426
00427 if (packet->flags & DSI_PACKET_TX_WAITING)
00428 {
00429 LOGdL(DEBUG_SYNC_RECEIVE,"sender already waiting");
00430 LOGdL(DEBUG_SYNC_RECEIVE,"wakeup "l4util_idfmt,
00431 l4util_idstr(socket->remote_socket.work_th));
00432
00433
00434 ret = l4_ipc_send(socket->remote_socket.work_th,
00435 L4_IPC_SHORT_MSG,0,0,
00436 L4_IPC_SEND_TIMEOUT_0,
00437 &result);
00438 if (ret)
00439 LOG_Error("DSI: IPC error in wakeup 0x%02x",ret);
00440
00441
00442 packet->flags &= (~DSI_PACKET_TX_WAITING);
00443 }
00444 else
00445 {
00446
00447 LOGdL(DEBUG_SYNC_RECEIVE,"sender not yet waiting");
00448
00449
00450 packet->flags |= DSI_PACKET_TX_PENDING;
00451 }
00452 } else goto e_inv_sender;
00453
00454 break;
00455 case DSI_SYNC_WAIT:
00456 if (l4_task_equal(src,socket->remote_socket.work_th))
00457 {
00458
00459
00460
00461
00462 LOGdL(DEBUG_SYNC_RECEIVE,"sender waits for packet %ld",dw1);
00463
00464 packet = &socket->packets[dw1];
00465
00466
00467 if (packet->flags & DSI_PACKET_TX_PENDING)
00468 {
00469 LOGdL(DEBUG_SYNC,"notification pending");
00470 LOGdL(DEBUG_SYNC,"wakeup "l4util_idfmt,
00471 l4util_idstr(src));
00472
00473
00474 ret = l4_ipc_send(src,L4_IPC_SHORT_MSG,0,0,
00475 L4_IPC_SEND_TIMEOUT_0,
00476 &result);
00477 if (ret)
00478 LOG_Error("DSI: IPC error in reply 0x%02x", ret);
00479
00480
00481 packet->flags &= (~DSI_PACKET_TX_PENDING);
00482 }
00483 else
00484 {
00485
00486 LOGdL(DEBUG_SYNC,"set wait flag");
00487
00488
00489 packet->flags |= DSI_PACKET_TX_WAITING;
00490
00491
00492 socket->remote_socket.work_th = src;
00493 }
00494 } else goto e_inv_sender;
00495
00496 break;
00497
00498 default:
00499 LOG_Error("DSI: invalid command (%ld) from "l4util_idfmt,
00500 dw0, l4util_idstr(src));
00501 }
00502 continue;
00503
00504 e_inv_sender:
00505 LOG_Error("ignoring message from "l4util_idfmt, l4util_idstr(src));
00506
00507 }
00508
00509 LOG_Error("DSI: IPC error in receiver sync thread 0x%02x", ret);
00510 }
00511
00512
00513 Panic("DSI: left sync loop!");
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 int
00528 dsi_start_sync_thread(dsi_socket_t * socket)
00529 {
00530 int ret;
00531 l4_msgdope_t result;
00532
00533
00534 if (l4_is_invalid_id(socket->sync_th))
00535 return -L4_EINVAL;
00536
00537
00538 ret = l4_ipc_send(socket->sync_th,L4_IPC_SHORT_MSG,DSI_SYNC_CONNECTED,
00539 (l4_umword_t)socket,L4_IPC_NEVER,&result);
00540 if (ret)
00541 return -L4_EIPC;
00542 else
00543 return 0;
00544 }