Introduction   Client Library API Reference   Demo1   Demo2   Demo3   File List   Index  

main.c

00001 
00009 /* (c) 2003 Technische Universitaet Dresden
00010  * This file is part of DROPS, which is distributed under the terms of the
00011  * GNU General Public License 2. Please see the COPYING file for details.
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 /* the virtual address range of this program */
00038 extern char _end, _stext, _etext, __bss_start;
00039 
00040 /* debug variables, set to nonzero to get more output */
00041 static const int debug_pager = 0; /* debug page faults */
00042 static const int debug_send = 0;  /* debug send operation */
00043 static const int debug_recv = 0;  /* debug receive operation */
00044 
00046 #define SEND_TASK_COUNT   1
00047 
00048 #define RECV_TASK_COUNT   1
00049 /* total number of required tasks */
00050 #define TASK_COUNT    (SEND_TASK_COUNT + RECV_TASK_COUNT)
00051 
00052 #define SEND_EVENT_COUNT  100
00053 /* this is the number of events received per task */
00054 #define RECV_EVENT_COUNT  (SEND_EVENT_COUNT * SEND_TASK_COUNT)
00055 
00056 /* time benchmark, set to nonzero to enable time measurement */
00057 static const int timebenchmark = 1;
00058 
00060 #define PINGPONG_IPC  5000
00061 
00062 /* event_ch used for this demo */
00063 #define DEMO3_EVENTID   10
00064 /* priority used for this demo */
00065 #define DEMO3_PRIORITY    0
00066 
00067 /* region of acquired task numbers, get initialised in get_tasks */
00068 static int task_min = -1;
00069 static int task_max = -1;
00070 
00071 /* pager thread variables */
00072 #define PAGER_THREAD 1  /* thread number definition */
00073 static l4_threadid_t pager_thread_id = L4_INVALID_ID; /* thread id */
00074 char pager_thread_stack[2048]; /* stack */
00075 
00076 
00077 /* varaiables for COW mechanism */
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 /* data structure for communication, should not be unshared*/
00087 typedef volatile struct
00088 {
00089   l4_uint32_t   start_tsc;  /* start time for benchmark */
00090   l4_uint32_t nr_pagefaults;  /* pagefault counter */
00091   int           recv_task_min;  /* minimal recv_task_id */
00092   int   send_task_min;  /* minimal send_task_id */
00093   l4_threadid_t main_thread_id; /* main thread_id */
00094 } shared_data_t;
00095 
00096 /* shared datas */
00097 static shared_data_t *shared_data = 0;
00098 
00099 
00100 /* nicely report ipc errors */
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 /* get thread number, preempter, pager, and ESP of calling thread */
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,       /* id, EIP, ESP */
00175          &_my_preempter,       /* preempter */
00176          &_my_pager,       /* pager */
00177          &ignore,        /* flags */
00178          &ignore,        /* old ip */
00179          &_esp         /* old sp */
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 /* get the apropriate number of task ids */
00190 static int
00191 get_tasks(void)
00192 {
00193   int res, task;
00194   int got_flag = 0;
00195   int count = 0;
00196 
00197   /* use the rmgr library now */
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 /* copy-on-write mechanism: allocate a new page and copy appropriate content
00238  of data into new page */
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   /* bss is located at &__bss_start ... &_end-1 */
00259   if (!(   (img_base+L4_PAGESIZE <= data_start)
00260         || (img_base             >= data_end)))
00261     {
00262       /* some space of the page we want to give out
00263        * is bss -- clear it! */
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   /* get first page fault */
00331   res = l4_ipc_wait(&src,      /* source */
00332        L4_IPC_SHORT_MSG,   /* rcv desc */
00333        & fault_address,
00334        & fault_eip,    /* data */
00335        L4_IPC_NEVER,     /* timeout */
00336        &dope);     /* 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       // do not lock in pager, because this gives dead locks
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         /* in Code */
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         /* in Data/Bss? */
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         /* in Stack ? */
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       /* send reply and wait for next page fault */
00427       res = l4_ipc_reply_and_wait
00428   (src,          /* destination */
00429    L4_IPC_SHORT_FPAGE,       /* snd desc */
00430    fp.snd_base,        /* snd data 0 */
00431    fp.fpage.fpage ,      /* snd data 1 */
00432    &src,           /* source */
00433    L4_IPC_SHORT_MSG,       /* rcv desc */
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]; // this must be static!!!
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   /* make sure that we don't get any page faults on code and stack
00470      sections and shared pages while benchmarking */
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   /* give 'feedback' to main task */
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   /* wait for main task to start */
00485   l4_ipc_receive(shared_data->main_thread_id,
00486      0, &ignore, &ignore, L4_IPC_NEVER, &dope);
00487 
00488 
00489   /* loop for receiving events */
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   /* make sure, only the first task reports benchmark result */
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   /* wait forever */
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   /* make sure that we don't get any page faults on code and stack sections
00554      while benchmarking */
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   /* prepare a very short event */
00560   strcpy(event.str, "hi");
00561   event.len = strlen(event.str)+1;
00562 
00563   /* send loop */
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   /* giving feedback to the main task
00587      that receive tasks can be started */
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   /* wait forever */
00593   l4_ipc_sleep(L4_IPC_NEVER);
00594 
00595   return;
00596 }
00597 
00598 /* these are some utility functions for memeory management */
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   /* initialize the resource manager */
00669   rmgr_init();
00670 
00671   /* initialize the events server */
00672   l4events_init();
00673 
00674   /* initialize the the names library
00675      -- must be done before save_data()! */
00676   names_register("eventdemo");
00677 
00678   get_thread_ids(&my_id, &my_preempter, &my_pager, NULL);
00679   
00680   /* initialize the memory management system */
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   /* get self task id */
00688   t = l4_myself();
00689 
00690   /* get the task apropriate number of tasks */
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   /* start pager thread */
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,    /* dest thread */
00708          (l4_umword_t)pager_thread,  /* EIP */
00709          (l4_umword_t)pager_thread_stack + 2048,
00710              /* ESP */
00711          &my_preempter,    /* preempter */
00712          &new_pager,     /* pager */
00713          &ignore,      /* flags */
00714          &ignore,      /* old ip */
00715          &ignore       /* old sp */
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   /* start receive tasks */
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   /* start send tasks */
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   /* reset pagefault counter */
00776   shared_data->nr_pagefaults = 0;
00777   /* set the start time */
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   /* wait forever */
00792   l4_ipc_sleep(L4_IPC_NEVER);
00793 
00794   return 0;
00795 }
00796 

Events Reference Manual, written by Torsten Frenzel  © 2003