static void test_interrupt_locks( void ) { rtems_mode normal_interrupt_level = get_interrupt_level(); rtems_interrupt_lock initialized = RTEMS_INTERRUPT_LOCK_INITIALIZER; rtems_interrupt_lock lock; rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_initialize( &lock ); rtems_test_assert( memcmp( &lock, &initialized, sizeof( lock ) ) == 0 ); rtems_interrupt_lock_acquire( &lock, &lock_context ); rtems_test_assert( normal_interrupt_level != get_interrupt_level() ); rtems_interrupt_lock_release( &lock, &lock_context ); rtems_test_assert( normal_interrupt_level == get_interrupt_level() ); rtems_interrupt_lock_acquire_isr( &lock, &lock_context ); rtems_test_assert( normal_interrupt_level == get_interrupt_level() ); rtems_interrupt_lock_release_isr( &lock, &lock_context ); rtems_test_assert( normal_interrupt_level == get_interrupt_level() ); rtems_interrupt_lock_destroy( &lock ); rtems_interrupt_lock_destroy( &initialized ); }
static void rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close) { rtems_status_code sc; if (rtems_termios_linesw[tty->t_line].l_close != NULL) { /* * call discipline-specific close */ sc = rtems_termios_linesw[tty->t_line].l_close(tty); } else if (last_close) { /* * default: just flush output buffer */ sc = rtems_semaphore_obtain(tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred (sc); } drainOutput (tty); rtems_semaphore_release (tty->osem); } if (tty->handler.mode == TERMIOS_TASK_DRIVEN) { /* * send "terminate" to I/O tasks */ sc = rtems_event_send( tty->rxTaskId, TERMIOS_RX_TERMINATE_EVENT ); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_event_send( tty->txTaskId, TERMIOS_TX_TERMINATE_EVENT ); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } if (last_close && tty->handler.last_close) (*tty->handler.last_close)(tty, arg); if (tty->device_node != NULL) tty->device_node->tty = NULL; rtems_semaphore_delete (tty->isem); rtems_semaphore_delete (tty->osem); rtems_semaphore_delete (tty->rawOutBuf.Semaphore); if ((tty->handler.poll_read == NULL) || (tty->handler.mode == TERMIOS_TASK_DRIVEN)) rtems_semaphore_delete (tty->rawInBuf.Semaphore); rtems_interrupt_lock_destroy (&tty->interrupt_lock); free (tty->rawInBuf.theBuf); free (tty->rawOutBuf.theBuf); free (tty->cbuf); free (tty); }
static void test_by_function_level(int fl, bool dirty) { rtems_interrupt_lock lock; rtems_interrupt_lock_context lock_context; int s; uint64_t min; uint64_t q1; uint64_t q2; uint64_t q3; uint64_t max; rtems_interrupt_lock_initialize(&lock, "test"); rtems_interrupt_lock_acquire(&lock, &lock_context); for (s = 0; s < SAMPLES; ++s) { call_at_level(fl, fl, s, dirty); } rtems_interrupt_lock_release(&lock, &lock_context); rtems_interrupt_lock_destroy(&lock); sort_t(); min = t[0]; q1 = t[(1 * SAMPLES) / 4]; q2 = t[SAMPLES / 2]; q3 = t[(3 * SAMPLES) / 4]; max = t[SAMPLES - 1]; printf( " <Sample functionNestLevel=\"%i\">\n" " <Min unit=\"ns\">%" PRIu64 "</Min>" "<Q1 unit=\"ns\">%" PRIu64 "</Q1>" "<Q2 unit=\"ns\">%" PRIu64 "</Q2>" "<Q3 unit=\"ns\">%" PRIu64 "</Q3>" "<Max unit=\"ns\">%" PRIu64 "</Max>\n" " </Sample>\n", fl, rtems_counter_ticks_to_nanoseconds(min), rtems_counter_ticks_to_nanoseconds(q1), rtems_counter_ticks_to_nanoseconds(q2), rtems_counter_ticks_to_nanoseconds(q3), rtems_counter_ticks_to_nanoseconds(max) ); }
rtems_status_code rtems_termios_close (void *arg) { rtems_libio_open_close_args_t *args = arg; struct rtems_termios_tty *tty = args->iop->data1; rtems_status_code sc; sc = rtems_semaphore_obtain( rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); if (--tty->refcount == 0) { if (rtems_termios_linesw[tty->t_line].l_close != NULL) { /* * call discipline-specific close */ sc = rtems_termios_linesw[tty->t_line].l_close(tty); } else { /* * default: just flush output buffer */ sc = rtems_semaphore_obtain(tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred (sc); } drainOutput (tty); rtems_semaphore_release (tty->osem); } if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { /* * send "terminate" to I/O tasks */ sc = rtems_event_send( tty->rxTaskId, TERMIOS_RX_TERMINATE_EVENT ); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_event_send( tty->txTaskId, TERMIOS_TX_TERMINATE_EVENT ); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } if (tty->device.lastClose) (*tty->device.lastClose)(tty->major, tty->minor, arg); if (tty->forw == NULL) { rtems_termios_ttyTail = tty->back; if ( rtems_termios_ttyTail != NULL ) { rtems_termios_ttyTail->forw = NULL; } } else { tty->forw->back = tty->back; } if (tty->back == NULL) { rtems_termios_ttyHead = tty->forw; if ( rtems_termios_ttyHead != NULL ) { rtems_termios_ttyHead->back = NULL; } } else { tty->back->forw = tty->forw; } rtems_semaphore_delete (tty->isem); rtems_semaphore_delete (tty->osem); rtems_semaphore_delete (tty->rawOutBuf.Semaphore); if ((tty->device.pollRead == NULL) || (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)) rtems_semaphore_delete (tty->rawInBuf.Semaphore); rtems_interrupt_lock_destroy (&tty->interrupt_lock); free (tty->rawInBuf.theBuf); free (tty->rawOutBuf.theBuf); free (tty->cbuf); free (tty); } rtems_semaphore_release (rtems_termios_ttyMutex); return RTEMS_SUCCESSFUL; }
static void test_data_flush_and_invalidate(void) { if (rtems_cache_get_data_line_size() > 0) { rtems_interrupt_lock lock; rtems_interrupt_lock_context lock_context; volatile int *vdata = &data[0]; int n = 32; int i; size_t data_size = n * sizeof(data[0]); bool write_through; printf("data cache flush and invalidate test\n"); rtems_interrupt_lock_initialize(&lock, "test"); rtems_interrupt_lock_acquire(&lock, &lock_context); for (i = 0; i < n; ++i) { vdata[i] = i; } rtems_cache_flush_multiple_data_lines(&data[0], data_size); for (i = 0; i < n; ++i) { rtems_test_assert(vdata[i] == i); } for (i = 0; i < n; ++i) { vdata[i] = ~i; } rtems_cache_invalidate_multiple_data_lines(&data[0], data_size); write_through = vdata[0] == ~0; if (write_through) { for (i = 0; i < n; ++i) { rtems_test_assert(vdata[i] == ~i); } } else { for (i = 0; i < n; ++i) { rtems_test_assert(vdata[i] == i); } } for (i = 0; i < n; ++i) { vdata[i] = ~i; } rtems_cache_flush_multiple_data_lines(&data[0], data_size); rtems_cache_invalidate_multiple_data_lines(&data[0], data_size); for (i = 0; i < n; ++i) { rtems_test_assert(vdata[i] == ~i); } rtems_interrupt_lock_release(&lock, &lock_context); rtems_interrupt_lock_destroy(&lock); printf( "data cache operations by line passed the test (%s cache detected)\n", write_through ? "write-through" : "copy-back" ); } else { printf( "skip data cache flush and invalidate test" " due to cache line size of zero\n" ); } /* Make sure these are nops */ rtems_cache_flush_multiple_data_lines(NULL, 0); rtems_cache_invalidate_multiple_data_lines(NULL, 0); }
static void test_timing(void) { rtems_interrupt_lock lock; rtems_interrupt_lock_context lock_context; size_t data_size = sizeof(data); uint64_t d[3]; uint32_t cache_level; size_t cache_size; rtems_interrupt_lock_initialize(&lock, "test"); printf( "data cache line size %zi bytes\n" "data cache size %zi bytes\n", rtems_cache_get_data_line_size(), rtems_cache_get_data_cache_size(0) ); cache_level = 1; cache_size = rtems_cache_get_data_cache_size(cache_level); while (cache_size > 0) { printf( "data cache level %" PRIu32 " size %zi bytes\n", cache_level, cache_size ); ++cache_level; cache_size = rtems_cache_get_data_cache_size(cache_level); } rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = load(); d[1] = load(); rtems_cache_flush_entire_data(); d[2] = load(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "load %zi bytes with flush entire data\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with flushed cache %" PRIu64 " ns\n", data_size, d[0], d[1], d[2] ); rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = load(); d[1] = load(); rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data)); d[2] = load(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "load %zi bytes with flush multiple data\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with flushed cache %" PRIu64 " ns\n", data_size, d[0], d[1], d[2] ); rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = load(); d[1] = load(); rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data)); d[2] = load(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "load %zi bytes with invalidate multiple data\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with invalidated cache %" PRIu64 " ns\n", data_size, d[0], d[1], d[2] ); rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = store(); d[1] = store(); rtems_cache_flush_entire_data(); d[2] = store(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "store %zi bytes with flush entire data\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with flushed cache %" PRIu64 " ns\n", data_size, d[0], d[1], d[2] ); rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = store(); d[1] = store(); rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data)); d[2] = store(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "store %zi bytes with flush multiple data\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with flushed cache %" PRIu64 " ns\n", data_size, d[0], d[1], d[2] ); rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = store(); d[1] = store(); rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data)); d[2] = store(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "store %zi bytes with invalidate multiple data\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with invalidated cache %" PRIu64 " ns\n", data_size, d[0], d[1], d[2] ); printf( "instruction cache line size %zi bytes\n" "instruction cache size %zi bytes\n", rtems_cache_get_instruction_line_size(), rtems_cache_get_instruction_cache_size(0) ); cache_level = 1; cache_size = rtems_cache_get_instruction_cache_size(cache_level); while (cache_size > 0) { printf( "instruction cache level %" PRIu32 " size %zi bytes\n", cache_level, cache_size ); ++cache_level; cache_size = rtems_cache_get_instruction_cache_size(cache_level); } rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = do_some_work(); d[1] = do_some_work(); rtems_cache_invalidate_entire_instruction(); d[2] = do_some_work(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "invalidate entire instruction\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with invalidated cache %" PRIu64 " ns\n", d[0], d[1], d[2] ); rtems_interrupt_lock_acquire(&lock, &lock_context); d[0] = do_some_work(); d[1] = do_some_work(); rtems_cache_invalidate_multiple_instruction_lines(do_some_work, 4096); d[2] = do_some_work(); rtems_interrupt_lock_release(&lock, &lock_context); printf( "invalidate multiple instruction\n" " duration with normal cache %" PRIu64 " ns\n" " duration with warm cache %" PRIu64 " ns\n" " duration with invalidated cache %" PRIu64 " ns\n", d[0], d[1], d[2] ); rtems_interrupt_lock_destroy(&lock); }