// Low level input function. int os_inchar(uint8_t *buf, int maxlen, int32_t ms, int tb_change_cnt) { InbufPollResult result; if (event_is_pending()) { // Return pending event bytes return push_event_key(buf, maxlen); } if (ms >= 0) { if ((result = inbuf_poll(ms)) == kInputNone) { return 0; } } else { if ((result = inbuf_poll(p_ut)) == kInputNone) { if (trigger_cursorhold() && maxlen >= 3 && !typebuf_changed(tb_change_cnt)) { buf[0] = K_SPECIAL; buf[1] = KS_EXTRA; buf[2] = KE_CURSORHOLD; return 3; } before_blocking(); result = inbuf_poll(-1); } } // If there are pending events, return the keys directly if (event_is_pending()) { return push_event_key(buf, maxlen); } // If input was put directly in typeahead buffer bail out here. if (typebuf_changed(tb_change_cnt)) { return 0; } if (result == kInputEof) { read_error_exit(); return 0; } return read_from_input_buf(buf, (int64_t)maxlen); }
// Wait for some event bool event_poll(int32_t ms) { bool timed_out; uv_run_mode run_mode = UV_RUN_ONCE; if (input_ready()) { // If there's a pending input event to be consumed, do it now return true; } input_start(); timed_out = false; if (ms > 0) { // Timeout passed as argument to the timer timer.data = &timed_out; // We only start the timer after the loop is running, for that we // use an prepare handle(pass the interval as data to it) timer_prepare.data = &ms; uv_prepare_start(&timer_prepare, timer_prepare_cb); } else if (ms == 0) { // For ms == 0, we need to do a non-blocking event poll by // setting the run mode to UV_RUN_NOWAIT. run_mode = UV_RUN_NOWAIT; } do { // Run one event loop iteration, blocking for events if run_mode is // UV_RUN_ONCE uv_run(uv_default_loop(), run_mode); } while ( // Continue running if ... !input_ready() && // we have no input kl_empty(event_queue) && // no events are waiting to be processed run_mode != UV_RUN_NOWAIT && // ms != 0 !timed_out); // we didn't get a timeout input_stop(); if (ms > 0) { // Stop the timer uv_timer_stop(&timer); } return input_ready() || event_is_pending(); }
PHP_METHOD(PeriodicEvent, again) { /* TODO: Optional EventLoop parameter? */ event_object *event_obj = (event_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if(event_has_loop(event_obj)) { event_periodic_again(event_obj); if( ! event_is_active(event_obj) && ! event_is_pending(event_obj)) { /* No longer referenced by libev, so remove GC protection */ IF_DEBUG(libev_printf("ev_periodic_again() stopped non-repeating timer\n")); EVENT_LOOP_REF_DEL(event_obj); } RETURN_BOOL(1); } /* TODO: Throw exception */ RETURN_BOOL(0); }
/** * Feeds the given event set into the event loop, as if the specified event * had happened for the specified watcher. * * The watcher will be GC protected until it has fired or clearPending is called * on it (unless you feed it again in the callback or add() it to an event loop * it won't accidentally be freed). * * NOTE: As of libev 4.0.4; If you feed an event in the callback of a fed event, * the newly fed event will be invoked before any other events (except other * fed events). So do NOT create loops by re-feeding an event into the EventLoop * as that loop will block just as much as a normal loop. * * TODO: Add note about AsyncEvent when AsyncEvent is implemented * * @param Event * @return boolean false if either the EventLoop or Event has not been initialized */ PHP_METHOD(EventLoop, feedEvent) { int revents = 0; zval *event_obj; event_object *event; event_loop_object *loop_obj = (event_loop_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &event_obj, event_ce, &revents) != SUCCESS) { return; } event = (event_object *)zend_object_store_get_object(event_obj TSRMLS_CC); assert(loop_obj->loop); /* Only allow Events which are associated with this EventLoop or those which are not associated with any EventLoop yet */ if(loop_obj->loop && ( ! event_has_loop(event) || event_in_loop(loop_obj, event))) { IF_DEBUG(libev_printf("Feeding event with pending %d and active %d...", event_is_pending(event), event_is_active(event))); /* The event might already have a loop, no need to increase refcount */ if( ! event_has_loop(event)) { EVENT_LOOP_REF_ADD(event, loop_obj); } event_feed_event(loop_obj, event, revents); IF_DEBUG(php_printf(" done\n")); RETURN_BOOL(1); } RETURN_BOOL(0); }
/** * Returns true if the event watcher is pending (ie. it has outstanding events but * the callback has not been called yet). * * @return boolean * @return null If object has not been initialized */ PHP_METHOD(Event, isPending) { event_object *obj = (event_object *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_BOOL(event_is_pending(obj)); }
void* thread_idle(void *arg) { extern uint_t __ktext_start; register uint_t id; register uint_t cpu_nr; register struct thread_s *this; register struct cpu_s *cpu; struct thread_s *thread; register struct page_s *reserved_pg; register uint_t reserved; kthread_args_t *args; bool_t isBSCPU; uint_t tm_now; uint_t count; error_t err; this = current_thread; cpu = current_cpu; id = cpu->gid; cpu_nr = arch_onln_cpu_nr(); args = (kthread_args_t*) arg; isBSCPU = (cpu == cpu->cluster->bscpu); cpu_trace_write(cpu, thread_idle_func); if(isBSCPU) pmm_tlb_flush_vaddr((vma_t)&__ktext_start, PMM_UNKNOWN); cpu_set_state(cpu, CPU_ACTIVE); rt_timer_read(&tm_now); this->info.tm_born = tm_now; this->info.tm_tmp = tm_now; //// Reset stats /// cpu_time_reset(cpu); //////////////////// mcs_barrier_wait(&boot_sync); printk(INFO, "INFO: Starting Thread Idle On Core %d\tOK\n", cpu->gid); if(isBSCPU && (id == args->val[2])) { for(reserved = args->val[0]; reserved < args->val[1]; reserved += PMM_PAGE_SIZE) { reserved_pg = ppm_ppn2page(&cpu->cluster->ppm, reserved >> PMM_PAGE_SHIFT); page_state_set(reserved_pg, PGINIT); ppm_free_pages(reserved_pg); } } thread = kthread_create(this->task, &thread_event_manager, NULL, cpu->cluster->id, cpu->lid); if(thread == NULL) PANIC("Failed to create default events handler Thread for CPU %d\n", id); thread->task = this->task; cpu->event_mgr = thread; wait_queue_init(&thread->info.wait_queue, "Events"); err = sched_register(thread); assert(err == 0); sched_add_created(thread); if(isBSCPU) { dqdt_update(); #if 0 thread = kthread_create(this->task, &cluster_manager_thread, cpu->cluster, cpu->cluster->id, cpu->lid); if(thread == NULL) { PANIC("Failed to create cluster manager thread, cid %d, cpu %d\n", cpu->cluster->id, cpu->gid); } thread->task = this->task; cpu->cluster->manager = thread; wait_queue_init(&thread->info.wait_queue, "Cluster-Mgr"); err = sched_register(thread); assert(err == 0); sched_add_created(thread); #endif if(clusters_tbl[cpu->cluster->id].flags & CLUSTER_IO) { thread = kthread_create(this->task, &kvfsd, NULL, cpu->cluster->id, cpu->lid); if(thread == NULL) { PANIC("Failed to create KVFSD on cluster %d, cpu %d\n", cpu->cluster->id, cpu->gid); } thread->task = this->task; wait_queue_init(&thread->info.wait_queue, "KVFSD"); err = sched_register(thread); assert(err == 0); sched_add_created(thread); printk(INFO,"INFO: kvfsd has been created\n"); } } cpu_set_state(cpu,CPU_IDLE); while (true) { cpu_disable_all_irq(NULL); if((event_is_pending(&cpu->re_listner)) || (event_is_pending(&cpu->le_listner))) { wakeup_one(&cpu->event_mgr->info.wait_queue, WAIT_ANY); } sched_idle(this); count = sched_runnable_count(&cpu->scheduler); cpu_enable_all_irq(NULL); if(count != 0) sched_yield(this); //arch_set_power_state(cpu, ARCH_PWR_IDLE); } return NULL; }