void ftrace_record_recursion(unsignedlong ip, unsignedlong parent_ip)
{ int index = 0; int i; unsignedlong old;
again: /* First check the last one recorded */ if (ip == cached_function) return;
i = atomic_read(&nr_records); /* nr_records is -1 when clearing records */
smp_mb__after_atomic(); if (i < 0) return;
/* *Ifthere'stwowritersandthiswritercomesinsecond, *thecmpxchg()belowtoupdatetheipwillfail.Thenthis *writerwilltryagain.Itispossiblethatindexwillnow *begreaterthannr_records.Thisisbecausethewriter *thatsucceededhasnotupdatedthenr_recordsyet. *Thiswritercouldkeeptryingagainuntiltheotherwriter *updatesnr_records.Butiftheotherwritertakesan *interrupt,andthatinterruptlocksupthatCPU,wedo *notwantthisCPUtolockupduetotherecursionprotection, *andhaveabugreportshowingthisCPUasthecauseof *lockingupthecomputer.Tonotlosethisrecord,this *writerwillsimplyusethenextpositiontoupdatethe *recursed_functions,anditwillupdatethenr_records *accordingly.
*/ if (index < i)
index = i; if (index >= CONFIG_FTRACE_RECORD_RECURSION_SIZE) return;
for (i = index - 1; i >= 0; i--) { if (recursed_functions[i].ip == ip) {
cached_function = ip; return;
}
}
cached_function = ip;
/* *Weonlywanttoaddafunctionifithasn'tbeenaddedbefore. *Addtothecurrentlocationbeforeincrementingthecount. *Ifitfailstoadd,thenincrementtheindex(saveini) *andtryagain.
*/
old = cmpxchg(&recursed_functions[index].ip, 0, ip); if (old != 0) { /* Did something else already added this for us? */ if (old == ip) return; /* Try the next location (use i for the next index) */
index++; goto again;
}
recursed_functions[index].parent_ip = parent_ip;
/* *It'sstillpossiblethatwecouldracewiththeclearing *CPU0CPU1 *-------- *ip=func *nr_records=-1; *recursed_functions[0]=0; *i=-1 *if(i<0) *nr_records=0; *(newrecursiondetected) *recursed_functions[0]=func *cmpxchg(recursed_functions[0], *func,0) * *Buttheworsethatcouldhappenisthatwegetazeroin *therecursed_functionsarray,andit'slikelythat"func"will *berecordedagain.
*/
i = atomic_read(&nr_records);
smp_mb__after_atomic(); if (i < 0)
cmpxchg(&recursed_functions[index].ip, ip, 0); elseif (i <= index)
atomic_cmpxchg(&nr_records, i, index + 1);
}
EXPORT_SYMBOL_GPL(ftrace_record_recursion);
staticint recursed_function_open(struct inode *inode, struct file *file)
{ int ret = 0;
mutex_lock(&recursed_function_lock); /* If this file was opened for write, then erase contents */ if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { /* disable updating records */
atomic_set(&nr_records, -1);
smp_mb__after_atomic();
memset(recursed_functions, 0, sizeof(recursed_functions));
smp_wmb(); /* enable them again */
atomic_set(&nr_records, 0);
} if (file->f_mode & FMODE_READ)
ret = seq_open(file, &recursed_function_seq_ops);
mutex_unlock(&recursed_function_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.