// FIXME: Pass a list of 'resources' rather than a single address+irq number, which may // not always be sufficient. static void scan_devices(void) { CORBA_Environment env; L4_ThreadId_t me = L4_Myself(); thread_ref_t server_; cap_t device; /* timer device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VTIMER_SERVER")), &server_); timer_server = thread_l4tid(server_); device_add_resource(timer_server, 0x40a00000,0, MEMORY_RESOURCE, &env); device_add_resource(timer_server, 27,0, INTERRUPT_RESOURCE, &env); device_add_resource(timer_server, 28,0, INTERRUPT_RESOURCE, &env); device = device_create(timer_server, &me, TIMER, &env); timer_device = device.ref.obj; /* rtc device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VRTC_SERVER")), &server_); rtc_server = thread_l4tid(server_); device_add_resource(rtc_server, RTC_PHYS, 0, MEMORY_RESOURCE, &env); device_add_resource(rtc_server, INT_RTC, 0, INTERRUPT_RESOURCE, &env); device = device_create(rtc_server, &me, RTC, &env); rtc_device = device.ref.obj; /* serial device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VSERIAL_SERVER")), &server_); serial_server = thread_l4tid(server_); device_add_resource(serial_server, 0x40100000,0, MEMORY_RESOURCE, &env); device_add_resource(serial_server, 22,0, INTERRUPT_RESOURCE, &env); device = device_create(serial_server, &me, UART1, &env); serial_device = device.ref.obj; #if 0 /* serial device */ memsection_lookup(iguana_getenv(IGUANA_GETENV_VBUS_SERVER), &server_); bus_server = thread_l4tid(server_); device_add_resource(bus_server, 101,0, INTERRUPT_RESOURCE, &env); device = device_create(bus_server, &me, BUS, &env); bus_device = device.ref.obj; DEBUG_TRACE(2, "looking for LCD device\n"); cap_t virtual_bus = virtual_bus_factory_create(bus_server, bus_device, &lcd_server, 0, NULL); /* LCD device */ memsection_lookup(iguana_getenv(IGUANA_GETENV_VLCD_SERVER), &server_); lcd_server = thread_l4tid(server_); device_add_resource(lcd_server, bus_server.raw, virtual_bus.ref.obj, BUS_RESOURCE, &env); device_add_resource(lcd_server, bus_server.raw, virtual_bus.ref.obj, BUS_RESOURCE, &env); device_add_resource(lcd_server, 101,0, INTERRUPT_RESOURCE, &env); device = device_create(lcd_server, &me, LCD, &env); lcd_device = device.ref.obj; #endif // And any other devices you care to add ... }
int main(int argc, char **argv) { struct driver_ops *ops; objref_t obj; /* * XXX: Should we be inserting the timer device into naming here? */ main_tid = thread_l4tid(env_thread(iguana_getenv("MAIN"))); obj = device_create_impl(main_tid, 0UL, NULL); naming_insert("timer", obj); ops = TIMER_DRIVER.ops.d_ops; iguana_cb_handle = cb_attach(__callback_buffer); #ifdef ENABLE_PM_THREAD { L4_ThreadId_t unused; pm_thread = thread_create_priority(1, &unused); L4_KDB_SetThreadName(unused, "PwrMgmt"); } #endif L4_Accept(L4_AsynchItemsAcceptor); L4_Set_NotifyMask(1UL << 31); timer_server_loop(); assert(!"Should reach here\n"); return 0; }
thread_ref_t thread_create_smt(void (*fn) (void *), void * arg, int priority, L4_Word_t hw_thread_bitmask) { void **stack_top; L4_ThreadId_t ignore; thread_ref_t thread; memsection_ref_t memref; L4_Word_t dummy; #define STACK_SIZE 0x1000 memref = memsection_create(STACK_SIZE, (void*) &stack_top); if (memref == 0) return 0; stack_top = (void**) ((uintptr_t) stack_top + STACK_SIZE); stack_top--; *stack_top = (void *) fn; stack_top--; *stack_top = arg; thread = thread_create_priority(priority, &ignore); L4_Schedule(thread_l4tid(thread), ~0UL, hw_thread_bitmask, ~0UL, ~0UL, 0, &dummy); thread_start(thread, (uintptr_t) __thread_stub, (uintptr_t)stack_top); return thread; }
int _session_create(objref_t object, clist_ref_t clist, L4_ThreadId_t *server_tid, struct session *session) { cap_t cap; thread_ref_t server; memsection_ref_t memsection; if (object == 0 || object == INVALID_ADDR) { return -1; } /* Find memsection */ memsection = memsection_lookup(object, &server); if (memsection == 0 || memsection == INVALID_ADDR) { return -1; } /* TODO: Search for existing session with that server */ cap = iguana_pd_create_session(IGUANA_PAGER, pd_myself(), thread_myself(), server, clist, default_clist, NULL); if (cap.ref.session == 0) { return -1; } *server_tid = thread_l4tid(server); session->ref = cap.ref.session; session->clist = clist; session->own_clist = 0; return 0; }
/* * Delete threads created by create_filler_threads. */ void delete_filler_threads(void) { while (allocated_threads > 0) { thread_delete(thread_l4tid(threads[allocated_threads - 1])); allocated_threads--; } }
thread_ref_t create_thread(pd_ref_t pd, void (*start)(void), int priority, int wait) { uintptr_t stack_base; int r; memsection_ref_t stack; thread_ref_t thread; L4_ThreadId_t tid; thread = pd_create_thread_with_priority(pd, priority, &tid); if (thread == 0 || thread == -1) { printf("Failed to create thread.\n"); return -1; } stack = pd_create_memsection(pd, SIZE, &stack_base); if (stack == 0 || stack == -1) { printf("Failed to create stack.\n"); return -1; } r = pd_attach(pd, stack, L4_ReadWriteOnly); if (r != 0) { printf("Failed to attach stack.\n"); return -1; } thread_start(thread, (uintptr_t)start, stack_base + SIZE); /* * Block on the mutex if waiting. The other thread will unlock just * before faulting. */ if (wait) { L4_Receive(thread_l4tid(thread)); okl4_libmutex_lock(serialise_mutex); okl4_libmutex_unlock(serialise_mutex); /* * Wait a little longer for iguana server to print out the * page fault details. */ for (r = 0; r < 1000; r++) L4_Yield(); } return thread; }
int main(void) { main_tid = thread_l4tid(env_thread(iguana_getenv("MAIN"))); printf("\nKernel counter example\n"); printf("----------\n"); test01(); test02(); test03(); printf("Kernel counter example finished\n"); L4_KDB_Enter("done"); return 0; }
static void worker_a(void *ignore) { ARCH_THREAD_INIT memsection_ref_t m; uintptr_t base; int i; L4_KDB_SetThreadName(thread_l4tid(thread_myself()), "worker_a"); L4_Yield(); for (i = 0; i < 10000; i++) { m = pd_create_memsection(pd_myself(), 1UL << 31, &base); assert(m == 0); } worker_a_done = 1; L4_WaitForever(); }
static void worker_b(void *ignore) { ARCH_THREAD_INIT memsection_ref_t m; uintptr_t base; int i; char *p; L4_KDB_SetThreadName(thread_l4tid(thread_myself()), "worker_b"); L4_Yield(); for (i = 0; i < 1000; i++) { m = pd_create_memsection(pd_myself(), MEM_SIZE, &base); assert(m != 0); p = (char *)base; memset(p, '%', 0x10); memsection_delete(m); } worker_b_done = 1; L4_WaitForever(); }
int main(int argc, char **argv) { struct okl4_libmutex rm; L4_ThreadId_t tid; int i, max_iteration, eg_num, server_on; L4_Word_t me; L4_MsgTag_t tag = L4_Niltag; /*** Initialisation ***/ pi_main = thread_l4tid(env_thread(iguana_getenv("MAIN"))); me = pi_main.raw; eg_num = max_iteration = server_on = 0; if (argc == 3) { eg_num = atoi(argv[0]); max_iteration = atoi(argv[1]); server_on = atoi(argv[2]); } else { printf("(%s 0x%lx) Error: Argument(s) missing!\n", test_name, me); return 1; } resource_mutex = &rm; okl4_libmutex_init(resource_mutex); high_prio_thread = medium1_prio_thread = medium2_prio_thread = medium3_prio_thread = low_prio_thread = L4_nilthread; high_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_HIGH"))); medium3_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_INTERMEDIATE_2"))); medium2_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_MEDIUM"))); medium1_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_INTERMEDIATE_1"))); low_prio_thread = thread_l4tid(env_thread(iguana_getenv("MIXED_PI_LOW"))); // Tell other threads that it is safe to use libraries libs_ready = 1; if (!server_on) printf("Start %s test #%d(0x%lx)\n", test_name, eg_num, me); /*** Start test ***/ scenario1 = 1; for (i = 0; i < 2 * max_iteration; i++) { // Wait for threads to be ready tag = L4_Wait(&tid); // If one thread had a problem while initialisation, then stop the test and notify // server that the test is dead. if (L4_Label(tag) == 0xdead) { rtos_init(); test_died(test_name, eg_num); rtos_cleanup(); return 1; } // Tell high prio thread to start the next iteration. L4_LoadMR(0, 0); tag = L4_Send(high_prio_thread); stop_spinning = 0; // Wait for the iteration to finish. L4_Receive(high_prio_thread); stop_spinning = 1; // If end of iterations for scenario1, then report results to RTOS server if server is on. if (i == (max_iteration - 1)) { if (server_on) { rtos_init(); mixed_priority_inversion_results(eg_num, 1, max_iteration, cnt_h, cnt_m1, cnt_m2, cnt_l, cnt_i1, cnt_i2); } else print_metrics(max_iteration); // Start scenario2 cnt_h = cnt_m1 = cnt_m2 = cnt_l = cnt_i1 = cnt_i2 = 0; scenario1 = 0; scenario2 = 1; } } /*** Test finished ***/ thread_delete(medium1_prio_thread); thread_delete(medium3_prio_thread); thread_delete(high_prio_thread); thread_delete(medium2_prio_thread); thread_delete(low_prio_thread); /* Clean up allocated mutexes. */ okl4_libmutex_free(resource_mutex); // If RTOS server is on, report results to it. if (server_on) { mixed_priority_inversion_results(eg_num, 2, max_iteration, cnt_h, cnt_m1, cnt_m2, cnt_l, cnt_i1, cnt_i2); rtos_cleanup(); } else { print_metrics(max_iteration); printf("%s test #%d(0x%lx) finished\n", test_name, eg_num, me); } return 0; }
int main(int argc, char **argv) { int i, tmp, eg_num, nb_philosophers, nb_dinners, server_on; L4_ThreadId_t *philo_tids; L4_ThreadId_t tid, any_thread; L4_MsgTag_t tag = L4_Niltag; /*** Initialisation ***/ dp_main = thread_l4tid(env_thread(iguana_getenv("MAIN"))); eg_num = nb_philosophers = nb_dinners = server_on = 0; if (argc == 3) { eg_num = atoi(argv[0]); nb_philosophers = atoi(argv[1]); server_on = atoi(argv[2]); } else { printf("(%s 0x%lx) Error: Argument(s) missing!\n", test_name, dp_main.raw); return 1; } if (!server_on) printf("Start %s test #%d(0x%lx): %d philosophers\n", test_name, eg_num, dp_main.raw, nb_philosophers); chopstick = malloc((nb_philosophers + 1) * sizeof(okl4_libmutex_t)); philo_tids = malloc(nb_philosophers * sizeof(L4_ThreadId_t)); for (i = 0; i < nb_philosophers; i++) { chopstick[i] = malloc (sizeof(struct okl4_libmutex)); okl4_libmutex_init(chopstick[i]); } chopstick[nb_philosophers] = NULL; // Tell other threads that it is safe to use libraries and mutexes libs_ready = 1; // Retrieve philosophers thread Ids and give them a go for (i = 0; i < nb_philosophers; i++) { L4_Wait(&tid); philo_tids[i] = tid; } /*** Start test ***/ meal_served = 1; tmp = nb_philosophers; while (tmp) { tag = L4_Wait(&any_thread); for (i = 0; i < nb_philosophers; i++) { if (any_thread.raw == philo_tids[i].raw) { thread_delete(any_thread); tmp--; if (L4_Label(tag) == 0xfed) { // Philosopher finished eating nb_dinners++; } break; } } } /*** Test finished ***/ free(philo_tids); for (i = 0; i < nb_philosophers; i++) { okl4_libmutex_free(chopstick[i]); free(chopstick[i]); } //free(*chopstick); // If RTOS server is on, report results to it. if (server_on) { rtos_init(); dining_philosophers_results(eg_num, nb_philosophers, nb_dinners); rtos_cleanup(); } else printf("%s test #%d(0x%lx) finished\n", test_name, eg_num, dp_main.raw); return 0; }
// FIXME: Pass a list of 'resources' rather than a single address+irq number, which may // not always be sufficient. static void scan_devices(void) { CORBA_Environment env; L4_ThreadId_t me = L4_Myself(); thread_ref_t server_; cap_t device; /* timer device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VTIMER_SERVER")), &server_); timer_server = thread_l4tid(server_); device_add_resource(timer_server, TIMER2_PHYS, 0, MEMORY_RESOURCE, &env); /* XXX only use timer2 */ device_add_resource(timer_server, INT_TIMER2, 0, INTERRUPT_RESOURCE, &env); device = device_create(timer_server, &me, TIMER, &env); timer_device = device.ref.obj; #if 0 // andy - 4 /* rtc device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VRTC_SERVER")), &server_); rtc_server = thread_l4tid(server_); device_add_resource(rtc_server, RTC_PHYS, 0, MEMORY_RESOURCE, &env); device_add_resource(rtc_server, INT_RTC, 0, INTERRUPT_RESOURCE, &env); device = device_create(rtc_server, &me, RTC, &env); rtc_device = device.ref.obj; #endif // andy - 4 /* This is an example of how to setup a software rtc. */ #if 0 memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VRTC_SERVER")), &server_); rtc_server = thread_l4tid(server_); /* Create virtual timer and pass to rtc_device as a resource.*/ cap_t virtual_timer = virtual_timer_factory_create(timer_server, timer_device, &rtc_server, 0x3, NULL); device_add_resource(rtc_server, timer_server.raw, virtual_timer.ref.obj, TIMER_RESOURCE, &env); device = device_create(rtc_server, &me, RTC, &env); rtc_device = device.ref.obj; #endif /* serial device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VSERIAL_SERVER")), &server_); serial_server = thread_l4tid(server_); device_add_resource(serial_server, UART1_PHYS, 0, MEMORY_RESOURCE, &env); device_add_resource(serial_server, INT_UART1, 0, INTERRUPT_RESOURCE, &env); device = device_create(serial_server, &me, UART, &env); serial_device = device.ref.obj; #if 0 // andy - 5 /* touchscreen device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VTOUCH_SERVER")), &server_); ts_server = thread_l4tid(server_); device_add_resource(ts_server, TS_PHYS, 0, MEMORY_RESOURCE, &env); device_add_resource(ts_server, INT_TC, 0, INTERRUPT_RESOURCE, &env); device_add_resource(ts_server, INT_ADC, 0, INTERRUPT_RESOURCE, &env); device = device_create(ts_server, &me, VTOUCH, &env); ts_device = device.ref.obj; /* spi device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VBUS_SERVER")), &server_); spi_server = thread_l4tid(server_); device_add_resource(spi_server, SPI_PHYS, 0, MEMORY_RESOURCE, &env); device_add_resource(spi_server, INT_SPI1, 0, INTERRUPT_RESOURCE, &env); device = device_create(spi_server, &me, SPI1, &env); spi_device = device.ref.obj; /* nand device */ memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VMTD_SERVER")), &server_); mtd_server = thread_l4tid(server_); device_add_resource(mtd_server, MTD_PHYS, 0, MEMORY_RESOURCE, &env); device = device_create(mtd_server, &me, NAND, &env); mtd_device = device.ref.obj; /* get a bus handle to provide to the lcd driver */ cap_t virtual_spi = virtual_bus_factory_create(spi_server, spi_device, &lcd_server, 0, NULL); #endif // andy - 5 /* lcd device */ // TEMP: REMOVED (jmatthews): causes NPE /* memsection_lookup((objref_t) env_memsection_base(iguana_getenv("OKL4_VLCD_SERVER")), */ /* &server_); */ /* lcd_server = thread_l4tid(server_); */ /* device_add_resource(lcd_server, LCD_PHYS, 0, MEMORY_RESOURCE, &env); */ /* //device_add_resource(lcd_server, spi_server.raw, virtual_spi.ref.obj, BUS_RESOURCE, &env); */ /* device_add_resource(lcd_server, spi_server.raw, 0, BUS_RESOURCE, &env); */ /* device_add_resource(lcd_server, INT_LCD, 0, INTERRUPT_RESOURCE, &env); */ /* device = device_create(lcd_server, &me, LCD, &env); */ /* lcd_device = device.ref.obj; */ // And any other devices you care to add ... return; }
static int __init ig_input_init(void) { /* Called when we are initialising the device */ void *buffer_area, *control_area, *input_dev; thread_ref_t server_; L4_ThreadId_t server; thread_ref_t dummy; CORBA_Environment env; memsection_ref_t memsect; uintptr_t base; int i, irq; /* Allocate space for the input structure */ ig_input = kmalloc(sizeof(*ig_input), GFP_KERNEL); input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL); buffer_area = kmalloc(BUFFER_SIZE, GFP_KERNEL); control_area = kmalloc(sizeof(struct control_block), GFP_KERNEL); if (!ig_input || !buffer_area || !control_area || !input_dev) { kfree(ig_input); kfree(buffer_area); kfree(control_area); kfree(input_dev); return -ENOMEM; } memset(ig_input, 0, sizeof(*ig_input)); memset(input_dev, 0, sizeof(struct input_dev)); memset(buffer_area, 0, BUFFER_SIZE); memset(control_area, 0, sizeof(struct control_block)); irq = iguana_alloc_irq(); printk("IG_KPP got IRQ %d\n", irq); /* First, we find the input device */ memsection_lookup(env_memsection_base(iguana_getenv("OKL4_CORE_DEVICE_SERVER")), &server_); server = thread_l4tid(server_); ig_input->dev = device_core_get_kpp(server, &ig_input->server, &timer_thread, IGUANA_IRQ_NOTIFY_MASK(irq), &env); /* Now, we add the kernel memory section to the server */ memsect = memsection_lookup((objref_t) buffer_area, &dummy); ig_input->memsect_base = base = (uintptr_t) memsection_base(memsect); virtual_kpp_add_memsection(ig_input->server, ig_input->dev, memsect, 0, &env); /* Initialise the control block */ ig_input->control = control_area; ig_input->control->rx = ~0; ig_input->rx_last = NULL; ig_input->free_list = buffer_area; for (i=0; i < BUFFER_SIZE / sizeof(struct stream_packet); i++) { ig_input->free_list[i].next = (uintptr_t) &ig_input->free_list[i+1]; ig_input->free_list[i].data_ptr = &ig_input->free_list[i].data; //vaddr_to_memsect(ig_input, &ig_input->free_list[i].data); } ig_input->free_list[i-1].next = 0; for (i = 0; i < BUFFER_SIZE / sizeof(struct stream_packet); i++) { struct stream_packet *packet; int new_q = 0; packet = ig_input->free_list; if (packet == NULL) { panic("Iguana input driver corrupted\n"); } ig_input->free_list = (void*) packet->next; packet->next = ~0; packet->size = PACKET_SIZE; packet->xferred = 0; packet->status = 0; if (ig_input->rx_last != NULL) { ig_input->rx_last->next = vaddr_to_memsect(ig_input, packet); if (ig_input->rx_last->status & TERMINATED) { new_q = 1; } } else { new_q = 1; } if (new_q) { ig_input->control->rx = vaddr_to_memsect(ig_input, packet); } ig_input->rx_last = packet; } /* Register the control block with the server */ virtual_kpp_register_control_block(ig_input->server, ig_input->dev, vaddr_to_memsect(ig_input, ig_input->control), &env); ig_input->input_dev = input_dev; ig_input->input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); set_bit(KEY_0, ig_input->input_dev->keybit); set_bit(KEY_1, ig_input->input_dev->keybit); set_bit(KEY_2, ig_input->input_dev->keybit); set_bit(KEY_3, ig_input->input_dev->keybit); set_bit(KEY_4, ig_input->input_dev->keybit); set_bit(KEY_5, ig_input->input_dev->keybit); set_bit(KEY_6, ig_input->input_dev->keybit); set_bit(KEY_7, ig_input->input_dev->keybit); set_bit(KEY_8, ig_input->input_dev->keybit); set_bit(KEY_9, ig_input->input_dev->keybit); set_bit(KEY_KPASTERISK, ig_input->input_dev->keybit); set_bit(KEY_CHAT, ig_input->input_dev->keybit); set_bit(KEY_F17, ig_input->input_dev->keybit); set_bit(KEY_F18, ig_input->input_dev->keybit); set_bit(KEY_F19, ig_input->input_dev->keybit); set_bit(KEY_F20, ig_input->input_dev->keybit); set_bit(KEY_F21, ig_input->input_dev->keybit); set_bit(KEY_END, ig_input->input_dev->keybit); set_bit(/*KEY_F22*/KEY_ENTER, ig_input->input_dev->keybit); set_bit(KEY_F23, ig_input->input_dev->keybit); set_bit(KEY_BACK, ig_input->input_dev->keybit); set_bit(KEY_UP, ig_input->input_dev->keybit); set_bit(KEY_DOWN, ig_input->input_dev->keybit); set_bit(KEY_LEFT, ig_input->input_dev->keybit); set_bit(KEY_RIGHT, ig_input->input_dev->keybit); set_bit(BTN_LEFT, ig_input->input_dev->keybit); set_bit(BTN_RIGHT, ig_input->input_dev->keybit); set_bit(REL_X, ig_input->input_dev->relbit); set_bit(REL_Y, ig_input->input_dev->relbit); //set_bit(KEY_CONNECT, ig_input->input_dev->keybit); //set_bit(KEY_FINANCE, ig_input->input_dev->keybit); set_bit(/*KEY_F13*/KEY_F1, ig_input->input_dev->keybit); set_bit(/*KEY_F14*/KEY_F2, ig_input->input_dev->keybit); set_bit(/*KEY_F15*/KEY_F3, ig_input->input_dev->keybit); set_bit(/*KEY_F16*/KEY_F4, ig_input->input_dev->keybit); set_bit(KEY_HOME, ig_input->input_dev->keybit); set_bit(KEY_POWER, ig_input->input_dev->keybit); set_bit(KEY_VOLUMEDOWN, ig_input->input_dev->keybit); set_bit(KEY_VOLUMEUP, ig_input->input_dev->keybit); set_bit(KEY_RECORD, ig_input->input_dev->keybit); ig_input->input_dev->name = "Iguana virtual input device"; request_irq(irq, ig_input_interrupt, 0, ig_input->input_dev->name, ig_input->input_dev); input_register_device(ig_input->input_dev); return 0; }
/* * Get current value, request timeout for different threads, check all notified * correctly. */ static void test02(void) { uint32_t cur_value; L4_Word_t result, i; thread_ref_t thread1, thread2, thread3; L4_ThreadId_t tid1, tid2, tid3, any_thread; L4_Word_t notifybits1 = 0x1; L4_Word_t notifybits2 = 0x2; L4_Word_t notifybits3 = 0x3; L4_MsgTag_t tag; L4_Word_t label; printf("%s: ", __func__); thread1 = thread_create_simple(waiting_notify_thread, NULL, 99); thread2 = thread_create_simple(waiting_notify_thread, NULL, 99); thread3 = thread_create_simple(waiting_notify_thread, NULL, 99); tid1 = thread_l4tid(thread1); tid2 = thread_l4tid(thread2); tid3 = thread_l4tid(thread3); tag = L4_Make_MsgTag(notifybits1, 0); L4_Set_MsgTag(tag); tag = L4_Call(tid1); tag = L4_Make_MsgTag(notifybits2, 0); L4_Set_MsgTag(tag); tag = L4_Call(tid2); tag = L4_Make_MsgTag(notifybits3, 0); L4_Set_MsgTag(tag); tag = L4_Call(tid3); result = counter_current_value(&cur_value); if (result == 0) { FAILED(); return; } result = counter_request(cur_value + 10, tid1, notifybits1); if (result == 0) { FAILED(); return; } result = counter_request(cur_value + 12, tid2, notifybits2); if (result == 0) { FAILED(); return; } result = counter_request(cur_value + 14, tid3, notifybits3); if (result == 0) { FAILED(); return; } for (i = 0; i < 3; i++) { tag = L4_Wait(&any_thread); label = L4_Label(tag); if (((i == 0) && (label != 0x1)) || ((i == 1) && (label != 0x2)) || ((i == 2) && (label != 0x3))) { thread_delete(tid1); thread_delete(tid2); thread_delete(tid3); FAILED(); return; } } thread_delete(tid1); thread_delete(tid2); thread_delete(tid3); PASSED(); }