00001
00011
00012
00013
00014
00015
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020
00021 #include <l4/crtx/crt0.h>
00022 #include <l4/log/l4log.h>
00023 #include <l4/names/libnames.h>
00024 #include <l4/rmgr/librmgr.h>
00025 #include <l4/sigma0/sigma0.h>
00026 #include <l4/sys/types.h>
00027 #include <l4/sys/syscalls.h>
00028 #include <l4/sys/ipc.h>
00029 #include <l4/sys/kernel.h>
00030 #include <l4/util/util.h>
00031 #include <l4/util/l4_macros.h>
00032
00033 #include <l4/events/events.h>
00034
00035 char LOG_tag[9]="ev_demo2";
00036
00037
00038 extern char _end, _start, _stext, _etext;
00039
00040
00041 static int debugpager = 0;
00042
00043
00044 #define DEMO2_EVENTID 9
00045
00046
00047 #define DEMO2_PRIORITY 0
00048
00049
00050 #define TASK_MAX 3
00051 static int task_min = -1;
00052 static int task_max = -1;
00053
00054
00055 #define PAGER_THREAD 1
00056 static l4_threadid_t pager_thread_id = L4_INVALID_ID;
00057 char pager_thread_stack[2048];
00058
00059
00060 #define COW_POOL_PAGES 2000
00061 static int copied_pages = 0;
00062 static l4_addr_t cow_pool;
00063 static l4_addr_t cow_pages;
00064 static l4_addr_t my_program_data_copy;
00065
00066 static l4_addr_t unshare_data(l4_addr_t addr, l4_threadid_t tid);
00067
00068
00069 static void
00070 ipc_error(char * msg, int error)
00071 {
00072 if(error == 0){
00073 printf("%s : ok\n", msg);
00074 }
00075 else {
00076 if( error == L4_IPC_ENOT_EXISTENT ){
00077 printf("%s : L4_IPC_ENOT_EXISTENT "
00078 "(Non-existing destination or source)\n", msg);
00079 }
00080 if( error == L4_IPC_RETIMEOUT ){
00081 printf("%s : L4_IPC_RETIMEOUT (Timeout during receive)\n", msg);
00082 }
00083 if( error == L4_IPC_SETIMEOUT ){
00084 printf("%s : L4_IPC_SETIMEOUT (Timeout during send)\n", msg);
00085 }
00086 if( error == L4_IPC_RECANCELED ){
00087 printf("%s : L4_IPC_RECANCELED (Receive operation cancelled)\n", msg);
00088 }
00089 if( error == L4_IPC_SECANCELED ){
00090 printf("%s : L4_IPC_SECANCELED (Send operation cancelled)\n", msg);
00091 }
00092 if( error == L4_IPC_REMAPFAILED ){
00093 printf("%s : L4_IPC_REMAPFAILED (Map failed in send)\n", msg);
00094 }
00095 if( error == L4_IPC_SEMAPFAILED ){
00096 printf("%s : L4_IPC_SEMAPFAILED (Map failed in receive)\n", msg);
00097 }
00098 if( error == L4_IPC_RESNDPFTO ){
00099 printf("%s : L4_IPC_RESNDPFTO (Send pagefault timeout)\n", msg);
00100 }
00101 if( error == L4_IPC_SESNDPFTO ){
00102 printf("%s : L4_IPC_SESNDPFTO (?)\n", msg);
00103 }
00104 if( error == L4_IPC_RERCVPFTO ){
00105 printf("%s : L4_IPC_RERCVPFTO (?)\n", msg);
00106 }
00107 if( error == L4_IPC_SERCVPFTO ){
00108 printf("%s : L4_IPC_SERCVPFTO (Receive pagefault timeout)\n", msg);
00109 }
00110 if( error == L4_IPC_REABORTED ){
00111 printf("%s : L4_IPC_REABORTED (Receive operation aborted)\n", msg);
00112 }
00113 if( error == L4_IPC_SEABORTED ){
00114 printf("%s : L4_IPC_SEABORTED (Send operation aborted)\n", msg);
00115 }
00116 if( error == L4_IPC_REMSGCUT ){
00117 printf("%s : L4_IPC_REMSGCUT (Received message cut)\n", msg);
00118 }
00119 if( error == L4_IPC_SEMSGCUT ){
00120 printf("%s : L4_IPC_SEMSGCUT (?)\n", msg);
00121 }
00122 }
00123 }
00124
00125
00126
00127
00128
00129 static void
00130 sit_and_wait(int exp)
00131 {
00132 l4_ipc_sleep(l4_ipc_timeout(255,16-exp,255,16-exp));
00133 }
00134
00135
00136
00137 static void
00138 wait_forever(void)
00139 {
00140 l4_ipc_sleep(L4_IPC_NEVER);
00141 }
00142
00143
00144
00145 static int
00146 get_thread_ids(l4_threadid_t *my_id,
00147 l4_threadid_t *my_preempter,
00148 l4_threadid_t *my_pager,
00149 l4_addr_t *esp)
00150 {
00151 l4_umword_t ignore, _esp;
00152 l4_threadid_t _my_id, _my_preempter, _my_pager;
00153
00154 _my_id = l4_myself();
00155
00156 _my_preempter = L4_INVALID_ID;
00157 _my_pager = L4_INVALID_ID;
00158
00159 l4_thread_ex_regs( _my_id, -1, -1,
00160 &_my_preempter,
00161 &_my_pager,
00162 &ignore,
00163 &ignore,
00164 &_esp
00165 );
00166
00167 if(my_id) *my_id = _my_id;
00168 if(my_preempter) *my_preempter = _my_preempter;
00169 if(my_pager) *my_pager = _my_pager;
00170 if(esp) *esp = _esp;
00171 return 0;
00172 }
00173
00174
00175 static int
00176 get_tasks(void)
00177 {
00178 int res, task;
00179 int got_flag = 0;
00180 int count = 0;
00181
00182
00183 res = rmgr_init();
00184
00185 if( res != 1){
00186 printf("rmgr_init failed with %x\n", res);
00187 }
00188
00189 task = 0;
00190
00191 while (count < TASK_MAX)
00192 {
00193 res = rmgr_get_task(task);
00194
00195 if(res == 0)
00196 {
00197 count++;
00198 if(got_flag == 0)
00199 {
00200 got_flag = 1;
00201 if(task_min == -1) task_min = task;
00202 }
00203 }
00204 else
00205 {
00206 if(got_flag == 1)
00207 {
00208 got_flag = 0;
00209 if(task_max == -1) task_max = task;
00210 break;
00211 }
00212 }
00213
00214 task++;
00215 }
00216
00217 return count;
00218 }
00219
00220
00221
00222
00223 static l4_addr_t
00224 unshare_data(l4_addr_t addr, l4_threadid_t tid)
00225 {
00226 l4_addr_t new_page = cow_pool;
00227 l4_addr_t img_base = l4_trunc_page(addr);
00228 l4_addr_t data_start = (l4_addr_t)&_etext;
00229 l4_addr_t data_end = (l4_addr_t)&_end;
00230
00231 if (!cow_pages)
00232 {
00233 printf("PANIC: Out of cow pages\n");
00234 exit(-1);
00235 }
00236
00237 cow_pool += L4_PAGESIZE;
00238 cow_pages--;
00239
00240 memcpy((void*)new_page, (void*)img_base, L4_PAGESIZE);
00241
00242
00243 if (!( (img_base+L4_PAGESIZE <= data_start)
00244 || (img_base >= data_end)))
00245 {
00246
00247
00248 l4_addr_t dst_offs;
00249 l4_addr_t src_offs;
00250 l4_size_t src_size;
00251 if (data_start <= img_base)
00252 {
00253 src_offs = img_base - data_start;
00254 dst_offs = 0;
00255 if (data_end >= img_base + L4_PAGESIZE)
00256 src_size = L4_PAGESIZE;
00257 else
00258 src_size = data_end-img_base;
00259 }
00260 else
00261 {
00262 src_offs = 0;
00263 dst_offs = data_start - img_base;
00264 if (data_end >= img_base + L4_PAGESIZE)
00265 src_size = L4_PAGESIZE-dst_offs;
00266 else
00267 src_size = data_end-img_base-dst_offs;
00268 }
00269
00270 memcpy((void*)new_page+dst_offs,
00271 (void*)my_program_data_copy+src_offs,
00272 src_size);
00273 #if 0
00274 printf("offs_shared_data=%08x\n"
00275 "copy from %08x-%08x to %08x-%08x\n"
00276 "data from %08x-%08x page %08x-%08x\n"
00277 "saved_data %08x-%08x\n",
00278 (l4_umword_t)&shared_data - (l4_umword_t)&_etext,
00279 my_program_data_copy+src_offs,
00280 my_program_data_copy+src_offs+src_size,
00281 new_page+dst_offs,
00282 new_page+dst_offs+src_size,
00283 data_start, data_end,
00284 img_base, img_base+L4_PAGESIZE,
00285 my_program_data_copy, my_program_data_copy+data_end-data_start);
00286 enter_kdebug("stop");
00287 #endif
00288 }
00289
00290 if (debugpager)
00291 printf("unshared data page %08lx => %08lx client "l4util_idfmt"\n",
00292 addr, new_page, l4util_idstr(tid));
00293
00294 if (debugpager)
00295 printf("copied pages: %d\n", ++copied_pages);
00296
00297 return new_page;
00298 }
00299
00300
00301
00302 static void
00303 pager_thread(void)
00304 {
00305 int res, rw_page_fault;
00306 l4_threadid_t src;
00307 l4_addr_t fault_address, fault_eip;
00308 l4_snd_fpage_t fp;
00309 l4_msgdope_t dope;
00310
00311
00312 res = l4_ipc_wait(&src,
00313 L4_IPC_SHORT_MSG,
00314 & fault_address,
00315 & fault_eip,
00316 L4_IPC_NEVER,
00317 &dope);
00318
00319 if(res)
00320 ipc_error("first PF", res);
00321
00322 while(1)
00323 {
00324 rw_page_fault = fault_address & 0x02;
00325 fault_address &= 0xfffffffc;
00326
00327
00328 if(debugpager)
00329 printf("[%s page fault in "l4util_idfmt" at %08lx (EIP %08lx) ",
00330 rw_page_fault ? "write" : "read",
00331 l4util_idstr(src), fault_address, fault_eip);
00332
00333 if( (l4_addr_t) & _stext <= fault_address
00334 && ((l4_addr_t) & _etext > fault_address)
00335 && !rw_page_fault)
00336 {
00337 if(debugpager)
00338 printf("Code\n");
00339 fp.fpage = l4_fpage(fault_address, L4_LOG2_PAGESIZE,
00340 L4_FPAGE_RO, L4_FPAGE_MAP);
00341 fp.snd_base = l4_trunc_page(fault_address);
00342 }
00343
00344 else if((l4_addr_t) & _etext <= fault_address
00345 && ((l4_addr_t) & _end > fault_address+3))
00346 {
00347 l4_addr_t new_page;
00348 if(debugpager)
00349 printf("Data\n");
00350
00351 if (rw_page_fault)
00352 {
00353 new_page = unshare_data(fault_address, src);
00354 fp.fpage = l4_fpage(new_page, L4_LOG2_PAGESIZE,
00355 L4_FPAGE_RW, L4_FPAGE_MAP);
00356 l4_fpage_unmap(l4_fpage(l4_trunc_page(fault_address),
00357 L4_LOG2_PAGESIZE, 0, 0),
00358 L4_FP_FLUSH_PAGE | L4_FP_OTHER_SPACES);
00359 }
00360 else
00361 {
00362 new_page = l4_trunc_page(fault_address);
00363 fp.fpage = l4_fpage(new_page, L4_LOG2_PAGESIZE,
00364 L4_FPAGE_RO, L4_FPAGE_MAP);
00365 }
00366
00367 fp.snd_base = l4_trunc_page(fault_address);
00368 }
00369
00370
00371 else
00372 {
00373 if(!debugpager)
00374 printf("[%s page fault in "l4util_idfmt" at %08lx (EIP %08lx) ",
00375 rw_page_fault ? "write" : "read",
00376 l4util_idstr(src), fault_address, fault_eip);
00377 printf("stop pager]\n");
00378 enter_kdebug("stop");
00379 fp.snd_base = 0;
00380 l4_ipc_sleep(L4_IPC_NEVER);
00381 }
00382
00383 if(debugpager)
00384 printf(" %s (%s), base : %08x, size : %d, offset : %08lx]\n",
00385 fp.fpage.fp.grant ? "grant" : "map",
00386 fp.fpage.fp.write ? "WR" : "RO",
00387 fp.fpage.fp.page << L4_PAGESHIFT,
00388 fp.fpage.fp.size,
00389 fp.snd_base
00390 );
00391
00392
00393 res = l4_ipc_reply_and_wait
00394 (src,
00395 L4_IPC_SHORT_FPAGE,
00396 fp.snd_base,
00397 fp.fpage.fpage ,
00398 &src,
00399 L4_IPC_SHORT_MSG,
00400 &fault_address,
00401 &fault_eip,
00402 L4_IPC_NEVER,
00403 &dope);
00404
00405 if(res)
00406 ipc_error("PF", res);
00407 }
00408 }
00409
00410
00411 static void
00412 print_event(l4events_ch_t event_ch, l4events_event_t *event)
00413 {
00414 printf("event_ch: %d\n", event_ch);
00415 printf("event: ");
00416 printf(event->str);
00417 printf("\n");
00418
00419 return;
00420 }
00421
00422 static void
00423 otask1(void)
00424 {
00425 l4events_ch_t event_ch = L4EVENTS_NO_CHANNEL;
00426 l4events_nr_t event_nr = L4EVENTS_NO_NR;
00427 l4events_event_t event;
00428 int res;
00429
00430
00431
00432 strcpy(LOG_tag, "task1");
00433
00434 printf("start.\n");
00435
00436 printf("register.\n");
00437 l4events_register(DEMO2_EVENTID, DEMO2_PRIORITY);
00438
00439 printf("receive first try.\n");
00440 res = l4events_receive(&event_ch, &event, &event_nr,
00441 l4_ipc_timeout(0,0,1,0), 0);
00442
00443 if (res == L4EVENTS_OK)
00444 {
00445 printf("receive event successful!\n");
00446
00447 print_event(event_ch, &event);
00448 }
00449 else
00450 {
00451 printf("receive event failed!\n");
00452 }
00453
00454 sit_and_wait(7);
00455
00456 printf("receive second try.\n");
00457 event_ch = L4EVENTS_NO_CHANNEL;
00458 res = l4events_receive(&event_ch, &event, &event_nr,
00459 L4_IPC_NEVER, 0);
00460
00461 if (res == L4EVENTS_OK)
00462 {
00463 printf("receive event successful!\n");
00464 print_event(event_ch, &event);
00465 }
00466 else
00467 {
00468 printf("receive event failed!\n");
00469 }
00470
00471 printf("unregister.\n");
00472 l4events_unregister(DEMO2_EVENTID);
00473
00474 printf("stop.\n");
00475
00476 wait_forever();
00477 }
00478
00479
00480 static void
00481 otask2(void)
00482 {
00483 l4events_event_t e;
00484 l4events_nr_t nr;
00485
00486 strcpy(e.str, "ein kleiner text.");
00487 e.len = strlen(e.str)+1;
00488
00489 strcpy(LOG_tag, "task2");
00490
00491 printf("start.\n");
00492
00493 sit_and_wait(8);
00494
00495 printf("send event.\n");
00496
00497 l4events_send(DEMO2_EVENTID, &e, &nr, 0);
00498
00499 printf("stop.\n");
00500
00501 wait_forever();
00502 }
00503
00504
00505 static void
00506 callback(l4events_ch_t event_ch, l4events_event_t *event)
00507 {
00508 print_event(event_ch, event);
00509 }
00510
00511 static void
00512 otask3(void)
00513 {
00514 strcpy(LOG_tag, "task3");
00515
00516 printf("start.\n");
00517
00518 l4events_register(DEMO2_EVENTID, DEMO2_PRIORITY);
00519 l4events_wait(1, L4EVENTS_NO_CHANNEL, callback);
00520
00521 printf("end...\n");
00522
00523 wait_forever();
00524 }
00525
00526
00527
00528 static void
00529 save_data(l4_threadid_t pager)
00530 {
00531 l4_addr_t beg = l4_trunc_page(&_etext);
00532 l4_addr_t end = l4_round_page(&_end);
00533
00534 my_program_data_copy = rmgr_reserve_mem(end-beg, L4_LOG2_PAGESIZE, 0, 0, 0);
00535 if (my_program_data_copy == ~0U)
00536 {
00537 printf("Cannot allocate %ldkB memory for unsharing data section\n",
00538 (end-beg)/1024);
00539 enter_kdebug("out of memory");
00540 }
00541
00542 l4sigma0_map_mem(pager,
00543 my_program_data_copy, my_program_data_copy, end-beg);
00544 memcpy((void*)my_program_data_copy, (void*)&_etext, &_end-&_etext);
00545 }
00546
00547
00548 static void
00549 reserve_cow(l4_threadid_t pager)
00550 {
00551 cow_pool = rmgr_reserve_mem(COW_POOL_PAGES*L4_PAGESIZE,
00552 L4_LOG2_PAGESIZE, 0, 0, 0);
00553 if (cow_pool == ~0U)
00554 {
00555 printf("Cannot allocate %dkB memory for cow pool!\n",
00556 COW_POOL_PAGES*L4_PAGESIZE/1024);
00557 enter_kdebug("out of memory");
00558 }
00559
00560 l4sigma0_map_mem(pager,
00561 (l4_addr_t)&_stext, (l4_addr_t)&_stext, &_etext-&_stext);
00562 l4sigma0_map_mem(pager,
00563 cow_pool, cow_pool, COW_POOL_PAGES*L4_PAGESIZE);
00564 cow_pages = COW_POOL_PAGES;
00565 }
00566
00567
00568 int
00569 main(void)
00570 {
00571 l4_threadid_t my_id, my_preempter, my_pager, new_pager;
00572
00573 l4_umword_t ignore;
00574 l4_threadid_t t, new_t;
00575
00576 int tasks;
00577
00578 rmgr_init();
00579
00580 l4events_init();
00581
00582
00583
00584 names_register("eventdemo");
00585
00586 get_thread_ids(&my_id,&my_preempter,&my_pager,NULL);
00587
00588
00589 save_data(my_pager);
00590 reserve_cow(my_pager);
00591
00592 printf("starting event server demo...\n");
00593
00594
00595 tasks = get_tasks();
00596
00597 if (tasks < TASK_MAX)
00598 {
00599 printf("got not enough tasks!!!");
00600 enter_kdebug("main");
00601 }
00602
00603
00604 get_thread_ids(&my_id,&my_preempter,&my_pager,NULL);
00605 pager_thread_id = my_id;
00606 pager_thread_id.id.lthread = PAGER_THREAD;
00607 my_preempter = L4_INVALID_ID;
00608 new_pager = my_pager;
00609 l4_thread_ex_regs( pager_thread_id,
00610 (l4_umword_t)pager_thread,
00611 (l4_umword_t)pager_thread_stack + 2048,
00612
00613 &my_preempter,
00614 &new_pager,
00615 &ignore,
00616 &ignore,
00617 &ignore
00618 );
00619
00620
00621 get_thread_ids(&t,NULL,NULL,NULL);
00622
00623 t.id.task = task_min;
00624 t.id.lthread = 0;
00625
00626 printf("start task1\n");
00627
00628 new_t = l4_task_new(t,
00629 255,
00630 (l4_umword_t)&crt0_stack_high,
00631 (l4_umword_t)otask1,
00632 pager_thread_id );
00633
00634 t.id.task = task_min+1;
00635 t.id.lthread = 0;
00636
00637 printf("start task2\n");
00638
00639 new_t = l4_task_new(t,
00640 255,
00641 (l4_umword_t)&crt0_stack_high,
00642 (l4_umword_t)otask2,
00643 pager_thread_id );
00644
00645
00646 t.id.task = task_min+2;
00647 t.id.lthread = 0;
00648
00649 printf("start task3\n");
00650
00651 new_t = l4_task_new(t,
00652 255,
00653 (l4_umword_t)&crt0_stack_high,
00654 (l4_umword_t)otask3,
00655 pager_thread_id );
00656
00657
00658
00659 l4_ipc_sleep(L4_IPC_NEVER);
00660
00661 return 0;
00662 }
00663