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 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) ); }
static rtems_termios_tty * rtems_termios_open_tty( rtems_device_major_number major, rtems_device_minor_number minor, rtems_libio_open_close_args_t *args, rtems_termios_tty *tty, rtems_termios_device_node *device_node, const rtems_termios_callbacks *callbacks ) { rtems_status_code sc; if (tty == NULL) { static char c = 'a'; /* * Create a new device */ tty = calloc (1, sizeof (struct rtems_termios_tty)); if (tty == NULL) { return NULL; } /* * allocate raw input buffer */ tty->rawInBuf.Size = RAW_INPUT_BUFFER_SIZE; tty->rawInBuf.theBuf = malloc (tty->rawInBuf.Size); if (tty->rawInBuf.theBuf == NULL) { free(tty); return NULL; } /* * allocate raw output buffer */ tty->rawOutBuf.Size = RAW_OUTPUT_BUFFER_SIZE; tty->rawOutBuf.theBuf = malloc (tty->rawOutBuf.Size); if (tty->rawOutBuf.theBuf == NULL) { free((void *)(tty->rawInBuf.theBuf)); free(tty); return NULL; } /* * allocate cooked buffer */ tty->cbuf = malloc (CBUFSIZE); if (tty->cbuf == NULL) { free((void *)(tty->rawOutBuf.theBuf)); free((void *)(tty->rawInBuf.theBuf)); free(tty); return NULL; } /* * Initialize wakeup callbacks */ tty->tty_snd.sw_pfn = NULL; tty->tty_snd.sw_arg = NULL; tty->tty_rcv.sw_pfn = NULL; tty->tty_rcv.sw_arg = NULL; tty->tty_rcvwakeup = 0; tty->minor = minor; tty->major = major; /* * Set up mutex semaphores */ sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'i', c), 1, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, RTEMS_NO_PRIORITY, &tty->isem); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'o', c), 1, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, RTEMS_NO_PRIORITY, &tty->osem); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'x', c), 0, RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO, RTEMS_NO_PRIORITY, &tty->rawOutBuf.Semaphore); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); tty->rawOutBufState = rob_idle; /* * Set callbacks */ if (device_node != NULL) { device_node->tty = tty; tty->handler = *device_node->handler; tty->device_node = device_node; tty->device_context = device_node->context; memset(&tty->device, 0, sizeof(tty->device)); } else { tty->handler.first_open = callbacks->firstOpen != NULL ? rtems_termios_callback_firstOpen : NULL; tty->handler.last_close = callbacks->lastClose != NULL ? rtems_termios_callback_lastClose : NULL; tty->handler.poll_read = callbacks->pollRead != NULL ? rtems_termios_callback_pollRead : NULL; tty->handler.write = callbacks->write != NULL ? rtems_termios_callback_write : NULL; tty->handler.set_attributes = callbacks->setAttributes != NULL ? rtems_termios_callback_setAttributes : NULL; tty->handler.stop_remote_tx = callbacks->stopRemoteTx != NULL ? rtems_termios_callback_stopRemoteTx : NULL; tty->handler.start_remote_tx = callbacks->startRemoteTx != NULL ? rtems_termios_callback_startRemoteTx : NULL; tty->handler.mode = callbacks->outputUsesInterrupts; tty->device_context = NULL; tty->device_node = NULL; tty->device = *callbacks; } rtems_interrupt_lock_initialize (&tty->interrupt_lock, "Termios"); /* * Create I/O tasks */ if (tty->handler.mode == TERMIOS_TASK_DRIVEN) { sc = rtems_task_create ( rtems_build_name ('T', 'x', 'T', c), TERMIOS_TXTASK_PRIO, TERMIOS_TXTASK_STACKSIZE, RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, &tty->txTaskId); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_task_create ( rtems_build_name ('R', 'x', 'T', c), TERMIOS_RXTASK_PRIO, TERMIOS_RXTASK_STACKSIZE, RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, &tty->rxTaskId); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } if ((tty->handler.poll_read == NULL) || (tty->handler.mode == TERMIOS_TASK_DRIVEN)){ sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'r', c), 0, RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY, RTEMS_NO_PRIORITY, &tty->rawInBuf.Semaphore); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } /* * Set default parameters */ tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; tty->termios.c_oflag = OPOST | ONLCR | XTABS; tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; tty->termios.c_cc[VINTR] = '\003'; tty->termios.c_cc[VQUIT] = '\034'; tty->termios.c_cc[VERASE] = '\177'; tty->termios.c_cc[VKILL] = '\025'; tty->termios.c_cc[VEOF] = '\004'; tty->termios.c_cc[VEOL] = '\000'; tty->termios.c_cc[VEOL2] = '\000'; tty->termios.c_cc[VSTART] = '\021'; tty->termios.c_cc[VSTOP] = '\023'; tty->termios.c_cc[VSUSP] = '\032'; tty->termios.c_cc[VREPRINT] = '\022'; tty->termios.c_cc[VDISCARD] = '\017'; tty->termios.c_cc[VWERASE] = '\027'; tty->termios.c_cc[VLNEXT] = '\026'; /* start with no flow control, clear flow control flags */ tty->flow_ctrl = 0; /* * set low/highwater mark for XON/XOFF support */ tty->lowwater = tty->rawInBuf.Size * 1/2; tty->highwater = tty->rawInBuf.Size * 3/4; /* * Bump name characer */ if (c++ == 'z') c = 'a'; } args->iop->data1 = tty; if (!tty->refcount++) { if (tty->handler.first_open && !(*tty->handler.first_open)(tty, args)) { rtems_termios_destroy_tty(tty, args, false); return NULL; } /* * start I/O tasks, if needed */ if (tty->handler.mode == TERMIOS_TASK_DRIVEN) { sc = rtems_task_start( tty->rxTaskId, rtems_termios_rxdaemon, (rtems_task_argument)tty); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_task_start( tty->txTaskId, rtems_termios_txdaemon, (rtems_task_argument)tty); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } } return tty; }
/* * Open a termios device */ rtems_status_code rtems_termios_open ( rtems_device_major_number major, rtems_device_minor_number minor, void *arg, const rtems_termios_callbacks *callbacks ) { rtems_status_code sc; rtems_libio_open_close_args_t *args = arg; struct rtems_termios_tty *tty; /* * See if the device has already been opened */ sc = rtems_semaphore_obtain( rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) return sc; for (tty = rtems_termios_ttyHead ; tty != NULL ; tty = tty->forw) { if ((tty->major == major) && (tty->minor == minor)) break; } if (tty == NULL) { static char c = 'a'; /* * Create a new device */ tty = calloc (1, sizeof (struct rtems_termios_tty)); if (tty == NULL) { rtems_semaphore_release (rtems_termios_ttyMutex); return RTEMS_NO_MEMORY; } /* * allocate raw input buffer */ tty->rawInBuf.Size = RAW_INPUT_BUFFER_SIZE; tty->rawInBuf.theBuf = malloc (tty->rawInBuf.Size); if (tty->rawInBuf.theBuf == NULL) { free(tty); rtems_semaphore_release (rtems_termios_ttyMutex); return RTEMS_NO_MEMORY; } /* * allocate raw output buffer */ tty->rawOutBuf.Size = RAW_OUTPUT_BUFFER_SIZE; tty->rawOutBuf.theBuf = malloc (tty->rawOutBuf.Size); if (tty->rawOutBuf.theBuf == NULL) { free((void *)(tty->rawInBuf.theBuf)); free(tty); rtems_semaphore_release (rtems_termios_ttyMutex); return RTEMS_NO_MEMORY; } /* * allocate cooked buffer */ tty->cbuf = malloc (CBUFSIZE); if (tty->cbuf == NULL) { free((void *)(tty->rawOutBuf.theBuf)); free((void *)(tty->rawInBuf.theBuf)); free(tty); rtems_semaphore_release (rtems_termios_ttyMutex); return RTEMS_NO_MEMORY; } /* * Initialize wakeup callbacks */ tty->tty_snd.sw_pfn = NULL; tty->tty_snd.sw_arg = NULL; tty->tty_rcv.sw_pfn = NULL; tty->tty_rcv.sw_arg = NULL; tty->tty_rcvwakeup = 0; /* * link tty */ tty->forw = rtems_termios_ttyHead; tty->back = NULL; if (rtems_termios_ttyHead != NULL) rtems_termios_ttyHead->back = tty; rtems_termios_ttyHead = tty; if (rtems_termios_ttyTail == NULL) rtems_termios_ttyTail = tty; tty->minor = minor; tty->major = major; /* * Set up mutex semaphores */ sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'i', c), 1, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, RTEMS_NO_PRIORITY, &tty->isem); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'o', c), 1, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, RTEMS_NO_PRIORITY, &tty->osem); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'x', c), 0, RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO, RTEMS_NO_PRIORITY, &tty->rawOutBuf.Semaphore); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); tty->rawOutBufState = rob_idle; /* * Set callbacks */ tty->device = *callbacks; rtems_interrupt_lock_initialize (&tty->interrupt_lock, "Termios"); /* * Create I/O tasks */ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { sc = rtems_task_create ( rtems_build_name ('T', 'x', 'T', c), TERMIOS_TXTASK_PRIO, TERMIOS_TXTASK_STACKSIZE, RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, &tty->txTaskId); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_task_create ( rtems_build_name ('R', 'x', 'T', c), TERMIOS_RXTASK_PRIO, TERMIOS_RXTASK_STACKSIZE, RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, &tty->rxTaskId); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } if ((tty->device.pollRead == NULL) || (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)){ sc = rtems_semaphore_create ( rtems_build_name ('T', 'R', 'r', c), 0, RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY, RTEMS_NO_PRIORITY, &tty->rawInBuf.Semaphore); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } /* * Set default parameters */ tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; tty->termios.c_oflag = OPOST | ONLCR | XTABS; tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; tty->termios.c_cc[VINTR] = '\003'; tty->termios.c_cc[VQUIT] = '\034'; tty->termios.c_cc[VERASE] = '\177'; tty->termios.c_cc[VKILL] = '\025'; tty->termios.c_cc[VEOF] = '\004'; tty->termios.c_cc[VEOL] = '\000'; tty->termios.c_cc[VEOL2] = '\000'; tty->termios.c_cc[VSTART] = '\021'; tty->termios.c_cc[VSTOP] = '\023'; tty->termios.c_cc[VSUSP] = '\032'; tty->termios.c_cc[VREPRINT] = '\022'; tty->termios.c_cc[VDISCARD] = '\017'; tty->termios.c_cc[VWERASE] = '\027'; tty->termios.c_cc[VLNEXT] = '\026'; /* start with no flow control, clear flow control flags */ tty->flow_ctrl = 0; /* * set low/highwater mark for XON/XOFF support */ tty->lowwater = tty->rawInBuf.Size * 1/2; tty->highwater = tty->rawInBuf.Size * 3/4; /* * Bump name characer */ if (c++ == 'z') c = 'a'; } args->iop->data1 = tty; if (!tty->refcount++) { if (tty->device.firstOpen) (*tty->device.firstOpen)(major, minor, arg); /* * start I/O tasks, if needed */ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { sc = rtems_task_start( tty->rxTaskId, rtems_termios_rxdaemon, (rtems_task_argument)tty); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); sc = rtems_task_start( tty->txTaskId, rtems_termios_txdaemon, (rtems_task_argument)tty); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); } } 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); }