/* the serial writer thread: */ static void _tme_posix_serial_th_writer(struct tme_posix_serial *serial) { tme_uint8_t buffer_output[1024]; unsigned int buffer_output_size; int rc; /* lock the mutex: */ tme_mutex_lock(&serial->tme_posix_serial_mutex); /* loop forever: */ for (;;) { /* if there is no data to write, wait on the writer condition, after which there must be data to write: */ if (tme_serial_buffer_is_empty(&serial->tme_posix_serial_buffer_out)) { tme_cond_wait_yield(&serial->tme_posix_serial_cond_writer, &serial->tme_posix_serial_mutex); } /* get the data to write: */ buffer_output_size = tme_serial_buffer_copyout(&serial->tme_posix_serial_buffer_out, buffer_output, sizeof(buffer_output), NULL, TME_SERIAL_COPY_PEEK); assert(buffer_output_size > 0); /* unlock the mutex: */ tme_mutex_unlock(&serial->tme_posix_serial_mutex); /* try to write the device: */ rc = tme_thread_write_yield(serial->tme_posix_serial_fd_out, buffer_output, buffer_output_size); /* lock the mutex: */ tme_mutex_lock(&serial->tme_posix_serial_mutex); /* if the write was successful: */ if (rc > 0) { /* remove the written data from the output buffer: */ tme_serial_buffer_copyout(&serial->tme_posix_serial_buffer_out, NULL, rc, NULL, TME_SERIAL_COPY_NORMAL); /* call out for more data: */ _tme_posix_serial_callout(serial); } } /* NOTREACHED */ }
/* this waits on a condition, with an optional sleep time: */ void tme_stp22xx_cond_sleep_yield(struct tme_stp22xx *stp22xx, struct tme_stp22xx_cond *cond, const struct timeval *sleep) { signed long completion_i; struct tme_completion *completion; /* this condition must be idle: */ assert (cond->tme_stp22xx_cond_state == TME_STP22XX_COND_STATE_IDLE); /* we are now running, before waiting on this condition: */ cond->tme_stp22xx_cond_state = TME_STP22XX_COND_STATE_RUNNING; /* run: */ _tme_stp22xx_run(stp22xx); /* if this condition was notified while we were running: */ if (cond->tme_stp22xx_cond_state == TME_STP22XX_COND_STATE_NOTIFIED) { /* this condition is idle again: */ cond->tme_stp22xx_cond_state = TME_STP22XX_COND_STATE_IDLE; return; } /* the condition must still be running: */ assert (cond->tme_stp22xx_cond_state == TME_STP22XX_COND_STATE_RUNNING); /* make a total write-after-write barrier, to force writes to the completion states to happen before validation: */ tme_memory_barrier(0, 0, TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); /* validate any completions whose validations were delayed: */ for (completion_i = 0;; completion_i++) { completion = stp22xx->tme_stp22xx_completions_delayed[completion_i]; if (completion == NULL) { break; } stp22xx->tme_stp22xx_completions_delayed[completion_i] = NULL; tme_completion_validate(completion); } /* we are now waiting on this condition, unless threading is cooperative, in which case the condition will be idle again the next time this thread runs: */ cond->tme_stp22xx_cond_state = (TME_THREADS_COOPERATIVE ? TME_STP22XX_COND_STATE_IDLE : TME_STP22XX_COND_STATE_WAITING); /* sleep or wait on the condition variable: */ if (sleep != NULL) { tme_cond_sleep_yield(&cond->tme_stp22xx_cond_cond, &stp22xx->tme_stp22xx_mutex, sleep); } else { tme_cond_wait_yield(&cond->tme_stp22xx_cond_cond, &stp22xx->tme_stp22xx_mutex); } /* this condition is idle again: */ cond->tme_stp22xx_cond_state = TME_STP22XX_COND_STATE_IDLE; /* reenter: */ _tme_stp22xx_enter_locked(stp22xx); }
/* the isil7170 timer thread: */ static void _tme_isil7170_th_timer(struct tme_isil7170 *isil7170) { tme_uint8_t int_mask; tme_uint32_t sleep_usec; #ifdef TME_ISIL7170_TRACK_INT_RATE struct timeval now; #endif /* TME_ISIL7170_TRACK_INT_RATE */ /* lock the mutex: */ tme_mutex_lock(&isil7170->tme_isil7170_mutex); /* loop forever: */ for (;;) { /* if we were sleeping: */ int_mask = isil7170->tme_isil7170_timer_sleeping; isil7170->tme_isil7170_timer_sleeping = 0; if (int_mask) { #ifdef TME_ISIL7170_TRACK_INT_RATE /* if no interrupt is pending, and this interrupt is not masked, we will deliver another interrupt: */ if (!(isil7170->tme_isil7170_regs[TME_ISIL7170_REG_INT] & TME_ISIL7170_INT_PENDING) && (int_mask & isil7170->tme_isil7170_int_mask)) { isil7170->tme_isil7170_int_sample++; } /* if the sample time has finished, report on the interrupt rate: */ gettimeofday(&now, NULL); if (now.tv_sec > isil7170->tme_isil7170_int_sample_time.tv_sec || (now.tv_sec == isil7170->tme_isil7170_int_sample_time.tv_sec && now.tv_usec > isil7170->tme_isil7170_int_sample_time.tv_usec)) { if (isil7170->tme_isil7170_int_sample > 0) { tme_log(TME_ISIL7170_LOG_HANDLE(isil7170), 0, TME_OK, (TME_ISIL7170_LOG_HANDLE(isil7170), "timer interrupt rate: %ld/sec", (isil7170->tme_isil7170_int_sample / (TME_ISIL7170_TRACK_INT_RATE + (unsigned long) (now.tv_sec - isil7170->tme_isil7170_int_sample_time.tv_sec))))); } /* reset the sample: */ isil7170->tme_isil7170_int_sample_time.tv_sec = now.tv_sec + TME_ISIL7170_TRACK_INT_RATE; isil7170->tme_isil7170_int_sample_time.tv_usec = now.tv_usec; isil7170->tme_isil7170_int_sample = 0; } #endif /* TME_ISIL7170_TRACK_INT_RATE */ /* update the interrupt register: */ isil7170->tme_isil7170_regs[TME_ISIL7170_REG_INT] |= int_mask; /* callout to update our interrupt signal: */ _tme_isil7170_callout(isil7170); } /* get the interrupt mask: */ int_mask = isil7170->tme_isil7170_int_mask; /* if the 1/100 second periodic interrupt is unmasked: */ if (int_mask & TME_ISIL7170_INT_HSEC) { int_mask = TME_ISIL7170_INT_HSEC; sleep_usec = isil7170->tme_isil7170_clock_hsec_usec; } /* if the 1/10 second periodic interrupt is unmasked: */ else if (int_mask & TME_ISIL7170_INT_TSEC) { int_mask = TME_ISIL7170_INT_TSEC; sleep_usec = isil7170->tme_isil7170_clock_tsec_usec; } /* otherwise, all periodic interrupts are masked. wait until one of them is not: */ else { tme_cond_wait_yield(&isil7170->tme_isil7170_cond_timer, &isil7170->tme_isil7170_mutex); continue; } /* we are sleeping: */ isil7170->tme_isil7170_timer_sleeping = int_mask; /* unlock our mutex: */ tme_mutex_unlock(&isil7170->tme_isil7170_mutex); /* sleep: */ tme_thread_sleep_yield(0, sleep_usec); /* lock our mutex: */ tme_mutex_unlock(&isil7170->tme_isil7170_mutex); } /* NOTREACHED */ }