You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
17 KiB
291 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
icecap.c
|
|
|
|
Abstract:
|
|
|
|
Macro definitions for manually-inserted icecap probes
|
|
|
|
Author:
|
|
|
|
Rick Vicik (rickv) 10-Aug-2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#ifdef _CAPKERN
|
|
|
|
PublicFunction(_CAP_Start_Profiling2)
|
|
PublicFunction(_CAP_End_Profiling2)
|
|
|
|
#define CAPSTART(parent,child) \
|
|
movl out0 = @fptr(parent) ;\
|
|
movl out1 = @fptr(child) ;\
|
|
br.call.sptk.few b0=_CAP_Start_Profiling2;;
|
|
|
|
#define CAPEND(parent) \
|
|
movl out0 = @fptr(parent) ;\
|
|
br.call.sptk.few b0=_CAP_End_Profiling2;;
|
|
|
|
#ifdef CAPKERN_SYNCH_POINTS
|
|
|
|
#define REC1INTSIZE 32
|
|
#define REC2INTSIZE 40
|
|
.global BBTBuffer
|
|
|
|
//
|
|
// Kernel Icecap logs to Perfmem (BBTBuffer) using the following format:
|
|
//
|
|
// BBTBuffer[0] contains the length in pages (4k or 8k)
|
|
// BBTBuffer[1] is a flagword: 1 = trace
|
|
// 2 = RDPMD4
|
|
// 4 = user stack dump
|
|
// BBTBuffer[2] is ptr to beginning of cpu0 buffer
|
|
// BBTBuffer[3] is ptr to beginning of cpu1 buffer (also end of cpu0 buffer)
|
|
// BBTBuffer[4] is ptr to beginning of cpu2 buffer (also end of cpu1 buffer)
|
|
// ...
|
|
// BBTBuffer[n+2] is ptr to beginning of cpu 'n' buffer (also end of cpu 'n-1' buffer)
|
|
// BBTBuffer[n+3] is ptr the end of cpu 'n' buffer
|
|
//
|
|
// The area starting with &BBTBuffer[n+4] is divided into private buffers
|
|
// for each cpu. The first dword in each cpu-private buffer points to the
|
|
// beginning of freespace in that buffer. Each one is initialized to point
|
|
// just after itself. Space is claimed using lock xadd on that dword.
|
|
// If the resulting value points beyond the beginning of the next cpu's
|
|
// buffer, this buffer is considered full and nothing further is logged.
|
|
// Each cpu's freespace pointer is in a separate cacheline.
|
|
|
|
|
|
|
|
// both of these macros mutate the tmp? register arguments and the ar.ccv register
|
|
|
|
#define CAPSPINLOG1INT(data, spare, tmp1, tmp2, tmp3, tmp4, tmpp) \
|
|
;; \
|
|
movl tmp1 = BBTBuffer ;\
|
|
;; \
|
|
ld8 tmp1 = [tmp1] /* tmp1 = ptr to BBTBuffer*/ ;\
|
|
;; \
|
|
cmp.eq tmpp = r0, tmp1 ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
|
|
adds tmp2 = 8, tmp1 ;\
|
|
;; \
|
|
ld8 tmp2 = [tmp2] /* tmp2 = BBTBuffer[1] */ ;\
|
|
;; \
|
|
tbit.z tmpp = tmp2, 0 ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
|
|
movl tmp3 = KiPcr + PcNumber ;\
|
|
;; \
|
|
ld1 tmp3 = [tmp3] /* tmp3 = 1 byte cpu# */ ;\
|
|
;; \
|
|
add tmp3 = 2, tmp3 ;\
|
|
;; \
|
|
shladd tmp3 = tmp3, 3, tmp1 /* tmp3 = &BBTBuffer[cpu# + 2] */ ;\
|
|
;; \
|
|
ld8 tmp1 = [tmp3] /* tmp1 = BBTBuffer[cpu# + 2] (&freeptr) */ ;\
|
|
add tmp2 = 8, tmp3 ;\
|
|
;; \
|
|
cmp.eq tmpp = r0, tmp1 ;\
|
|
ld8 tmp3 = [tmp1] /* tmp3 = BBTBuffer[cpu#+2][0] (freeptr) */ ;\
|
|
ld8 tmp2 = [tmp2] /* tmp2 = BBTBuffer[(cpu#+1)+2] (beginnextbuf) */ ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
|
|
;; \
|
|
cmp.gtu tmpp = tmp3, tmp2 ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
|
|
;; \
|
|
RETRYCAPSPINLOG1INT@__LINE__: \
|
|
ld8 tmp3 = [tmp1] /* tmp3 = reloaded freeptr */ ;\
|
|
;; \
|
|
mov.m ar.ccv = tmp3 /* only exchange on our loaded freeptr */ ;\
|
|
add tmp4 = REC1INTSIZE, tmp3 /* new freeptr val */ ;\
|
|
;; \
|
|
cmpxchg8.acq tmp4=[tmp1], tmp4, ar.ccv /* tmp4 = freeptr before xchng */ ;\
|
|
;; \
|
|
cmp.ne tmpp = tmp4, tmp3 /* if cmpxchg failed, retry */ ;\
|
|
(tmpp) br.cond.dpnt.few RETRYCAPSPINLOG1INT@__LINE__ ;\
|
|
add tmp1 = REC1INTSIZE, tmp4 /* tmp1 = end of record */ ;\
|
|
add tmp3 = 8, tmp4 /* tmp3 = 8 bytes into record */ ;\
|
|
;; \
|
|
cmp.geu tmpp = tmp1, tmp2 /* check if end of record is within buf */ ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
|
|
movl tmp2 = (REC1INTSIZE - 4)<<16 ;\
|
|
;; \
|
|
add tmp2 = 16|(spare<<8), tmp2 ;\
|
|
;; \
|
|
st8 [tmp4] = tmp2, 16 /* store type(16),spare,size */ ;\
|
|
mov.m tmp1 = ar.itc ;\
|
|
;; \
|
|
st8 [tmp3] = tmp1 /* store TS */ ;\
|
|
st8 [tmp4] = data, 8 /* store data */ ;\
|
|
mov tmp3 = brp ;\
|
|
;; \
|
|
st8 [tmp4] = tmp3 ;\
|
|
;; \
|
|
ENDCAPSPINLOG1INT@__LINE__:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CAPSPINLOG2INT(data1, data2, spare, tmp1, tmp2, tmp3, tmp4, tmpp) \
|
|
;; \
|
|
movl tmp1 = BBTBuffer ;\
|
|
;; \
|
|
ld8 tmp1 = [tmp1] ;\
|
|
;; \
|
|
cmp.eq tmpp = r0, tmp1 ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
|
|
adds tmp2 = 8, tmp1 ;\
|
|
;; \
|
|
ld8 tmp2 = [tmp2] ;\
|
|
;; \
|
|
tbit.z tmpp = tmp2, 0 ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
|
|
movl tmp3 = KiPcr + PcNumber ;\
|
|
;; \
|
|
ld1 tmp3 = [tmp3] ;\
|
|
;; \
|
|
add tmp3 = 2, tmp3 ;\
|
|
;; \
|
|
shladd tmp3 = tmp3, 3, tmp1 ;\
|
|
;; \
|
|
ld8 tmp1 = [tmp3] ;\
|
|
add tmp2 = 8, tmp3 ;\
|
|
;; \
|
|
cmp.eq tmpp = r0, tmp1 ;\
|
|
ld8 tmp3 = [tmp1] ;\
|
|
ld8 tmp2 = [tmp2] ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
|
|
;; \
|
|
cmp.gtu tmpp = tmp3, tmp2 ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
|
|
;; \
|
|
RETRYCAPSPINLOG2INT@__LINE__: \
|
|
ld8 tmp3 = [tmp1] ;\
|
|
;; \
|
|
mov.m ar.ccv = tmp3 ;\
|
|
add tmp4 = REC2INTSIZE, tmp3 ;\
|
|
;; \
|
|
cmpxchg8.acq tmp4=[tmp1], tmp4, ar.ccv ;\
|
|
;; \
|
|
cmp.ne tmpp = tmp4, tmp3 ;\
|
|
(tmpp) br.cond.dpnt.few RETRYCAPSPINLOG2INT@__LINE__ ;\
|
|
add tmp1 = REC2INTSIZE, tmp4 ;\
|
|
;; \
|
|
cmp.geu tmpp = tmp1, tmp2 ;\
|
|
(tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
|
|
movl tmp2 = (REC2INTSIZE - 4)<<16 ;\
|
|
;; \
|
|
add tmp2 = 16|(spare<<8), tmp2 ;\
|
|
add tmp3 = 16, tmp4 ;\
|
|
;; \
|
|
st8 [tmp4] = tmp2, 8 ;\
|
|
st8 [tmp3] = data1, 8 ;\
|
|
mov.m tmp1 = ar.itc ;\
|
|
;; \
|
|
st8 [tmp4] = tmp1 ;\
|
|
st8 [tmp3] = data2, 8 ;\
|
|
mov tmp4 = brp ;\
|
|
;; \
|
|
st8 [tmp3] = tmp4 ;\
|
|
;; \
|
|
ENDCAPSPINLOG2INT@__LINE__:
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// CAP_ACQUIRE_SPINLOCK(rpLock, rOwn, Loop)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Acquire a spinlock. Waits for lock to become free
|
|
// by spinning on the cached lock value.
|
|
//
|
|
// Agruments:
|
|
//
|
|
// rpLock: pointer to the spinlock (64-bit)
|
|
// rOwn: value to store in lock to indicate owner
|
|
// Depending on call location, it could be:
|
|
// - rpLock
|
|
// - pointer to process
|
|
// - pointer to thread
|
|
// - pointer to PRCB
|
|
// Loop: unique name for loop label
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Notes:
|
|
//
|
|
// Uses temporaries: predicates pt0, pt1, pt2, and GR t22.
|
|
//--
|
|
|
|
|
|
|
|
|
|
|
|
#define CAP_ACQUIRE_SPINLOCK(rpLock, rOwn, Loop, rCounter, temp1, temp2, temp3) \
|
|
cmp##.##eq pt0, pt1 = zero, zero ;\
|
|
cmp##.##eq pt2 = zero, zero ;\
|
|
mov rCounter = -1 ;\
|
|
;; ;\
|
|
Loop: ;\
|
|
.pred.rel "mutex",pt0,pt1 ;\
|
|
(pt1) YIELD ;\
|
|
(pt0) xchg8 t22 = [rpLock], rOwn ;\
|
|
(pt1) ld8##.##nt1 t22 = [rpLock] ;\
|
|
;; ;\
|
|
(pt0) cmp##.##ne pt2 = zero, t22 ;\
|
|
cmp##.##eq pt0, pt1 = zero, t22 ;\
|
|
add rCounter = 1, rCounter ;\
|
|
(pt2) br##.##dpnt Loop ;\
|
|
;; ;\
|
|
CAPSPINLOG1INT(rpLock, 1, t22, temp1, temp2, temp3, pt2) ;\
|
|
cmp##.##eq pt2 = zero, rCounter ;\
|
|
(pt2) br##.##cond##.##sptk CAP_SKIP_COLL_LOG@__LINE__ ;\
|
|
CAPSPINLOG2INT(rCounter, rpLock, 2, t22, temp1, temp2, temp3, pt2) ;\
|
|
CAP_SKIP_COLL_LOG@__LINE__:
|
|
|
|
|
|
//++
|
|
// Routine:
|
|
//
|
|
// CAP_RELEASE_SPINLOCK(rpLock)
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Release a spinlock by setting lock to zero.
|
|
//
|
|
// Agruments:
|
|
//
|
|
// rpLock: pointer to the spinlock.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Notes:
|
|
//
|
|
// Uses an ordered store to ensure previous memory accesses in
|
|
// critical section complete.
|
|
//--
|
|
|
|
#define CAP_RELEASE_SPINLOCK(rpLock, temp1, temp2, temp3, temp4, tempp) \
|
|
st8##.##rel [rpLock] = zero ;\
|
|
CAPSPINLOG1INT(rpLock, 7, temp1, temp2, temp3, temp4, tempp)
|
|
|
|
#endif //CAPKERN_SYNCH_POINTS
|
|
|
|
#else //!defined(_CAPKERN)
|
|
|
|
#define CAPSTART(parent,child)
|
|
#define CAPEND(parent)
|
|
#endif
|