From 66bf2af2784dd96aa3d9e86505b11f11c63a1654 Mon Sep 17 00:00:00 2001 From: Jennifer Averett Date: Thu, 6 Nov 2014 08:37:54 -0600 Subject: capture: Add SMP support. To support smp data was broken into global and percpu capture data. Capture control must be disabled prior to printing or setting of watch points. --- cpukit/libmisc/capture/capture.c | 411 +++++++++++++++++++---------------- cpukit/libmisc/capture/capture.h | 22 +- cpukit/libmisc/capture/captureimpl.h | 19 +- 3 files changed, 234 insertions(+), 218 deletions(-) diff --git a/cpukit/libmisc/capture/capture.c b/cpukit/libmisc/capture/capture.c index a83bc90770..4327100449 100644 --- a/cpukit/libmisc/capture/capture.c +++ b/cpukit/libmisc/capture/capture.c @@ -5,7 +5,7 @@ All rights reserved Objective Design Systems Pty Ltd, 2002 Chris Johns (ccj@acm.org) - COPYRIGHT (c) 1989-2009. + COPYRIGHT (c) 1989-2014. On-Line Applications Research Corporation (OAR). The license and distribution terms for this file may be @@ -59,21 +59,52 @@ #define RTEMS_CAPTURE_RECORD_EVENTS (0) #endif +typedef struct { + rtems_capture_buffer_t records; + uint32_t count; + rtems_id reader; + rtems_interrupt_lock lock; + uint32_t flags; +} rtems_capture_per_cpu_data; + +typedef struct { + uint32_t flags; + rtems_capture_control_t* controls; + int extension_index; + rtems_capture_timestamp timestamp; + rtems_task_priority ceiling; + rtems_task_priority floor; + rtems_interrupt_lock lock; +} rtems_capture_global_data; + +static rtems_capture_per_cpu_data *capture_per_cpu = NULL; + +static rtems_capture_global_data capture_global; /* * RTEMS Capture Data. */ -static rtems_capture_buffer_t capture_records = {NULL, 0, 0, 0, 0, 0}; -static uint32_t capture_count; -static uint32_t capture_flags; -static rtems_capture_control_t* capture_controls; -static int capture_extension_index; -static rtems_capture_timestamp capture_timestamp; -static rtems_task_priority capture_ceiling; -static rtems_task_priority capture_floor; -static rtems_id capture_reader; -static rtems_interrupt_lock capture_lock = - RTEMS_INTERRUPT_LOCK_INITIALIZER("capture"); +#define capture_per_cpu_get( _cpu ) \ + ( &capture_per_cpu[ _cpu ] ) + +#define capture_records_on_cpu( _cpu ) capture_per_cpu[ _cpu ].records +#define capture_count_on_cpu( _cpu ) capture_per_cpu[ _cpu ].count +#define capture_flags_on_cpu( _cpu ) capture_per_cpu[ _cpu ].flags +#define capture_reader_on_cpu( _cpu ) capture_per_cpu[ _cpu ].reader +#define capture_lock_on_cpu( _cpu ) capture_per_cpu[ _cpu ].lock + +#define capture_records capture_records_on_cpu( _SMP_Get_current_processor() ) +#define capture_count capture_count_on_cpu( _SMP_Get_current_processor() ) +#define capture_flags_per_cpu capture_flags_on_cpu( _SMP_Get_current_processor() ) +#define capture_flags_global capture_global.flags +#define capture_controls capture_global.controls +#define capture_extension_index capture_global.extension_index +#define capture_timestamp capture_global.timestamp +#define capture_ceiling capture_global.ceiling +#define capture_floor capture_global.floor +#define capture_reader capture_reader_on_cpu( _SMP_Get_current_processor() ) +#define capture_lock_per_cpu capture_lock_on_cpu( _SMP_Get_current_processor() ) +#define capture_lock_global capture_global.lock /* * RTEMS Event text. @@ -108,12 +139,12 @@ int rtems_capture_get_extension_index(void) uint32_t rtems_capture_get_flags(void) { - return capture_flags; + return capture_flags_global; } void rtems_capture_set_flags(uint32_t mask) { - capture_flags |= mask; + capture_flags_global |= mask; } /* @@ -284,11 +315,11 @@ rtems_capture_create_control (rtems_name name, rtems_id id) if (control == NULL) { - bool ok = rtems_workspace_allocate (sizeof (*control), (void **) &control); + control = malloc( sizeof (*control)); - if (!ok) + if (!control) { - capture_flags |= RTEMS_CAPTURE_NO_MEMORY; + capture_flags_global |= RTEMS_CAPTURE_NO_MEMORY; return NULL; } @@ -301,13 +332,13 @@ rtems_capture_create_control (rtems_name name, rtems_id id) memset (control->by, 0, sizeof (control->by)); - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); control->next = capture_controls; capture_controls = control; rtems_iterate_over_all_threads (rtems_capture_initialize_control); - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); } return control; @@ -315,16 +346,18 @@ rtems_capture_create_control (rtems_name name, rtems_id id) void rtems_capture_initialize_task( rtems_tcb* tcb ) { - rtems_capture_control_t* control; - rtems_name name; + rtems_capture_control_t* control; + rtems_name name; + rtems_interrupt_lock_context lock_context; /* - * We need to scan the default control list to initialise + * We need to scan the default control list to initialize * this control if it is a new task. */ rtems_object_get_classic_name( tcb->Object.id, &name ); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); if (tcb->Capture.control == NULL) { for (control = capture_controls; control != NULL; control = control->next) if (rtems_capture_match_name_id (control->name, control->id, @@ -333,28 +366,31 @@ void rtems_capture_initialize_task( rtems_tcb* tcb ) } tcb->Capture.flags |= RTEMS_CAPTURE_INIT_TASK; + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); } void rtems_capture_record_task( rtems_tcb* tcb ) { rtems_capture_task_record_t rec; void* ptr; + rtems_interrupt_lock_context lock_context; rtems_object_get_classic_name( tcb->Object.id, &rec.name ); - + rec.stack_size = tcb->Start.Initial_stack.size; rec.start_priority = _RTEMS_tasks_Priority_from_Core( tcb->Start.initial_priority ); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); tcb->Capture.flags |= RTEMS_CAPTURE_RECORD_TASK; + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); /* * Log the task information. The first time a task is * seen a record is logged. This record can be identified * by a 0 in the event identifier. */ - rtems_capture_begin_add_record (tcb, 0, sizeof(rec), &ptr); ptr = rtems_capture_append_to_record( ptr, @@ -375,14 +411,14 @@ void rtems_capture_record_task( rtems_tcb* tcb ) } /* - * This function indicates if data should be filtered from the + * This function indicates if data should be filtered from the * log. */ bool rtems_capture_filter( rtems_tcb* tcb, uint32_t events) { if (tcb && - ((capture_flags & + ((capture_flags_global & (RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) == RTEMS_CAPTURE_TRIGGERED)) { @@ -398,7 +434,7 @@ bool rtems_capture_filter( rtems_tcb* tcb, if ((events & RTEMS_CAPTURE_RECORD_EVENTS) || ((tcb->real_priority >= capture_ceiling) && (tcb->real_priority <= capture_floor) && - ((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) || + ((capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH) || (control && (control->flags & RTEMS_CAPTURE_WATCH))))) { return false; @@ -420,7 +456,7 @@ rtems_capture_record_open (rtems_tcb* tcb, uint8_t* ptr; rtems_capture_record_t* capture_in; - rtems_interrupt_lock_acquire (&capture_lock, lock_context); + rtems_interrupt_lock_acquire (&capture_lock_per_cpu, lock_context); ptr = rtems_capture_buffer_allocate(&capture_records, size); capture_in = (rtems_capture_record_t *) ptr; @@ -441,14 +477,14 @@ rtems_capture_record_open (rtems_tcb* tcb, ptr = ptr + sizeof(*capture_in); } else - capture_flags |= RTEMS_CAPTURE_OVERFLOW; + capture_flags_per_cpu |= RTEMS_CAPTURE_OVERFLOW; return ptr; } void rtems_capture_record_close( void *rec, rtems_interrupt_lock_context* lock_context) { - rtems_interrupt_lock_release (&capture_lock, lock_context); + rtems_interrupt_lock_release (&capture_lock_per_cpu, lock_context); } /* @@ -460,11 +496,10 @@ rtems_capture_trigger (rtems_tcb* ft, rtems_tcb* tt, uint32_t events) { - /* * If we have not triggered then see if this is a trigger condition. */ - if (!(capture_flags & RTEMS_CAPTURE_TRIGGERED)) + if (!(capture_flags_global & RTEMS_CAPTURE_TRIGGERED)) { rtems_capture_control_t* fc = NULL; rtems_capture_control_t* tc = NULL; @@ -499,7 +534,7 @@ rtems_capture_trigger (rtems_tcb* ft, */ if (from_events || to_events) { - capture_flags |= RTEMS_CAPTURE_TRIGGERED; + capture_flags_global |= RTEMS_CAPTURE_TRIGGERED; return 1; } @@ -510,7 +545,7 @@ rtems_capture_trigger (rtems_tcb* ft, { if (rtems_capture_by_in_to (events, ft, tc)) { - capture_flags |= RTEMS_CAPTURE_TRIGGERED; + capture_flags_global |= RTEMS_CAPTURE_TRIGGERED; return 1; } } @@ -523,47 +558,61 @@ rtems_capture_trigger (rtems_tcb* ft, /* * This function initialises the realtime capture engine allocating the trace - * buffer. It is assumed we have a working heap at stage of initialisation. + * buffer. It is assumed we have a working heap at stage of initialization. */ rtems_status_code rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribute__((unused))) { - rtems_status_code sc; + rtems_status_code sc = RTEMS_SUCCESSFUL; + size_t count; + uint32_t i; + rtems_capture_buffer_t* buff; /* * See if the capture engine is already open. */ - if (capture_records.buffer) + if ((capture_flags_global & RTEMS_CAPTURE_INIT) == RTEMS_CAPTURE_INIT) { return RTEMS_RESOURCE_IN_USE; + } - rtems_capture_buffer_create( &capture_records, size ); + count = rtems_get_processor_count(); + if (capture_per_cpu == NULL) { + capture_per_cpu = calloc( count, sizeof(rtems_capture_per_cpu_data) ); + } - if (capture_records.buffer == NULL) - return RTEMS_NO_MEMORY; + for (i=0; ibuffer == NULL) { + sc = RTEMS_NO_MEMORY; + break; + } - capture_count = 0; - capture_flags = 0; + capture_count_on_cpu(i) = 0; + capture_flags_on_cpu(i) = 0; + } + + capture_flags_global = 0; capture_ceiling = 0; capture_floor = 255; - - sc = rtems_capture_user_extension_open(); + if (sc == RTEMS_SUCCESSFUL) + sc = rtems_capture_user_extension_open(); if (sc != RTEMS_SUCCESSFUL) { - rtems_capture_buffer_destroy( &capture_records); + for (i=0; inext; - rtems_workspace_free (delete); + free (delete); } capture_controls = NULL; - - if (capture_records.buffer) - { - rtems_capture_buffer_destroy( &capture_records); + for (cpu=0; cpu < rtems_get_processor_count(); cpu++) { + capture_count_on_cpu(cpu) = 0; + if (capture_records_on_cpu(cpu).buffer) + rtems_capture_buffer_destroy( &capture_records_on_cpu(cpu) ); } + free( capture_per_cpu ); + capture_per_cpu = NULL; + return RTEMS_SUCCESSFUL; } @@ -618,20 +678,20 @@ rtems_capture_control (bool enable) { rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); - if (!capture_records.buffer) + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT) { - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); return RTEMS_UNSATISFIED; } if (enable) - capture_flags |= RTEMS_CAPTURE_ON; + capture_flags_global |= RTEMS_CAPTURE_ON; else - capture_flags &= ~RTEMS_CAPTURE_ON; + capture_flags_global &= ~RTEMS_CAPTURE_ON; - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); return RTEMS_SUCCESSFUL; } @@ -646,20 +706,20 @@ rtems_capture_monitor (bool enable) { rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); - if (!capture_records.buffer) + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT) { - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); return RTEMS_UNSATISFIED; } if (enable) - capture_flags |= RTEMS_CAPTURE_ONLY_MONITOR; + capture_flags_global |= RTEMS_CAPTURE_ONLY_MONITOR; else - capture_flags &= ~RTEMS_CAPTURE_ONLY_MONITOR; + capture_flags_global &= ~RTEMS_CAPTURE_ONLY_MONITOR; - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); return RTEMS_SUCCESSFUL; } @@ -673,7 +733,6 @@ rtems_capture_flush_tcb (rtems_tcb *tcb) tcb->Capture.flags &= ~RTEMS_CAPTURE_TRACED; } - /* * This function flushes the capture buffer. The prime parameter allows the * capture engine to also be primed again. @@ -681,21 +740,36 @@ rtems_capture_flush_tcb (rtems_tcb *tcb) rtems_status_code rtems_capture_flush (bool prime) { - rtems_interrupt_lock_context lock_context; + rtems_interrupt_lock_context lock_context_global; + rtems_interrupt_lock_context lock_context_per_cpu; + rtems_interrupt_lock* lock; + uint32_t cpu; + + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context_global); - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) + { + rtems_interrupt_lock_release (&capture_lock_global, &lock_context_global); + return RTEMS_UNSATISFIED; + } rtems_iterate_over_all_threads (rtems_capture_flush_tcb); if (prime) - capture_flags &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW); + capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW); else - capture_flags &= ~RTEMS_CAPTURE_OVERFLOW; - - rtems_capture_buffer_flush( &capture_records ); - capture_count = 0; + capture_flags_global &= ~RTEMS_CAPTURE_OVERFLOW; + + for (cpu=0; cpu < rtems_get_processor_count(); cpu++) { + lock = &(capture_lock_on_cpu( cpu )); + rtems_interrupt_lock_acquire (lock, &lock_context_per_cpu); + capture_count_on_cpu(cpu) = 0; + if (capture_records_on_cpu(cpu).buffer) + rtems_capture_buffer_flush( &capture_records_on_cpu(cpu) ); + rtems_interrupt_lock_release (lock, &lock_context_per_cpu); + } - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context_global); return RTEMS_SUCCESSFUL; } @@ -704,13 +778,16 @@ rtems_capture_flush (bool prime) * This function defines a watch for a specific task given a name. A watch * causes it to be traced either in or out of context. The watch can be * optionally enabled or disabled with the set routine. It is disabled by - * default. + * default. A watch can only be defined when capture control is disabled */ rtems_status_code rtems_capture_watch_add (rtems_name name, rtems_id id) { rtems_capture_control_t* control; + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) + return RTEMS_UNSATISFIED; + if ((name == 0) && (id == 0)) return RTEMS_UNSATISFIED; @@ -731,7 +808,8 @@ rtems_capture_watch_add (rtems_name name, rtems_id id) /* * This function removes a watch for a specific task given a name. The task * description will still exist if referenced by a trace record in the trace - * buffer or a global watch is defined. + * buffer or a global watch is defined. A watch can only be deleted when + * capture control is disabled. */ rtems_status_code rtems_capture_watch_del (rtems_name name, rtems_id id) @@ -741,6 +819,9 @@ rtems_capture_watch_del (rtems_name name, rtems_id id) rtems_capture_control_t** prev_control; bool found = false; + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) + return RTEMS_UNSATISFIED; + /* * Should this test be for wildcards ? */ @@ -750,13 +831,13 @@ rtems_capture_watch_del (rtems_name name, rtems_id id) { if (rtems_capture_match_name_id (control->name, control->id, name, id)) { - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); *prev_control = control->next; - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); - rtems_workspace_free (control); + free (control); control = *prev_control; @@ -786,6 +867,9 @@ rtems_capture_watch_ctrl (rtems_name name, rtems_id id, bool enable) rtems_capture_control_t* control; bool found = false; + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) + return RTEMS_UNSATISFIED; + /* * Find the control and then set the watch. It must exist before it can * be controlled. @@ -794,14 +878,14 @@ rtems_capture_watch_ctrl (rtems_name name, rtems_id id, bool enable) { if (rtems_capture_match_name_id (control->name, control->id, name, id)) { - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); if (enable) control->flags |= RTEMS_CAPTURE_WATCH; else control->flags &= ~RTEMS_CAPTURE_WATCH; - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); found = true; } @@ -823,18 +907,18 @@ rtems_capture_watch_global (bool enable) { rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); /* * We need to keep specific and global watches separate so * a global enable/disable does not lose a specific watch. */ if (enable) - capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH; + capture_flags_global |= RTEMS_CAPTURE_GLOBAL_WATCH; else - capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH; + capture_flags_global &= ~RTEMS_CAPTURE_GLOBAL_WATCH; - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); return RTEMS_SUCCESSFUL; } @@ -845,7 +929,7 @@ rtems_capture_watch_global (bool enable) bool rtems_capture_watch_global_on (void) { - return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0; + return capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0; } /* @@ -1082,30 +1166,26 @@ rtems_capture_clear_trigger (rtems_name from_name, } static inline uint32_t rtems_capture_count_records( void* recs, size_t size ) -{ +{ rtems_capture_record_t* rec; uint8_t* ptr = recs; uint32_t rec_count = 0; size_t byte_count = 0; - - + + while (byte_count < size) { rec = (rtems_capture_record_t*) ptr; rec_count++; _Assert( rec->size >= sizeof(*rec) ); ptr += rec->size; byte_count += rec->size; - _Assert( rec_count <= capture_count ); }; - + return rec_count; } /* * This function reads a number of records from the capture buffer. - * The user can optionally block and wait until the buffer as a - * specific number of records available or a specific time has - * elasped. * * The function returns the number of record that is has that are * in a continous block of memory. If the number of available records @@ -1117,106 +1197,47 @@ static inline uint32_t rtems_capture_count_records( void* recs, size_t size ) * The user must release the records. This is achieved with a call to * rtems_capture_release. Calls this function without a release will * result in at least the same number of records being released. - * - * The 'threshold' parameter is the number of records that must be - * captured before returning. If a timeout period is specified (non-0) - * any captured records will be returned. These parameters stop - * thrashing occuring for a small number of records, yet allows - * a user configured latiency to be applied for single events. - * - * The 'timeout' parameter is in micro-seconds. A value of 0 will disable - * the timeout. */ rtems_status_code -rtems_capture_read (uint32_t threshold, - uint32_t timeout, +rtems_capture_read (uint32_t cpu, uint32_t* read, rtems_capture_record_t** recs) { rtems_interrupt_lock_context lock_context; rtems_status_code sc = RTEMS_SUCCESSFUL; size_t recs_size = 0; - bool wrapped; + rtems_interrupt_lock* lock = &(capture_lock_on_cpu( cpu )); + rtems_capture_buffer_t* records = &(capture_records_on_cpu( cpu )); + uint32_t* flags = &(capture_flags_on_cpu( cpu )); *read = 0; *recs = NULL; - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (lock, &lock_context); /* * Only one reader is allowed. */ - if (capture_flags & RTEMS_CAPTURE_READER_ACTIVE) + if (*flags & RTEMS_CAPTURE_READER_ACTIVE) { - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (lock, &lock_context); return RTEMS_RESOURCE_IN_USE; } - capture_flags |= RTEMS_CAPTURE_READER_ACTIVE; - - *recs = rtems_capture_buffer_peek( &capture_records, &recs_size ); - *read = rtems_capture_count_records( *recs, recs_size ); - - rtems_interrupt_lock_release (&capture_lock, &lock_context); - - for (;;) + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) { - /* - * See if the data wraps the end of the record buffer. - */ - wrapped = rtems_capture_buffer_has_wrapped( &capture_records); - - /* - * Do we have a threshold and have not wrapped - * around the end of the capture record buffer ? - */ - if ((!wrapped) && threshold) - { - /* - * Do we have enough records ? - */ - if (*read < threshold) - { - rtems_event_set event_out; - - rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &capture_reader); - - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); - - capture_flags |= RTEMS_CAPTURE_READER_WAITING; - - rtems_interrupt_lock_release (&capture_lock, &lock_context); - - sc = rtems_event_receive (RTEMS_EVENT_0, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_MICROSECONDS_TO_TICKS (timeout), - &event_out); - - /* - * Let the user handle all other sorts of errors. This may - * not be the best solution, but oh well, it will do for - * now. - */ - if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT)) - break; - - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_release (lock, &lock_context); + return RTEMS_UNSATISFIED; + } - *recs = rtems_capture_buffer_peek( &capture_records, &recs_size ); - *read = rtems_capture_count_records( *recs, recs_size ); + *flags |= RTEMS_CAPTURE_READER_ACTIVE; - rtems_interrupt_lock_release (&capture_lock, &lock_context); + *recs = rtems_capture_buffer_peek( records, &recs_size ); - continue; - } - } + *read = rtems_capture_count_records( *recs, recs_size ); - /* - * Always out if we reach here. To loop use continue. - */ - break; - } + rtems_interrupt_lock_release (lock, &lock_context); return sc; } @@ -1226,7 +1247,7 @@ rtems_capture_read (uint32_t threshold, * to the capture engine. The count must match the number read. */ rtems_status_code -rtems_capture_release (uint32_t count) +rtems_capture_release (uint32_t cpu, uint32_t count) { rtems_interrupt_lock_context lock_context; uint8_t* ptr; @@ -1235,43 +1256,49 @@ rtems_capture_release (uint32_t count) size_t ptr_size = 0; size_t rel_size = 0; rtems_status_code ret_val = RTEMS_SUCCESSFUL; + rtems_interrupt_lock* lock = &(capture_lock_on_cpu( cpu )); + rtems_capture_buffer_t* records = &(capture_records_on_cpu( cpu )); + uint32_t* flags = &(capture_flags_on_cpu( cpu )); + uint32_t* total = &(capture_count_on_cpu( cpu )); - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); + rtems_interrupt_lock_acquire (lock, &lock_context); - if (count > capture_count) - count = capture_count; + if (count > *total) { + count = *total; + } - rtems_interrupt_lock_release (&capture_lock, &lock_context); + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) { + rtems_interrupt_lock_release (lock, &lock_context); + return RTEMS_UNSATISFIED; + } counted = count; - - ptr = rtems_capture_buffer_peek( &capture_records, &ptr_size ); + + ptr = rtems_capture_buffer_peek( records, &ptr_size ); _Assert(ptr_size >= (count * sizeof(*rec) )); rel_size = 0; - while (counted--) - { + while (counted--) { rec = (rtems_capture_record_t*) ptr; rel_size += rec->size; _Assert( rel_size <= ptr_size ); ptr += rec->size; } - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); - if (rel_size > ptr_size ) { ret_val = RTEMS_INVALID_NUMBER; rel_size = ptr_size; } - capture_count -= count; + *total -= count; - if (count) - rtems_capture_buffer_free( &capture_records, rel_size ); + if (count) { + rtems_capture_buffer_free( records, rel_size ); + } - capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE; + *flags &= ~RTEMS_CAPTURE_READER_ACTIVE; - rtems_interrupt_lock_release (&capture_lock, &lock_context); + rtems_interrupt_lock_release (lock, &lock_context); return ret_val; } @@ -1308,5 +1335,3 @@ rtems_capture_get_control_list (void) { return capture_controls; } - - diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h index f9076865a2..c8bc270515 100644 --- a/cpukit/libmisc/capture/capture.h +++ b/cpukit/libmisc/capture/capture.h @@ -520,9 +520,6 @@ rtems_capture_clear_trigger (rtems_name from_name, * @brief Capture read records from capture buffer * * This function reads a number of records from the capture buffer. - * The user can optionally block and wait until the buffer as a - * specific number of records available or a specific time has - * elasped. * * The function returns the number of record that is has that are * in a continous block of memory. If the number of available records @@ -535,17 +532,7 @@ rtems_capture_clear_trigger (rtems_name from_name, * rtems_capture_release. Calls this function without a release will * result in at least the same number of records being released. * - * The 'threshold' parameter is the number of records that must be - * captured before returning. If a timeout period is specified (non-0) - * any captured records will be returned. These parameters stop - * thrashing occuring for a small number of records, yet allows - * a user configured latiency to be applied for single events. - * - * The @a timeout parameter is in microseconds. A value of 0 will - * disable the timeout. - * - * @param[in] threshold The number of records that must be captured - * @param[in] timeout The micro-second timeout period + * @param[in] cpu The cpu number that the records were recorded on * @param[out] read will contain the number of records read * @param[out] recs The capture records that are read. * @@ -554,8 +541,7 @@ rtems_capture_clear_trigger (rtems_name from_name, * source of the error. */ rtems_status_code -rtems_capture_read (uint32_t threshold, - uint32_t timeout, +rtems_capture_read (uint32_t cpu, uint32_t* read, rtems_capture_record_t** recs); @@ -566,13 +552,13 @@ rtems_capture_read (uint32_t threshold, * to the capture engine. The count must match the number read. * * @param[in] count The number of record slots to release - * + * * @retval This method returns RTEMS_SUCCESSFUL if there was not an * error. Otherwise, a status code is returned indicating the * source of the error. */ rtems_status_code -rtems_capture_release (uint32_t count); +rtems_capture_release (uint32_t cpu, uint32_t count); /* * @brief Capture nano-second time period. diff --git a/cpukit/libmisc/capture/captureimpl.h b/cpukit/libmisc/capture/captureimpl.h index cc116468a3..44d81dbbc2 100644 --- a/cpukit/libmisc/capture/captureimpl.h +++ b/cpukit/libmisc/capture/captureimpl.h @@ -43,14 +43,19 @@ extern "C" { /* * Global capture flags. */ -#define RTEMS_CAPTURE_ON (1U << 0) -#define RTEMS_CAPTURE_NO_MEMORY (1U << 1) -#define RTEMS_CAPTURE_OVERFLOW (1U << 2) +#define RTEMS_CAPTURE_INIT (1u << 0) +#define RTEMS_CAPTURE_ON (1U << 1) +#define RTEMS_CAPTURE_NO_MEMORY (1U << 2) #define RTEMS_CAPTURE_TRIGGERED (1U << 3) -#define RTEMS_CAPTURE_READER_ACTIVE (1U << 4) -#define RTEMS_CAPTURE_READER_WAITING (1U << 5) -#define RTEMS_CAPTURE_GLOBAL_WATCH (1U << 6) -#define RTEMS_CAPTURE_ONLY_MONITOR (1U << 7) +#define RTEMS_CAPTURE_GLOBAL_WATCH (1U << 4) +#define RTEMS_CAPTURE_ONLY_MONITOR (1U << 5) + +/* + * Per-CPU capture flags. + */ +#define RTEMS_CAPTURE_OVERFLOW (1U << 0) +#define RTEMS_CAPTURE_READER_ACTIVE (1U << 1) +#define RTEMS_CAPTURE_READER_WAITING (1U << 2) /** * @brief Capture set extension index. -- cgit v1.2.3