static void *simuart_thread(void *arg) { unsigned char ch; ssize_t nread; int next; int prev; /* Now loop, collecting a buffering data from stdin forever */ for (;;) { /* Read one character from stdin */ nread = read(0, &ch, 1); /* Check for failures (but don't do anything) */ if (nread == 1) { #ifdef CONFIG_SIM_UART_DATAPOST sched_lock(); #endif /* Get the index to the next slot in the UART buffer */ prev = g_uarthead; next = prev + 1; if (next >= SIMUART_BUFSIZE) { next = 0; } /* Would adding this character cause an overflow? */ if (next != g_uarttail) { /* No.. Add the character to the UART buffer */ g_uartbuffer[prev] = ch; /* Update the head index (BEFORE posting) */ g_uarthead = next; /* Was the buffer previously empty? */ if (prev == g_uarttail) { /* Yes.. signal any (NuttX) threads waiting for serial * input. */ #ifdef CONFIG_SIM_UART_DATAPOST simuart_post(); #else g_uart_data_available = 1; #endif } } #ifdef CONFIG_SIM_UART_DATAPOST /* REVISIT: This is very weird and scary here. When sched_unlock() * is called, we may do a lonjmp() style context switch meaning * that the logic will be run running on this thread! (but with a * different stack). So we do not get back here until the task * sleeps again. I can't help but believe that that is going to * be a problem someday. */ sched_unlock(); #endif } } return NULL; }
void up_idle(void) { #ifdef CONFIG_SMP /* In the SMP configuration, only one CPU should do these operations. It * should not matter which, however. */ static volatile spinlock_t lock; /* The one that gets the lock is the one that executes the IDLE operations */ if (up_testset(&lock) != SP_UNLOCKED) { /* We didn't get it... Give other pthreads/CPUs a shot and try again * later. */ pthread_yield(); return; } #endif #ifdef CONFIG_SCHED_TICKLESS /* Driver the simulated interval timer */ up_timer_update(); #else /* If the system is idle, then process "fake" timer interrupts. * Hopefully, something will wake up. */ sched_process_timer(); #endif #if defined(CONFIG_DEV_CONSOLE) && !defined(CONFIG_SIM_UART_DATAPOST) /* Handle UART data availability */ if (g_uart_data_available) { g_uart_data_available = 0; simuart_post(); } #endif #ifdef CONFIG_NET_ETHERNET /* Run the network if enabled */ netdriver_loop(); #endif #ifdef CONFIG_PM /* Fake some power management stuff for testing purposes */ { static enum pm_state_e state = PM_NORMAL; enum pm_state_e newstate; newstate = pm_checkstate(); if (newstate != state) { if (pm_changestate(newstate) == OK) { state = newstate; } } } #endif #if defined(CONFIG_SIM_WALLTIME) || defined(CONFIG_SIM_X11FB) /* Wait a bit so that the sched_process_timer() is called close to the * correct rate. */ (void)up_hostusleep(1000000 / CLK_TCK); /* Handle X11-related events */ #ifdef CONFIG_SIM_X11FB if (g_x11initialized) { #if defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK) /* Drive the X11 event loop */ if (g_eventloop) { up_x11events(); } #endif /* Update the display periodically */ g_x11refresh += 1000000 / CLK_TCK; if (g_x11refresh > 500000) { up_x11update(); } } #endif #endif #ifdef CONFIG_SMP /* Release the spinlock */ lock = SP_UNLOCKED; /* Give other pthreads/CPUs a shot */ pthread_yield(); #endif }