static void reorder_elem_down(unsigned int index) { /* If the size of the heap is even, there is a node with only one leaf, so we should stop reordering the heap before encountering such a node, and treat it specificaly if necessary. This trick does not behave correctly if the heap size is 0, but then we do not need to reorder anything. */ unsigned int half_size = (heap_size - 1) / 2; while (index < half_size) { unsigned int childs = index * 2 + 1; unsigned int lower_child = childs + (events_heap[childs].trigger >= events_heap[childs + 1].trigger); if (events_heap[index].trigger <= events_heap[lower_child].trigger) return; swap_events(index, lower_child); index = lower_child; } // Special case for a possible mono-leaf node. if (index == half_size && !(heap_size % 2)) { unsigned int child = index * 2 + 1; if (events_heap[index].trigger > events_heap[child].trigger) swap_events(index, child); } }
// remove the event at the top of the heap void removeNextEvent(EventHeap *h) { unsigned int idx, idx1, idx_left, idx_right; free(h->heap[0]); if (h->size > 1) h->heap[0] = h->heap[h->size - 1]; if (h->size) h->size--; // rebuild heap idx = 0; while (1) { idx_left = 2*idx + 1; idx_right = idx_left + 1; if (idx_left >= h->size) { return; } if (idx_left == h->size - 1) // only left child idx1 = idx_left; else { if (h->heap[idx_left]->time < h->heap[idx_right]->time) idx1 = idx_left; else idx1 = idx_right; } if (h->heap[idx]->time > h->heap[idx1]->time) { swap_events(h, idx, idx1); idx = idx1; } else { return; } } }
static void reorder_elem_up(unsigned int index) { while (index) { unsigned int parent = (index - 1) / 2; if (events_heap[index].trigger >= events_heap[parent].trigger) return; swap_events(index, parent); index = parent; } }
// insert new event in the heap void insertEvent(EventHeap *h, Event *ev) { int idx, idx1; if (h->size > h->max_size - 1) { printf("Event not inserted; too many events.\n"); return; } h->heap[h->size] = ev; (h->size)++; // rebuild heap idx = h->size - 1; idx1 = (idx-1)/2; while ((idx >= 1) && (h->heap[idx]->time < h->heap[idx1]->time)) { swap_events(h, idx, idx1); idx = idx1; idx1 = (idx-1)/2; } }
int _papi_hwd_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold ) { hwd_control_state_t *this_state = &ESI->machdep; struct hwd_pmc_control *contr = &this_state->control; int i, ncntrs, nricntrs = 0, nracntrs = 0, retval = 0; OVFDBG( "EventIndex=%d, threshold = %d\n", EventIndex, threshold ); /* The correct event to overflow is EventIndex */ ncntrs = _papi_hwi_system_info.sub_info.num_cntrs; i = ESI->EventInfoArray[EventIndex].pos[0]; if ( i >= ncntrs ) { OVFDBG( "Selector id (%d) larger than ncntrs (%d)\n", i, ncntrs ); return PAPI_EINVAL; } if ( threshold != 0 ) { /* Set an overflow threshold */ if ( ESI->EventInfoArray[EventIndex].derived ) { OVFDBG( "Can't overflow on a derived event.\n" ); return PAPI_EINVAL; } if ( ( retval = _papi_hwi_start_signal( _papi_hwi_system_info.sub_info. hardware_intr_sig, NEED_CONTEXT ) ) != PAPI_OK ) return ( retval ); contr->cpu_control.ireset[i] = PMC_OVFL - threshold; nricntrs = ++contr->cpu_control.nrictrs; nracntrs = --contr->cpu_control.nractrs; contr->si_signo = _papi_hwi_system_info.sub_info.hardware_intr_sig; contr->cpu_control.ppc64.mmcr0 |= PERF_INT_ENABLE; /* move this event to the bottom part of the list if needed */ if ( i < nracntrs ) swap_events( ESI, contr, i, nracntrs ); OVFDBG( "Modified event set\n" ); } else { if ( contr->cpu_control.ppc64.mmcr0 & PERF_INT_ENABLE ) { contr->cpu_control.ireset[i] = 0; nricntrs = --contr->cpu_control.nrictrs; nracntrs = ++contr->cpu_control.nractrs; if ( !nricntrs ) contr->cpu_control.ppc64.mmcr0 &= ( ~PERF_INT_ENABLE ); } /* move this event to the top part of the list if needed */ if ( i >= nracntrs ) swap_events( ESI, contr, i, nracntrs - 1 ); if ( !nricntrs ) contr->si_signo = 0; OVFDBG( "Modified event set\n" ); retval = _papi_hwi_stop_signal( _papi_hwi_system_info.sub_info. hardware_intr_sig ); } #ifdef DEBUG print_control( &contr->cpu_control ); #endif OVFDBG( "%s:%d: Hardware overflow is still experimental.\n", __FILE__, __LINE__ ); OVFDBG( "End of call. Exit code: %d\n", retval ); return ( retval ); }
static int _x86_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold ) { struct hwd_pmc_control *contr = &ESI->ctl_state->control; int i, ncntrs, nricntrs = 0, nracntrs = 0, retval = 0; OVFDBG( "EventIndex=%d\n", EventIndex ); #ifdef DEBUG if ( is_pentium4() ) print_control( &ESI->ctl_state->control.cpu_control ); #endif /* The correct event to overflow is EventIndex */ ncntrs = MY_VECTOR.cmp_info.num_cntrs; i = ESI->EventInfoArray[EventIndex].pos[0]; if ( i >= ncntrs ) { PAPIERROR( "Selector id %d is larger than ncntrs %d", i, ncntrs ); return PAPI_EINVAL; } if ( threshold != 0 ) { /* Set an overflow threshold */ retval = _papi_hwi_start_signal( MY_VECTOR.cmp_info.hardware_intr_sig, NEED_CONTEXT, MY_VECTOR.cmp_info.CmpIdx ); if ( retval != PAPI_OK ) return ( retval ); /* overflow interrupt occurs on the NEXT event after overflow occurs thus we subtract 1 from the threshold. */ contr->cpu_control.ireset[i] = ( -threshold + 1 ); if ( is_pentium4() ) contr->cpu_control.evntsel[i] |= CCCR_OVF_PMI_T0; else contr->cpu_control.evntsel[i] |= PERF_INT_ENABLE; contr->cpu_control.nrictrs++; contr->cpu_control.nractrs--; nricntrs = ( int ) contr->cpu_control.nrictrs; nracntrs = ( int ) contr->cpu_control.nractrs; contr->si_signo = MY_VECTOR.cmp_info.hardware_intr_sig; /* move this event to the bottom part of the list if needed */ if ( i < nracntrs ) swap_events( ESI, contr, i, nracntrs ); OVFDBG( "Modified event set\n" ); } else { if ( is_pentium4() && contr->cpu_control.evntsel[i] & CCCR_OVF_PMI_T0 ) { contr->cpu_control.ireset[i] = 0; contr->cpu_control.evntsel[i] &= ( ~CCCR_OVF_PMI_T0 ); contr->cpu_control.nrictrs--; contr->cpu_control.nractrs++; } else if ( !is_pentium4() && contr->cpu_control.evntsel[i] & PERF_INT_ENABLE ) { contr->cpu_control.ireset[i] = 0; contr->cpu_control.evntsel[i] &= ( ~PERF_INT_ENABLE ); contr->cpu_control.nrictrs--; contr->cpu_control.nractrs++; } nricntrs = ( int ) contr->cpu_control.nrictrs; nracntrs = ( int ) contr->cpu_control.nractrs; /* move this event to the top part of the list if needed */ if ( i >= nracntrs ) swap_events( ESI, contr, i, nracntrs - 1 ); if ( !nricntrs ) contr->si_signo = 0; OVFDBG( "Modified event set\n" ); retval = _papi_hwi_stop_signal( MY_VECTOR.cmp_info.hardware_intr_sig ); } #ifdef DEBUG if ( is_pentium4() ) print_control( &ESI->ctl_state->control.cpu_control ); #endif OVFDBG( "End of call. Exit code: %d\n", retval ); return ( retval ); }