00001
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <assert.h>
00017 #include <string.h>
00018
00019 #include <l4/crtx/crt0.h>
00020 #include <l4/events/events.h>
00021 #include <l4/log/l4log.h>
00022 #include <l4/names/libnames.h>
00023 #include <l4/rmgr/librmgr.h>
00024 #include <l4/sigma0/sigma0.h>
00025 #include <l4/sys/ipc.h>
00026 #include <l4/sys/syscalls.h>
00027 #include <l4/sys/types.h>
00028 #include <l4/sys/kdebug.h>
00029 #include <l4/sys/kernel.h>
00030 #include <l4/util/rdtsc.h>
00031 #include <l4/util/util.h>
00032 #include <l4/util/l4_macros.h>
00033
00034 char LOG_tag[9]="ev_demo3";
00035
00036
00037
00038 extern char _end, _stext, _etext, __bss_start;
00039
00040
00041 static const int debug_pager = 0;
00042 static const int debug_send = 0;
00043 static const int debug_recv = 0;
00044
00046 #define SEND_TASK_COUNT 1
00047
00048 #define RECV_TASK_COUNT 1
00049
00050 #define TASK_COUNT (SEND_TASK_COUNT + RECV_TASK_COUNT)
00051
00052 #define SEND_EVENT_COUNT 100
00053
00054 #define RECV_EVENT_COUNT (SEND_EVENT_COUNT * SEND_TASK_COUNT)
00055
00056
00057 static const int timebenchmark = 1;
00058
00060 #define PINGPONG_IPC 5000
00061
00062
00063 #define DEMO3_EVENTID 10
00064
00065 #define DEMO3_PRIORITY 0
00066
00067
00068 static int task_min = -1;
00069 static int task_max = -1;
00070
00071
00072 #define PAGER_THREAD 1
00073 static l4_threadid_t pager_thread_id = L4_INVALID_ID;
00074 char pager_thread_stack[2048];
00075
00076
00077
00078 #define COW_POOL_PAGES 2000
00079 static int copied_pages = 0;
00080 static l4_addr_t cow_pool;
00081 static l4_addr_t cow_pages;
00082 static l4_addr_t my_program_data_copy;
00083
00084 static l4_addr_t unshare_data(l4_addr_t addr, l4_threadid_t tid);
00085
00086
00087 typedef volatile struct
00088 {
00089 l4_uint32_t start_tsc;
00090 l4_uint32_t nr_pagefaults;
00091 int recv_task_min;
00092 int send_task_min;
00093 l4_threadid_t main_thread_id;
00094 } shared_data_t;
00095
00096
00097 static shared_data_t *shared_data = 0;
00098
00099
00100
00101 static
00102 void ipc_error(char * msg, int error)
00103 {
00104 if(error == 0){
00105 printf("%s : ok\n", msg);
00106 }
00107 else {
00108 printf(" \n");
00109
00110 if( error == L4_IPC_ENOT_EXISTENT ){
00111 printf("%s : L4_IPC_ENOT_EXISTENT "
00112 "(Non-existing destination or source)\n", msg);
00113 }
00114 if( error == L4_IPC_RETIMEOUT ){
00115 printf("%s : L4_IPC_RETIMEOUT (Timeout during receive)\n", msg);
00116 }
00117 if( error == L4_IPC_SETIMEOUT ){
00118 printf("%s : L4_IPC_SETIMEOUT (Timeout during send)\n", msg);
00119 }
00120 if( error == L4_IPC_RECANCELED ){
00121 printf("%s : L4_IPC_RECANCELED (Receive operation cancelled)\n", msg);
00122 }
00123 if( error == L4_IPC_SECANCELED ){
00124 printf("%s : L4_IPC_SECANCELED (Send operation cancelled)\n", msg);
00125 }
00126 if( error == L4_IPC_REMAPFAILED ){
00127 printf("%s : L4_IPC_REMAPFAILED (Map failed in send)\n", msg);
00128 }
00129 if( error == L4_IPC_SEMAPFAILED ){
00130 printf("%s : L4_IPC_SEMAPFAILED (Map failed in receive)\n", msg);
00131 }
00132 if( error == L4_IPC_RESNDPFTO ){
00133 printf("%s : L4_IPC_RESNDPFTO (Send pagefault timeout)\n", msg);
00134 }
00135 if( error == L4_IPC_SESNDPFTO ){
00136 printf("%s : L4_IPC_SESNDPFTO (?)\n", msg);
00137 }
00138 if( error == L4_IPC_RERCVPFTO ){
00139 printf("%s : L4_IPC_RERCVPFTO (?)\n", msg);
00140 }
00141 if( error == L4_IPC_SERCVPFTO ){
00142 printf("%s : L4_IPC_SERCVPFTO (Receive pagefault timeout)\n", msg);
00143 }
00144 if( error == L4_IPC_REABORTED ){
00145 printf("%s : L4_IPC_REABORTED (Receive operation aborted)\n", msg);
00146 }
00147 if( error == L4_IPC_SEABORTED ){
00148 printf("%s : L4_IPC_SEABORTED (Send operation aborted)\n", msg);
00149 }
00150 if( error == L4_IPC_REMSGCUT ){
00151 printf("%s : L4_IPC_REMSGCUT (Received message cut)\n", msg);
00152 }
00153 if( error == L4_IPC_SEMSGCUT ){
00154 printf("%s : L4_IPC_SEMSGCUT (?)\n", msg);
00155 }
00156 }
00157 }
00158
00159
00160 static int
00161 get_thread_ids(l4_threadid_t *my_id,
00162 l4_threadid_t *my_preempter,
00163 l4_threadid_t *my_pager,
00164 l4_addr_t *esp)
00165 {
00166 l4_umword_t ignore, _esp;
00167 l4_threadid_t _my_id, _my_preempter, _my_pager;
00168
00169 _my_id = l4_myself();
00170
00171 _my_preempter = L4_INVALID_ID;
00172 _my_pager = L4_INVALID_ID;
00173
00174 l4_thread_ex_regs( _my_id, -1, -1,
00175 &_my_preempter,
00176 &_my_pager,
00177 &ignore,
00178 &ignore,
00179 &_esp
00180 );
00181
00182 if(my_id) *my_id = _my_id;
00183 if(my_preempter) *my_preempter = _my_preempter;
00184 if(my_pager) *my_pager = _my_pager;
00185 if(esp) *esp = _esp;
00186 return 0;
00187 }
00188
00189
00190 static int
00191 get_tasks(void)
00192 {
00193 int res, task;
00194 int got_flag = 0;
00195 int count = 0;
00196
00197
00198 res = rmgr_init();
00199
00200 if( res != 1){
00201 printf("rmgr_init failed with %x\n", res);
00202 }
00203
00204 task = 0;
00205
00206 while (count < TASK_COUNT)
00207 {
00208 res = rmgr_get_task(task);
00209
00210 if(res == 0)
00211 {
00212 count++;
00213 if(got_flag == 0)
00214 {
00215 got_flag = 1;
00216 if(task_min == -1) task_min = task;
00217 }
00218 }
00219 else
00220 {
00221 if(got_flag == 1)
00222 {
00223 got_flag = 0;
00224 if(task_max == -1) task_max = task;
00225 break;
00226 }
00227 }
00228
00229 task++;
00230 }
00231
00232 return count;
00233 }
00234
00235
00236
00237
00238
00239 static l4_addr_t
00240 unshare_data(l4_addr_t addr, l4_threadid_t tid)
00241 {
00242 l4_addr_t new_page = cow_pool;
00243 l4_addr_t img_base = l4_trunc_page(addr);
00244 l4_addr_t data_start = (l4_addr_t)&_etext;
00245 l4_addr_t data_end = (l4_addr_t)&_end;
00246
00247 if (!cow_pages)
00248 {
00249 printf("PANIC: Out of cow pages\n");
00250 exit(-1);
00251 }
00252
00253 cow_pool += L4_PAGESIZE;
00254 cow_pages--;
00255
00256 memcpy((void*)new_page, (void*)img_base, L4_PAGESIZE);
00257
00258
00259 if (!( (img_base+L4_PAGESIZE <= data_start)
00260 || (img_base >= data_end)))
00261 {
00262
00263
00264 l4_addr_t dst_offs;
00265 l4_addr_t src_offs;
00266 l4_size_t src_size;
00267 if (data_start <= img_base)
00268 {
00269 src_offs = img_base - data_start;
00270 dst_offs = 0;
00271 if (data_end >= img_base + L4_PAGESIZE)
00272 src_size = L4_PAGESIZE;
00273 else
00274 src_size = data_end-img_base;
00275 }
00276 else
00277 {
00278 src_offs = 0;
00279 dst_offs = data_start - img_base;
00280 if (data_end >= img_base + L4_PAGESIZE)
00281 src_size = L4_PAGESIZE-dst_offs;
00282 else
00283 src_size = data_end-img_base-dst_offs;
00284 }
00285
00286 memcpy((void*)new_page+dst_offs,
00287 (void*)my_program_data_copy+src_offs,
00288 src_size);
00289 #if 0
00290 printf("offs_shared_data=%08x\n"
00291 "copy from %08x-%08x to %08x-%08x\n"
00292 "data from %08x-%08x page %08x-%08x\n"
00293 "saved_data %08x-%08x\n",
00294 (l4_umword_t)&shared_data - (l4_umword_t)&_etext,
00295 my_program_data_copy+src_offs,
00296 my_program_data_copy+src_offs+src_size,
00297 new_page+dst_offs,
00298 new_page+dst_offs+src_size,
00299 data_start, data_end,
00300 img_base, img_base+L4_PAGESIZE,
00301 my_program_data_copy, my_program_data_copy+data_end-data_start);
00302 enter_kdebug("stop");
00303 #endif
00304 }
00305
00306 if (debug_pager)
00307 printf("unshared data page %08lx => %08lx client "l4util_idfmt"\n",
00308 addr, new_page, l4util_idstr(tid));
00309
00310 if (debug_pager)
00311 printf("copied pages: %d\n", ++copied_pages);
00312
00313 return new_page;
00314 }
00315
00316
00318 static void
00319 pager_thread(void)
00320 {
00321 int res, rw_page_fault;
00322 l4_threadid_t src;
00323 l4_addr_t fault_address, fault_eip;
00324 l4_snd_fpage_t fp;
00325 l4_msgdope_t dope;
00326
00327 l4_touch_ro((void*)&_stext, l4_round_page(&_etext - &_stext));
00328 l4_touch_rw((void*)shared_data, L4_PAGESIZE);
00329
00330
00331 res = l4_ipc_wait(&src,
00332 L4_IPC_SHORT_MSG,
00333 & fault_address,
00334 & fault_eip,
00335 L4_IPC_NEVER,
00336 &dope);
00337
00338 if(res)
00339 ipc_error("first PF", res);
00340
00341 while(1)
00342 {
00343 rw_page_fault = fault_address & 0x02;
00344 fault_address &= 0xfffffffc;
00345
00346 shared_data->nr_pagefaults++;
00347
00348
00349 if(debug_pager)
00350 printf("[%s page fault in "l4util_idfmt" at %08lx (EIP %08lx) ",
00351 rw_page_fault ? "write" : "read",
00352 l4util_idstr(src), fault_address, fault_eip);
00353
00354 if( (l4_addr_t) & _stext <= fault_address
00355 && ((l4_addr_t) & _etext > fault_address)
00356 && !rw_page_fault)
00357 {
00358 if(debug_pager)
00359 printf("Code\n");
00360 fp.fpage = l4_fpage(fault_address, L4_LOG2_PAGESIZE,
00361 L4_FPAGE_RO, L4_FPAGE_MAP);
00362 fp.snd_base = l4_trunc_page(fault_address);
00363 }
00364
00365 else if((l4_addr_t) & _etext <= fault_address
00366 && ((l4_addr_t) & _end > fault_address+3))
00367 {
00368 l4_addr_t new_page;
00369 if(debug_pager)
00370 printf("Data\n");
00371
00372 if (rw_page_fault)
00373 {
00374 new_page = unshare_data(fault_address, src);
00375 fp.fpage = l4_fpage(new_page, L4_LOG2_PAGESIZE,
00376 L4_FPAGE_RW, L4_FPAGE_MAP);
00377 l4_fpage_unmap(l4_fpage(l4_trunc_page(fault_address),
00378 L4_LOG2_PAGESIZE, 0, 0),
00379 L4_FP_FLUSH_PAGE | L4_FP_OTHER_SPACES);
00380 }
00381 else
00382 {
00383 new_page = l4_trunc_page(fault_address);
00384 fp.fpage = l4_fpage(new_page, L4_LOG2_PAGESIZE,
00385 L4_FPAGE_RO, L4_FPAGE_MAP);
00386 }
00387
00388 fp.snd_base = l4_trunc_page(fault_address);
00389 }
00390
00391
00392 else
00393 {
00394 if ( ((l4_addr_t)shared_data <= fault_address)
00395 && (((l4_addr_t)shared_data + L4_PAGESIZE) > fault_address))
00396 {
00397 if(debug_pager)
00398 printf("Shared data\n");
00399 fp.fpage = l4_fpage(fault_address, L4_LOG2_PAGESIZE,
00400 L4_FPAGE_RO, L4_FPAGE_MAP);
00401 fp.snd_base = l4_trunc_page(fault_address);
00402 }
00403 else
00404 {
00405
00406 if(!debug_pager)
00407 printf("[%s page fault in "l4util_idfmt" at %08lx (EIP %08lx) ",
00408 rw_page_fault ? "write" : "read",
00409 l4util_idstr(src), fault_address, fault_eip);
00410 printf("stop pager]\n");
00411 enter_kdebug("stop");
00412 fp.snd_base = 0;
00413 l4_ipc_sleep(L4_IPC_NEVER);
00414 }
00415 }
00416
00417 if(debug_pager)
00418 printf(" %s (%s), base : %08x, size : %d, offset : %08lx]\n",
00419 fp.fpage.fp.grant ? "grant" : "map",
00420 fp.fpage.fp.write ? "WR" : "RO",
00421 fp.fpage.fp.page << L4_PAGESHIFT,
00422 fp.fpage.fp.size,
00423 fp.snd_base
00424 );
00425
00426
00427 res = l4_ipc_reply_and_wait
00428 (src,
00429 L4_IPC_SHORT_FPAGE,
00430 fp.snd_base,
00431 fp.fpage.fpage ,
00432 &src,
00433 L4_IPC_SHORT_MSG,
00434 &fault_address,
00435 &fault_eip,
00436 L4_IPC_NEVER,
00437 &dope);
00438
00439 if(res)
00440 ipc_error("PF", res);
00441 }
00442 }
00443
00445 static void
00446 recv_task(void)
00447 {
00448 l4_taskid_t my_id;
00449 l4_umword_t ignore;
00450 l4_msgdope_t dope;
00451
00452 l4events_ch_t event_ch = DEMO3_EVENTID;
00453 l4events_nr_t event_nr = L4EVENTS_NO_NR;
00454 l4events_event_t event;
00455 int i, res;
00456
00457 l4_uint32_t in ,out;
00458 l4_uint32_t ipc_start, ipc_end;
00459 static l4_uint32_t all_ipc_times[RECV_EVENT_COUNT];
00460 int ipc_counter = 0;
00461
00462 char my_name[16];
00463
00464 my_id = l4_myself();
00465
00466 sprintf(my_name, "rcv %3d", my_id.id.task-shared_data->recv_task_min);
00467 strcpy(LOG_tag, my_name);
00468
00469
00470
00471 l4_touch_ro(&_stext, &_etext-&_stext);
00472 l4_touch_rw(&crt0_stack_low, &crt0_stack_high-&crt0_stack_low);
00473
00474 printf("started.\n");
00475
00476 l4events_register(DEMO3_EVENTID, DEMO3_PRIORITY);
00477
00478 printf("registered.\n");
00479
00480
00481 l4_ipc_send(shared_data->main_thread_id, 0,
00482 (l4_umword_t)0, (l4_umword_t)0, L4_IPC_NEVER, &dope);
00483
00484
00485 l4_ipc_receive(shared_data->main_thread_id,
00486 0, &ignore, &ignore, L4_IPC_NEVER, &dope);
00487
00488
00489
00490 for (i = 0; i < RECV_EVENT_COUNT; i++)
00491 {
00492 ipc_start = l4_rdtsc_32();
00493 res = l4events_receive(&event_ch, &event, &event_nr,
00494 L4_IPC_NEVER, L4EVENTS_RECV_SHORT);
00495 ipc_end = l4_rdtsc_32();
00496
00497 all_ipc_times[ipc_counter++] = (ipc_end-ipc_start);
00498
00499 if (res != L4EVENTS_OK)
00500 {
00501 printf("recv failed with %d.\n", res);
00502 }
00503 }
00504
00505 out = l4_rdtsc_32();
00506 in = shared_data->start_tsc;
00507
00508
00509 if (timebenchmark && (my_id.id.task == shared_data->recv_task_min))
00510 {
00511 if (shared_data->nr_pagefaults != 0)
00512 {
00513 printf("WARNING: %d pagefaults occured during measurment!\n",
00514 shared_data->nr_pagefaults);
00515 }
00516
00517 printf("number of CPU cycles: %u\n", (l4_uint32_t)(out-in));
00518 printf("number of IPC calls: %d\n", ipc_counter);
00519 printf("PINGPONG ratio: %d\n\n", (l4_uint32_t)((out-in)/(PINGPONG_IPC*ipc_counter)));
00520
00521 for (i=0; i < ipc_counter; i++)
00522 {
00523 printf("time for ipc %u is %u \n", i, all_ipc_times[i]);
00524 }
00525 }
00526
00527 l4events_unregister(DEMO3_EVENTID);
00528
00529 printf("end.\n");
00530
00531
00532 l4_ipc_sleep(L4_IPC_NEVER);
00533
00534 return;
00535 }
00536
00538 static void
00539 send_task(void)
00540 {
00541 l4_taskid_t my_id;
00542 l4_msgdope_t dope;
00543 l4events_event_t event;
00544 l4events_nr_t event_nr;
00545 int i, res;
00546 char my_name[16];
00547
00548 my_id = l4_myself();
00549
00550 sprintf(my_name, "rcv %3d", my_id.id.task-shared_data->recv_task_min);
00551 strcpy(LOG_tag, my_name);
00552
00553
00554
00555 l4_touch_ro(&_stext, &_etext-&_stext);
00556 l4_touch_ro((void*)shared_data, sizeof(shared_data_t));
00557 l4_touch_rw(&crt0_stack_low, &crt0_stack_high-&crt0_stack_low);
00558
00559
00560 strcpy(event.str, "hi");
00561 event.len = strlen(event.str)+1;
00562
00563
00564 for (i = 0; i < SEND_EVENT_COUNT; i++)
00565 {
00566 if(debug_send)
00567 {
00568 printf("%d sending\n", my_id.id.task);
00569 }
00570
00571 res = l4events_send(DEMO3_EVENTID, &event, &event_nr, 0);
00572
00573 if(debug_send)
00574 {
00575 if (res == L4EVENTS_OK)
00576 {
00577 printf("%d send successful.\n", my_id.id.task);
00578 }
00579 else
00580 {
00581 printf("%d send failed.\n", my_id.id.task);
00582 }
00583 }
00584 }
00585
00586
00587
00588 l4_ipc_send(shared_data->main_thread_id,
00589 0, (l4_umword_t)0, (l4_umword_t)0, L4_IPC_NEVER, &dope);
00590
00591
00592
00593 l4_ipc_sleep(L4_IPC_NEVER);
00594
00595 return;
00596 }
00597
00598
00599
00601 static void
00602 get_shared_memory(l4_threadid_t pager)
00603 {
00604 assert(sizeof(shared_data_t) <= L4_PAGESIZE);
00605
00606 shared_data = (shared_data_t*)rmgr_reserve_mem(L4_PAGESIZE,
00607 L4_LOG2_PAGESIZE, 0, 0, 0);
00608 l4sigma0_map_mem(pager,
00609 (l4_addr_t)shared_data, (l4_addr_t)shared_data, L4_PAGESIZE);
00610
00611 if (shared_data == (shared_data_t*)~0U)
00612 {
00613 printf("Cannot allocate page for sharing data section\n");
00614 enter_kdebug("out of memory");
00615 }
00616 }
00617
00619 static void
00620 save_data(l4_threadid_t pager)
00621 {
00622 l4_addr_t beg = l4_trunc_page(&_etext);
00623 l4_addr_t end = l4_round_page(&_end);
00624
00625 my_program_data_copy = rmgr_reserve_mem(end-beg, L4_LOG2_PAGESIZE, 0, 0, 0);
00626
00627 if (my_program_data_copy == ~0U)
00628 {
00629 printf("Cannot allocate %ldkB memory for unsharing data section\n",
00630 (end-beg)/1024);
00631 enter_kdebug("out of memory");
00632 }
00633
00634 l4sigma0_map_mem(pager,
00635 my_program_data_copy, my_program_data_copy, end-beg);
00636 memcpy((void*)my_program_data_copy, (void*)&_etext, &_end-&_etext);
00637 }
00638
00640 static void
00641 reserve_cow(l4_threadid_t pager)
00642 {
00643 cow_pool = rmgr_reserve_mem(COW_POOL_PAGES*L4_PAGESIZE,
00644 L4_LOG2_PAGESIZE, 0, 0, 0);
00645 if (cow_pool == ~0U)
00646 {
00647 printf("Cannot allocate %dkB memory for cow pool!\n",
00648 COW_POOL_PAGES*L4_PAGESIZE/1024);
00649 enter_kdebug("out of memory");
00650 }
00651
00652 l4sigma0_map_mem(pager,
00653 cow_pool, cow_pool, COW_POOL_PAGES*L4_PAGESIZE);
00654 cow_pages = COW_POOL_PAGES;
00655 }
00656
00657
00658 int main(void)
00659 {
00660 l4_threadid_t my_id, my_preempter, my_pager, new_pager;
00661
00662 l4_umword_t ignore;
00663 l4_msgdope_t dope;
00664 l4_threadid_t t, new_t;
00665
00666 int task_curr, tasks, i;
00667
00668
00669 rmgr_init();
00670
00671
00672 l4events_init();
00673
00674
00675
00676 names_register("eventdemo");
00677
00678 get_thread_ids(&my_id, &my_preempter, &my_pager, NULL);
00679
00680
00681 get_shared_memory(my_pager);
00682 save_data(my_pager);
00683 reserve_cow(my_pager);
00684
00685 printf("starting event server demo...\n");
00686
00687
00688 t = l4_myself();
00689
00690
00691 tasks = get_tasks();
00692
00693 printf("got %d tasks.\n", tasks);
00694
00695 if (tasks < TASK_COUNT)
00696 {
00697 printf("got not enough tasks!!!");
00698 enter_kdebug("main");
00699 }
00700
00701
00702 shared_data->main_thread_id = my_id;
00703 pager_thread_id = my_id;
00704 pager_thread_id.id.lthread = PAGER_THREAD;
00705 my_preempter = L4_INVALID_ID;
00706 new_pager = my_pager;
00707 l4_thread_ex_regs( pager_thread_id,
00708 (l4_umword_t)pager_thread,
00709 (l4_umword_t)pager_thread_stack + 2048,
00710
00711 &my_preempter,
00712 &new_pager,
00713 &ignore,
00714 &ignore,
00715 &ignore
00716 );
00717
00718 task_curr = task_min;
00719 shared_data->recv_task_min = task_min;
00720 shared_data->send_task_min = task_min+RECV_TASK_COUNT;
00721
00722
00723 for (i=0; i < RECV_TASK_COUNT; i++)
00724 {
00725 t.id.task = task_curr;
00726 t.id.lthread = 0;
00727
00728 printf("start recv task.\n");
00729
00730 new_t = l4_task_new(t,
00731 155,
00732 (l4_umword_t)&crt0_stack_high,
00733 (l4_umword_t)recv_task,
00734 pager_thread_id );
00735
00736 task_curr = task_curr + 1;
00737 }
00738
00739 printf("waiting for receive tasks to become ready.\n");
00740
00741 for (i=0; i<RECV_TASK_COUNT; i++)
00742 {
00743 t.id.task = shared_data->recv_task_min+i;
00744 t.id.lthread = 0;
00745
00746 l4_ipc_receive(t, 0, &ignore, &ignore, L4_IPC_NEVER, &dope);
00747 }
00748
00749
00750 for (i=0; i<SEND_TASK_COUNT; i++)
00751 {
00752 t.id.task = task_curr;
00753 t.id.lthread = 0;
00754
00755 printf("start send task.\n");
00756
00757 new_t = l4_task_new(t,
00758 255,
00759 (l4_umword_t)&crt0_stack_high,
00760 (l4_umword_t)send_task,
00761 pager_thread_id );
00762
00763 task_curr = task_curr + 1;
00764 }
00765
00766 printf("waiting for send tasks to become ready.\n");
00767
00768 for (i=0; i<SEND_TASK_COUNT; i++)
00769 {
00770 t.id.task = shared_data->send_task_min+i;
00771 t.id.lthread = 0;
00772 l4_ipc_receive(t, 0, &ignore, &ignore, L4_IPC_NEVER, &dope);
00773 }
00774
00775
00776 shared_data->nr_pagefaults = 0;
00777
00778 shared_data->start_tsc = l4_rdtsc_32();
00779
00780 printf("waking up receive tasks.\n");
00781
00782 for (i=0; i<RECV_TASK_COUNT; i++)
00783 {
00784 t.id.task = shared_data->recv_task_min+i;
00785 t.id.lthread = 0;
00786 l4_ipc_send(t, 0, (l4_umword_t)0, (l4_umword_t)0, L4_IPC_NEVER, &dope);
00787 }
00788
00789 printf("end of the game.\n");
00790
00791
00792 l4_ipc_sleep(L4_IPC_NEVER);
00793
00794 return 0;
00795 }
00796