aboutsummaryrefslogtreecommitdiffstats
BranchCommit messageAuthorAge
archive/unc-master-3.0P-FP: fix BUG_ON releated to priority inheritanceBjoern Brandenburg13 years
archived-2013.1uncachedev: mmap memory that is not cached by CPUsGlenn Elliott12 years
archived-private-masterMerge branch 'wip-2.6.34' into old-private-masterAndrea Bastoni16 years
archived-semi-partMerge branch 'wip-semi-part' of ssh://cvs/cvs/proj/litmus/repo/litmus2010 int...Andrea Bastoni15 years
demoFurther refinementsJonathan Herman14 years
ecrts-pgm-finalMerge branch 'wip-ecrts14-pgm' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus-r...Glenn Elliott12 years
ecrts14-pgm-finalMerge branch 'wip-ecrts14-pgm' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus-r...Glenn Elliott12 years
gpusync-rtss12Final GPUSync implementation.Glenn Elliott13 years
gpusync/stagingRename IKGLP R2DGLP.Glenn Elliott12 years
linux-tipMerge branch 'slab/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/p...Linus Torvalds15 years
litmus2008-patch-seriesadd i386 feather-trace implementationBjoern B. Brandenburg16 years
masterPSN-EDF: use inferred_sporadic_job_release_atBjoern Brandenburg9 years
pgmmake it compileGlenn Elliott12 years
prop/litmus-signalsInfrastructure for Litmus signals.Glenn Elliott13 years
prop/robust-tie-breakFixed bug in edf_higher_prio().Glenn Elliott13 years
stagingFix tracepoint compilation errorFelipe Cerqueira13 years
test9/23/2016Namhoon Kim9 years
tracing-develTest kernel tracing events capabilitiesAndrea Bastoni16 years
v2.6.34-with-arm-patchessmsc911x: Add spinlocks around registers accessCatalin Marinas16 years
v2015.1Add ARM syscall def for get_current_budgetBjoern Brandenburg10 years
wip-2011.2-bbbLitmus core: simplify np-section protocolBjoern B. Brandenburg14 years
wip-2011.2-bbb-traceRefactor sched_trace_log_message() -> debug_trace_log_message()Andrea Bastoni14 years
wip-2012.3-gpuSOBLIV draining support for C-EDF.Glenn Elliott13 years
wip-2012.3-gpu-preportpick up last C-RM fileGlenn Elliott12 years
wip-2012.3-gpu-rtss13Fix critical bug in GPU tracker.Glenn Elliott12 years
wip-2012.3-gpu-sobliv-budget-w-ksharkProper sobliv draining and many bug fixes.Glenn Elliott13 years
wip-aedzl-finalMake it easier to compile AEDZL interfaces in liblitmus.Glenn Elliott15 years
wip-aedzl-revisedAdd sched_trace data for Apative EDZLGlenn Elliott15 years
wip-arbit-deadlineFix compilation bug.Glenn Elliott13 years
wip-aux-tasksDescription of refined aux task inheritance.Glenn Elliott13 years
wip-bbbGSN-EDF & Core: improve debug TRACE'ing for NP sectionsBjoern B. Brandenburg14 years
wip-bbb-prio-donuse correct timestampBjoern B. Brandenburg14 years
wip-better-breakImplement hash-based EDF tie-breaking.Glenn Elliott13 years
wip-binary-heapMake C-EDF work with simplified binheap_deleteGlenn Elliott14 years
wip-budgetAdded support for choices in budget policy enforcement.Glenn Elliott16 years
wip-colorSummarize schedulability with final recordJonathan Herman14 years
wip-color-jlhsched_color: Fixed two bugs causing crashing on experiment restart and a rare...Jonathan Herman14 years
wip-d10-hz1000Enable HZ=1000 on District 10Bjoern B. Brandenburg15 years
wip-default-clusteringFeature: Make default C-EDF clustering compile-time configurable.Glenn Elliott15 years
wip-dissipation-jericksoUpdate from 2.6.36 to 2.6.36.4Jeremy Erickson12 years
wip-dissipation2-jericksoUpdate 2.6.36 to 2.6.36.4Jeremy Erickson12 years
wip-ecrts14-pgmMerge branch 'wip-ecrts14-pgm' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus-r...Glenn Elliott12 years
wip-edf-hsblast tested versionJonathan Herman14 years
wip-edf-osLookup table EDF-osJeremy Erickson13 years
wip-edf-tie-breakMerge branch 'wip-edf-tie-break' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus...Glenn Elliott13 years
wip-edzl-critiqueUse hr_timer's active checks instead of having own flag.Glenn Elliott15 years
wip-edzl-finalImplementation of the EDZL scheduler.Glenn Elliott15 years
wip-edzl-revisedClean up comments.Glenn Elliott15 years
wip-eventsAdded support for tracing arbitrary actions.Jonathan Herman15 years
wip-extra-debugDBG: add additional tracingBjoern B. Brandenburg15 years
wip-fix-switch-jericksoAttempt to fix race condition with plugin switchingJeremy Erickson15 years
wip-fix3sched: show length of runqueue clock deactivation in /proc/sched_debugBjoern B. Brandenburg15 years
wip-fmlp-dequeueImprove FMLP queue management.Glenn Elliott15 years
wip-ft-irq-flagFeather-Trace: keep track of interrupt-related interference.Bjoern B. Brandenburg14 years
wip-gpu-cleanupEnable sched_trace log injection from userspaceGlenn Elliott13 years
wip-gpu-interruptsRemove option for threading of all softirqs.Glenn Elliott14 years
wip-gpu-rtas12Generalized GPU cost predictors + EWMA. (untested)Glenn Elliott13 years
wip-gpu-rtss12Final GPUSync implementation.Glenn Elliott14 years
wip-gpu-rtss12-srpexperimental changes to support GPUs under SRPGlenn Elliott14 years
wip-gpusync-mergeCleanup priority tracking for budget enforcement.Glenn Elliott12 years
wip-ikglpMove RSM and IKGLP imp. to own .c filesGlenn Elliott14 years
wip-k-fmlpMerge branch 'mpi-master' into wip-k-fmlpGlenn Elliott14 years
wip-kernel-coloringAdded recolor syscallNamhoon Kim8 years
wip-kernthreadsKludge work-queue processing into klitirqd.Glenn Elliott15 years
wip-klmirqd-to-auxAllow klmirqd threads to be given names.Glenn Elliott13 years
wip-ksharkMerge branch 'mpi-staging' into wip-ksharkJonathan Herman13 years
wip-litmus-3.2Merge commit 'v3.2' into litmus-stagingAndrea Bastoni13 years
wip-litmus2011.2Cleanup: Coding conformance for affinity stuff.Glenn Elliott15 years
wip-litmus3.0-2011.2Feather-Trace: keep track of interrupt-related interference.Bjoern B. Brandenburg14 years
wip-master-2.6.33-rtAvoid deadlock when switching task policy to BACKGROUND (ugly)Andrea Bastoni16 years
wip-mcRemoved ARM-specific hacks which disabled less common mixed-criticality featu...Jonathan Herman13 years
wip-mc-bipasaMC-EDF addedbipasa chattopadhyay14 years
wip-mc-jericksoSplit C/D queuesJeremy Erickson15 years
wip-mc2-cache-slackManually patched mc^2 related codeMing Yang10 years
wip-mcrit-maccosmeticMac Mollison15 years
wip-merge-3.0Prevent Linux to send IPI and queue tasks on remote CPUs.Andrea Bastoni14 years
wip-merge-v3.0Prevent Linux to send IPI and queue tasks on remote CPUs.Andrea Bastoni14 years
wip-migration-affinityNULL affinity dereference in C-EDF.Glenn Elliott15 years
wip-mmap-uncacheshare branch with othersGlenn Elliott13 years
wip-modechangeRTSS 2017 submissionNamhoon Kim9 years
wip-nested-lockingAppears to be working.Bryan Ward13 years
wip-omlp-gedfFirst implementation of G-OMLP.Glenn Elliott15 years
wip-paiSome cleanup of PAIGlenn Elliott14 years
wip-percore-lib9/21/2016Namhoon Kim9 years
wip-performanceCONFIG_DONT_PREEMPT_ON_TIE: Don't preeempt a scheduled task on priority tie.Glenn Elliott15 years
wip-pgmAdd PGM support to C-FLGlenn Elliott12 years
wip-pgm-splitFirst draft of C-FL-splitNamhoon Kim12 years
wip-pm-ovdAdd preemption-and-migration overhead tracing supportAndrea Bastoni16 years
wip-prio-inhP-EDF updated to use the generic pi framework.Glenn Elliott15 years
wip-prioq-dglBUG FIX: Support DGLs with PRIOQ_MUTEXGlenn Elliott13 years
wip-refactored-gedfGeneralizd architecture for GEDF-style scheduelrs to reduce code redundancy.Glenn Elliott15 years
wip-release-master-fixbugfix: release master CPU must signal task was pickedBjoern B. Brandenburg15 years
wip-robust-tie-breakEDF priority tie-breaks.Glenn Elliott13 years
wip-rt-ksharkMove task time accounting into the complete_job method.Jonathan Herman13 years
wip-rtas12-pgmScheduling of PGM jobs.Glenn Elliott14 years
wip-semi-partFix compile error with newer GCCJeremy Erickson13 years
wip-semi-part-edfos-jericksoUse initial CPU set by clientJeremy Erickson13 years
wip-shared-libTODO: Fix condition checks in replicate_page_move_mapping()Namhoon Kim9 years
wip-shared-lib2RTAS 2017 Submission ver.Namhoon Kim9 years
wip-shared-memInitial commit for shared libraryNamhoon Kim9 years
wip-splitting-jericksoFix release behaviorJeremy Erickson13 years
wip-splitting-omlp-jericksoBjoern's Dissertation Code with Priority DonationJeremy Erickson13 years
wip-stage-binheapAn efficient binary heap implementation.Glenn Elliott14 years
wip-sun-portDynamic memory allocation and clean exit for FeatherTraceChristopher Kenna15 years
wip-timer-tracebugfix: C-EDF, clear scheduled field of the correct CPU upon task_exitAndrea Bastoni15 years
wip-tracepointsAdd kernel-style events for sched_trace_XXX() functionsAndrea Bastoni14 years
 
TagDownloadAuthorAge
2015.1commit 8e51b37822...Bjoern Brandenburg10 years
2013.1commit bcaacec1ca...Glenn Elliott12 years
2012.3commit c158b5fbe4...Jonathan Herman13 years
2012.2commit b53c479a0f...Glenn Elliott13 years
2012.1commit 83b11ea1c6...Bjoern B. Brandenburg14 years
rtas12-mc-beta-expcommit 8e236ee20f...Christopher Kenna14 years
2011.1commit d11808b5c6...Christopher Kenna15 years
v2.6.37-rc4commit e8a7e48bb2...Linus Torvalds15 years
v2.6.37-rc3commit 3561d43fd2...Linus Torvalds15 years
v2.6.37-rc2commit e53beacd23...Linus Torvalds15 years
v2.6.37-rc1commit c8ddb2713c...Linus Torvalds15 years
v2.6.36commit f6f94e2ab1...Linus Torvalds15 years
2010.2commit 5c5456402d...Bjoern B. Brandenburg15 years
v2.6.36-rc8commit cd07202cc8...Linus Torvalds15 years
v2.6.36-rc7commit cb655d0f3d...Linus Torvalds15 years
v2.6.36-rc6commit 899611ee7d...Linus Torvalds15 years
v2.6.36-rc5commit b30a3f6257...Linus Torvalds15 years
v2.6.36-rc4commit 49553c2ef8...Linus Torvalds15 years
v2.6.36-rc3commit 2bfc96a127...Linus Torvalds15 years
v2.6.36-rc2commit 76be97c1fc...Linus Torvalds15 years
v2.6.36-rc1commit da5cabf80e...Linus Torvalds15 years
v2.6.35commit 9fe6206f40...Linus Torvalds15 years
v2.6.35-rc6commit b37fa16e78...Linus Torvalds15 years
v2.6.35-rc5commit 1c5474a65b...Linus Torvalds15 years
v2.6.35-rc4commit 815c4163b6...Linus Torvalds15 years
v2.6.35-rc3commit 7e27d6e778...Linus Torvalds16 years
v2.6.35-rc2commit e44a21b726...Linus Torvalds16 years
v2.6.35-rc1commit 67a3e12b05...Linus Torvalds16 years
2010.1commit 7c1ff4c544...Andrea Bastoni16 years
v2.6.34commit e40152ee1e...Linus Torvalds16 years
v2.6.33.4commit 4640b4e7d9...Greg Kroah-Hartman16 years
v2.6.34-rc7commit b57f95a382...Linus Torvalds16 years
v2.6.34-rc6commit 66f41d4c5c...Linus Torvalds16 years
v2.6.33.3commit 3e7ad8ed97...Greg Kroah-Hartman16 years
v2.6.34-rc5commit 01bf0b6457...Linus Torvalds16 years
v2.6.34-rc4commit 0d0fb0f9c5...Linus Torvalds16 years
v2.6.33.2commit 19f00f070c...Greg Kroah-Hartman16 years
v2.6.34-rc3commit 2eaa9cfdf3...Linus Torvalds16 years
v2.6.34-rc2commit 220bf991b0...Linus Torvalds16 years
v2.6.33.1commit dbdafe5ccf...Greg Kroah-Hartman16 years
v2.6.34-rc1commit 57d54889cd...Linus Torvalds16 years
v2.6.33commit 60b341b778...Linus Torvalds16 years
v2.6.33-rc8commit 724e6d3fe8...Linus Torvalds16 years
v2.6.33-rc7commit 29275254ca...Linus Torvalds16 years
v2.6.33-rc6commit abe94c756c...Linus Torvalds16 years
v2.6.33-rc5commit 92dcffb916...Linus Torvalds16 years
v2.6.33-rc4commit 7284ce6c9f...Linus Torvalds16 years
v2.6.33-rc3commit 74d2e4f8d7...Linus Torvalds16 years
v2.6.33-rc2commit 6b7b284958...Linus Torvalds16 years
v2.6.33-rc1commit 55639353a0...Linus Torvalds16 years
v2.6.32commit 22763c5cf3...Linus Torvalds16 years
v2.6.32-rc8commit 648f4e3e50...Linus Torvalds16 years
v2.6.32-rc7commit 156171c71a...Linus Torvalds16 years
v2.6.32-rc6commit b419148e56...Linus Torvalds16 years
v2.6.32-rc5commit 012abeea66...Linus Torvalds16 years
v2.6.32-rc4commit 161291396e...Linus Torvalds16 years
v2.6.32-rc3commit 374576a8b6...Linus Torvalds16 years
v2.6.32-rc1commit 17d857be64...Linus Torvalds16 years
v2.6.32-rc2commit 17d857be64...Linus Torvalds16 years
v2.6.31commit 74fca6a428...Linus Torvalds16 years
v2.6.31-rc9commit e07cccf404...Linus Torvalds16 years
v2.6.31-rc8commit 326ba5010a...Linus Torvalds16 years
v2.6.31-rc7commit 422bef879e...Linus Torvalds16 years
v2.6.31-rc6commit 64f1607ffb...Linus Torvalds16 years
v2.6.31-rc5commit ed680c4ad4...Linus Torvalds16 years
v2.6.31-rc4commit 4be3bd7849...Linus Torvalds16 years
v2.6.31-rc3commit 6847e154e3...Linus Torvalds16 years
v2.6.31-rc2commit 8e4a718ff3...Linus Torvalds16 years
v2.6.31-rc1commit 28d0325ce6...Linus Torvalds17 years
v2.6.30commit 07a2039b8e...Linus Torvalds17 years
v2.6.30-rc8commit 9fa7eb283c...Linus Torvalds17 years
v2.6.30-rc7commit 59a3759d0f...Linus Torvalds17 years
v2.6.30-rc6commit 1406de8e11...Linus Torvalds17 years
v2.6.30-rc5commit 091bf7624d...Linus Torvalds17 years
v2.6.30-rc4commit 091438dd56...Linus Torvalds17 years
v2.6.30-rc3commit 0910697403...Linus Torvalds17 years
v2.6.30-rc2commit 0882e8dd3a...Linus Torvalds17 years
v2.6.30-rc1commit 577c9c456f...Linus Torvalds17 years
v2.6.29commit 8e0ee43bc2...Linus Torvalds17 years
v2.6.29-rc8commit 041b62374c...Linus Torvalds17 years
v2.6.29-rc7commit fec6c6fec3...Linus Torvalds17 years
v2.6.29-rc6commit 20f4d6c3a2...Linus Torvalds17 years
v2.6.29-rc5commit d2f8d7ee1a...Linus Torvalds17 years
v2.6.29-rc4commit 8e4921515c...Linus Torvalds17 years
v2.6.29-rc3commit 18e352e4a7...Linus Torvalds17 years
v2.6.29-rc2commit 1de9e8e70f...Linus Torvalds17 years
v2.6.29-rc1commit c59765042f...Linus Torvalds17 years
v2.6.28commit 4a6908a3a0...Linus Torvalds17 years
v2.6.28-rc9commit 929096fe9f...Linus Torvalds17 years
v2.6.28-rc8commit 8b1fae4e42...Linus Torvalds17 years
v2.6.28-rc7commit 061e41fdb5...Linus Torvalds17 years
v2.6.28-rc6commit 13d428afc0...Linus Torvalds17 years
v2.6.28-rc5commit 9bf1a2445f...Linus Torvalds17 years
v2.6.28-rc4commit f7160c7573...Linus Torvalds17 years
v2.6.28-rc3commit 45beca08dd...Linus Torvalds17 years
v2.6.28-rc2commit 0173a3265b...Linus Torvalds17 years
v2.6.28-rc1commit 57f8f7b60d...Linus Torvalds17 years
v2.6.27commit 3fa8749e58...Linus Torvalds17 years
v2.6.27-rc9commit 4330ed8ed4...Linus Torvalds17 years
v2.6.27-rc8commit 94aca1dac6...Linus Torvalds17 years
v2.6.27-rc7commit 72d31053f6...Linus Torvalds17 years
v2.6.27-rc6commit adee14b2e1...Linus Torvalds17 years
v2.6.27-rc5commit 24342c34a0...Linus Torvalds17 years
v2.6.27-rc4commit 6a55617ed5...Linus Torvalds17 years
v2.6.27-rc3commit 30a2f3c60a...Linus Torvalds17 years
v2.6.27-rc2commit 0967d61ea0...Linus Torvalds17 years
v2.6.27-rc1commit 6e86841d05...Linus Torvalds17 years
v2.6.26commit bce7f793da...Linus Torvalds17 years
v2.6.26-rc9commit b7279469d6...Linus Torvalds17 years
v2.6.26-rc8commit 543cf4cb3f...Linus Torvalds18 years
v2.6.26-rc7commit d70ac829b7...Linus Torvalds18 years
v2.6.26-rc6commit 5dd34572ad...Linus Torvalds18 years
v2.6.26-rc5commit 53c8ba9540...Linus Torvalds18 years
v2.6.26-rc4commit e490517a03...Linus Torvalds18 years
v2.6.26-rc3commit b8291ad07a...Linus Torvalds18 years
v2.6.26-rc2commit 492c2e476e...Linus Torvalds18 years
v2.6.26-rc1commit 2ddcca36c8...Linus Torvalds18 years
v2.6.25commit 4b119e21d0...Linus Torvalds18 years
v2.6.25-rc9commit 120dd64cac...Linus Torvalds18 years
v2.6.25-rc8commit 0e81a8ae37...Linus Torvalds18 years
v2.6.25-rc7commit 05dda977f2...Linus Torvalds18 years
v2.6.25-rc6commit a978b30af3...Linus Torvalds18 years
v2.6.25-rc5commit cdeeeae056...Linus Torvalds18 years
v2.6.25-rc4commit 29e8c3c304...Linus Torvalds18 years
v2.6.25-rc3commit bfa274e243...Linus Torvalds18 years
v2.6.25-rc2commit 101142c37b...Linus Torvalds18 years
v2.6.25-rc1commit 19af35546d...Linus Torvalds18 years
v2.6.24commit 49914084e7...Linus Torvalds18 years
v2.6.24-rc8commit cbd9c88369...Linus Torvalds18 years
v2.6.24-rc7commit 3ce5445046...Linus Torvalds18 years
v2.6.24-rc6commit ea67db4cdb...Linus Torvalds18 years
v2.6.24-rc5commit 82d29bf6dc...Linus Torvalds18 years
v2.6.24-rc4commit 09b56adc98...Linus Torvalds18 years
v2.6.24-rc3commit d9f8bcbf67...Linus Torvalds18 years
v2.6.24-rc2commit dbeeb816e8...Linus Torvalds18 years
v2.6.24-rc1commit c9927c2bf4...Linus Torvalds18 years
v2.6.23commit bbf25010f1...Linus Torvalds18 years
v2.6.23-rc9commit 3146b39c18...Linus Torvalds18 years
v2.6.23-rc8commit 4942de4a0e...Linus Torvalds18 years
v2.6.23-rc7commit 81cfe79b9c...Linus Torvalds18 years
v2.6.23-rc6commit 0d4cbb5e7f...Linus Torvalds18 years
v2.6.23-rc5commit 40ffbfad6b...Linus Torvalds18 years
v2.6.23-rc4commit b07d68b5ca...Linus Torvalds18 years
v2.6.23-rc3commit 39d3520c92...Linus Torvalds18 years
v2.6.23-rc2commit d4ac2477fa...Linus Torvalds18 years
v2.6.23-rc1commit f695baf2df...Linus Torvalds18 years
v2.6.22commit 7dcca30a32...Linus Torvalds18 years
v2.6.22-rc7commit a38d6181ff...Linus Torvalds19 years
v2.6.22-rc6commit 189548642c...Linus Torvalds19 years
v2.6.22-rc5commit 188e1f81ba...Linus Torvalds19 years
v2.6.22-rc4commit 5ecd3100e6...Linus Torvalds19 years
v2.6.22-rc3commit c420bc9f09...Linus Torvalds19 years
v2.6.22-rc2commit 55b637c6a0...Linus Torvalds19 years
v2.6.22-rc1commit 39403865d2...Linus Torvalds19 years
v2.6.21commit de46c33745...Linus Torvalds19 years
v2.6.21-rc7commit 94a05509a9...Linus Torvalds19 years
v2.6.21-rc6commit a21bd69e15...Linus Torvalds19 years
v2.6.21-rc5commit e0f2e3a06b...Linus Torvalds19 years
v2.6.21-rc4commit db98e0b434...Linus Torvalds19 years
v2.6.21-rc3commit 08e15e81a4...Linus Torvalds19 years
v2.6.21-rc2commit 606135a308...Linus Torvalds19 years
v2.6.21-rc1commit c8f71b01a5...Linus Torvalds19 years
v2.6.20commit 62d0cfcb27...Linus Torvalds19 years
v2.6.20-rc7commit f56df2f4db...Linus Torvalds19 years
v2.6.20-rc6commit 99abfeafb5...Linus Torvalds19 years
v2.6.20-rc5commit a8b3485287...Linus Torvalds19 years
v2.6.20-rc4commit bf81b46482...Linus Torvalds19 years
v2.6.20-rc3commit 669df1b478...Linus Torvalds19 years
v2.6.20-rc2commit 3bf8ba38f3...Linus Torvalds19 years
v2.6.20-rc1commit cc016448b0...Linus Torvalds19 years
v2.6.19commit 0215ffb08c...Linus Torvalds19 years
v2.6.19-rc6commit 44597f65f6...Linus Torvalds19 years
v2.6.19-rc5commit 80c2188127...Linus Torvalds19 years
v2.6.19-rc4commit ae99a78af3...Linus Torvalds19 years
v2.6.19-rc3commit 7059abedd2...Linus Torvalds19 years
v2.6.19-rc2commit b4bd8c6643...Linus Torvalds19 years
v2.6.19-rc1commit d223a60106...Linus Torvalds19 years
v2.6.18commit e478bec0ba...Linus Torvalds19 years
v2.6.18-rc7commit 95064a75eb...Linus Torvalds19 years
v2.6.18-rc6commit c336923b66...Linus Torvalds19 years
v2.6.18-rc5commit 60d4684068...Linus Torvalds19 years
v2.6.18-rc4commit 9f737633e6...Linus Torvalds19 years
v2.6.18-rc3commit b6ff50833a...Linus Torvalds19 years
v2.6.18-rc2commit 82d6897fef...Linus Torvalds19 years
v2.6.18-rc1commit 120bda20c6...Linus Torvalds19 years
v2.6.17commit 427abfa28a...Linus Torvalds20 years
v2.6.17-rc6commit 1def630a6a...Linus Torvalds20 years
v2.6.17-rc5commit a8bd60705a...Linus Torvalds20 years
v2.6.17-rc4commit d8c3291c73...Linus Torvalds20 years
v2.6.17-rc3commit 2be4d50295...Linus Torvalds20 years
v2.6.17-rc2commit 8bbde0e6d5...Linus Torvalds20 years
v2.6.17-rc1commit 6246b6128b...Linus Torvalds20 years
v2.6.16commit 7705a8792b...Linus Torvalds20 years
v2.6.16-rc6commit 535744878e...Linus Torvalds20 years
v2.6.16-rc5commit b9a33cebac...Linus Torvalds20 years
v2.6.16-rc4commit bd71c2b174...Linus Torvalds20 years
v2.6.16-rc3commit e9bb4c9929...Linus Torvalds20 years
v2.6.16-rc2commit 826eeb53a6...Linus Torvalds20 years
v2.6.16-rc1commit 2664b25051...Linus Torvalds20 years
v2.6.15commit 88026842b0...Linus Torvalds20 years
v2.6.15-rc7commit f89f5948fc...Linus Torvalds20 years
v2.6.15-rc6commit df7addbb45...Linus Torvalds20 years
v2.6.15-rc5commit 436b0f76f2...Linus Torvalds20 years
v2.6.15-rc4commit 5666c0947e...Linus Torvalds20 years
v2.6.15-rc3commit 624f54be20...Linus Torvalds20 years
v2.6.15-rc2commit 3bedff1d73...Linus Torvalds20 years
v2.6.15-rc1commit cd52d1ee9a...Linus Torvalds20 years
v2.6.14commit 741b2252a5...Linus Torvalds20 years
v2.6.14-rc5commit 93918e9afc...Linus Torvalds20 years
v2.6.14-rc4commit 907a426179...Linus Torvalds20 years
v2.6.14-rc3commit 1c9426e8a5...Linus Torvalds20 years
v2.6.14-rc2commit 676d55ae30...Linus Torvalds20 years
v2.6.14-rc1commit 2f4ba45a75...Linus Torvalds20 years
v2.6.13commit 02b3e4e2d7...Linus Torvalds20 years
v2.6.13-rc7commit 0572e3da3f...Linus Torvalds20 years
v2.6.13-rc6commit 6fc32179de...Linus Torvalds20 years
v2.6.13-rc5commit 9a351e30d7...Linus Torvalds20 years
v2.6.13-rc4commit 6395352334...Linus Torvalds20 years
v2.6.11tree c39ae07f39...
v2.6.11-treetree c39ae07f39...
v2.6.12commit 9ee1c939d1...
v2.6.12-rc2commit 1da177e4c3...
v2.6.12-rc3commit a2755a80f4...
v2.6.12-rc4commit 88d7bd8cb9...
v2.6.12-rc5commit 2a24ab628a...
v2.6.12-rc6commit 7cef5677ef...
v2.6.13-rc1commit 4c91aedb75...
v2.6.13-rc2commit a18bcb7450...
v2.6.13-rc3commit c32511e271...
an> NULL; int i; line = strtok_r(file, "\n", &next); while (line) { item = malloc_or_die(sizeof(*item)); sscanf(line, "%d %as", &item->pid, (float *)(void *)&item->comm); /* workaround gcc warning */ item->next = list; list = item; line = strtok_r(NULL, "\n", &next); cmdline_count++; } cmdlines = malloc_or_die(sizeof(*cmdlines) * cmdline_count); i = 0; while (list) { cmdlines[i].pid = list->pid; cmdlines[i].comm = list->comm; i++; item = list; list = list->next; free(item); } qsort(cmdlines, cmdline_count, sizeof(*cmdlines), cmdline_cmp); } static struct func_map { unsigned long long addr; char *func; char *mod; } *func_list; static unsigned int func_count; static int func_cmp(const void *a, const void *b) { const struct func_map *fa = a; const struct func_map *fb = b; if (fa->addr < fb->addr) return -1; if (fa->addr > fb->addr) return 1; return 0; } void parse_proc_kallsyms(char *file, unsigned int size __unused) { struct func_list { struct func_list *next; unsigned long long addr; char *func; char *mod; } *list = NULL, *item; char *line; char *next = NULL; char *addr_str; char ch; int ret __used; int i; line = strtok_r(file, "\n", &next); while (line) { item = malloc_or_die(sizeof(*item)); item->mod = NULL; ret = sscanf(line, "%as %c %as\t[%as", (float *)(void *)&addr_str, /* workaround gcc warning */ &ch, (float *)(void *)&item->func, (float *)(void *)&item->mod); item->addr = strtoull(addr_str, NULL, 16); free(addr_str); /* truncate the extra ']' */ if (item->mod) item->mod[strlen(item->mod) - 1] = 0; item->next = list; list = item; line = strtok_r(NULL, "\n", &next); func_count++; } func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1)); i = 0; while (list) { func_list[i].func = list->func; func_list[i].addr = list->addr; func_list[i].mod = list->mod; i++; item = list; list = list->next; free(item); } qsort(func_list, func_count, sizeof(*func_list), func_cmp); /* * Add a special record at the end. */ func_list[func_count].func = NULL; func_list[func_count].addr = 0; func_list[func_count].mod = NULL; } /* * We are searching for a record in between, not an exact * match. */ static int func_bcmp(const void *a, const void *b) { const struct func_map *fa = a; const struct func_map *fb = b; if ((fa->addr == fb->addr) || (fa->addr > fb->addr && fa->addr < (fb+1)->addr)) return 0; if (fa->addr < fb->addr) return -1; return 1; } static struct func_map *find_func(unsigned long long addr) { struct func_map *func; struct func_map key; key.addr = addr; func = bsearch(&key, func_list, func_count, sizeof(*func_list), func_bcmp); return func; } void print_funcs(void) { int i; for (i = 0; i < (int)func_count; i++) { printf("%016llx %s", func_list[i].addr, func_list[i].func); if (func_list[i].mod) printf(" [%s]\n", func_list[i].mod); else printf("\n"); } } static struct printk_map { unsigned long long addr; char *printk; } *printk_list; static unsigned int printk_count; static int printk_cmp(const void *a, const void *b) { const struct func_map *fa = a; const struct func_map *fb = b; if (fa->addr < fb->addr) return -1; if (fa->addr > fb->addr) return 1; return 0; } static struct printk_map *find_printk(unsigned long long addr) { struct printk_map *printk; struct printk_map key; key.addr = addr; printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list), printk_cmp); return printk; } void parse_ftrace_printk(char *file, unsigned int size __unused) { struct printk_list { struct printk_list *next; unsigned long long addr; char *printk; } *list = NULL, *item; char *line; char *next = NULL; char *addr_str; int i; line = strtok_r(file, "\n", &next); while (line) { addr_str = strsep(&line, ":"); if (!line) { warning("error parsing print strings"); break; } item = malloc_or_die(sizeof(*item)); item->addr = strtoull(addr_str, NULL, 16); /* fmt still has a space, skip it */ item->printk = strdup(line+1); item->next = list; list = item; line = strtok_r(NULL, "\n", &next); printk_count++; } printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1); i = 0; while (list) { printk_list[i].printk = list->printk; printk_list[i].addr = list->addr; i++; item = list; list = list->next; free(item); } qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp); } void print_printk(void) { int i; for (i = 0; i < (int)printk_count; i++) { printf("%016llx %s\n", printk_list[i].addr, printk_list[i].printk); } } static struct event *alloc_event(void) { struct event *event; event = malloc_or_die(sizeof(*event)); memset(event, 0, sizeof(*event)); return event; } enum event_type { EVENT_ERROR, EVENT_NONE, EVENT_SPACE, EVENT_NEWLINE, EVENT_OP, EVENT_DELIM, EVENT_ITEM, EVENT_DQUOTE, EVENT_SQUOTE, }; static struct event *event_list; static void add_event(struct event *event) { event->next = event_list; event_list = event; } static int event_item_type(enum event_type type) { switch (type) { case EVENT_ITEM ... EVENT_SQUOTE: return 1; case EVENT_ERROR ... EVENT_DELIM: default: return 0; } } static void free_arg(struct print_arg *arg) { if (!arg) return; switch (arg->type) { case PRINT_ATOM: if (arg->atom.atom) free(arg->atom.atom); break; case PRINT_NULL: case PRINT_FIELD ... PRINT_OP: default: /* todo */ break; } free(arg); } static enum event_type get_type(int ch) { if (ch == '\n') return EVENT_NEWLINE; if (isspace(ch)) return EVENT_SPACE; if (isalnum(ch) || ch == '_') return EVENT_ITEM; if (ch == '\'') return EVENT_SQUOTE; if (ch == '"') return EVENT_DQUOTE; if (!isprint(ch)) return EVENT_NONE; if (ch == '(' || ch == ')' || ch == ',') return EVENT_DELIM; return EVENT_OP; } static int __read_char(void) { if (input_buf_ptr >= input_buf_siz) return -1; return input_buf[input_buf_ptr++]; } static int __peek_char(void) { if (input_buf_ptr >= input_buf_siz) return -1; return input_buf[input_buf_ptr]; } static enum event_type __read_token(char **tok) { char buf[BUFSIZ]; int ch, last_ch, quote_ch, next_ch; int i = 0; int tok_size = 0; enum event_type type; *tok = NULL; ch = __read_char(); if (ch < 0) return EVENT_NONE; type = get_type(ch); if (type == EVENT_NONE) return type; buf[i++] = ch; switch (type) { case EVENT_NEWLINE: case EVENT_DELIM: *tok = malloc_or_die(2); (*tok)[0] = ch; (*tok)[1] = 0; return type; case EVENT_OP: switch (ch) { case '-': next_ch = __peek_char(); if (next_ch == '>') { buf[i++] = __read_char(); break; } /* fall through */ case '+': case '|': case '&': case '>': case '<': last_ch = ch; ch = __peek_char(); if (ch != last_ch) goto test_equal; buf[i++] = __read_char(); switch (last_ch) { case '>': case '<': goto test_equal; default: break; } break; case '!': case '=': goto test_equal; default: /* what should we do instead? */ break; } buf[i] = 0; *tok = strdup(buf); return type; test_equal: ch = __peek_char(); if (ch == '=') buf[i++] = __read_char(); break; case EVENT_DQUOTE: case EVENT_SQUOTE: /* don't keep quotes */ i--; quote_ch = ch; last_ch = 0; do { if (i == (BUFSIZ - 1)) { buf[i] = 0; if (*tok) { *tok = realloc(*tok, tok_size + BUFSIZ); if (!*tok) return EVENT_NONE; strcat(*tok, buf); } else *tok = strdup(buf); if (!*tok) return EVENT_NONE; tok_size += BUFSIZ; i = 0; } last_ch = ch; ch = __read_char(); buf[i++] = ch; /* the '\' '\' will cancel itself */ if (ch == '\\' && last_ch == '\\') last_ch = 0; } while (ch != quote_ch || last_ch == '\\'); /* remove the last quote */ i--; goto out; case EVENT_ERROR ... EVENT_SPACE: case EVENT_ITEM: default: break; } while (get_type(__peek_char()) == type) { if (i == (BUFSIZ - 1)) { buf[i] = 0; if (*tok) { *tok = realloc(*tok, tok_size + BUFSIZ); if (!*tok) return EVENT_NONE; strcat(*tok, buf); } else *tok = strdup(buf); if (!*tok) return EVENT_NONE; tok_size += BUFSIZ; i = 0; } ch = __read_char(); buf[i++] = ch; } out: buf[i] = 0; if (*tok) { *tok = realloc(*tok, tok_size + i); if (!*tok) return EVENT_NONE; strcat(*tok, buf); } else *tok = strdup(buf); if (!*tok) return EVENT_NONE; return type; } static void free_token(char *tok) { if (tok) free(tok); } static enum event_type read_token(char **tok) { enum event_type type; for (;;) { type = __read_token(tok); if (type != EVENT_SPACE) return type; free_token(*tok); } /* not reached */ return EVENT_NONE; } /* no newline */ static enum event_type read_token_item(char **tok) { enum event_type type; for (;;) { type = __read_token(tok); if (type != EVENT_SPACE && type != EVENT_NEWLINE) return type; free_token(*tok); } /* not reached */ return EVENT_NONE; } static int test_type(enum event_type type, enum event_type expect) { if (type != expect) { warning("Error: expected type %d but read %d", expect, type); return -1; } return 0; } static int __test_type_token(enum event_type type, char *token, enum event_type expect, const char *expect_tok, bool warn) { if (type != expect) { if (warn) warning("Error: expected type %d but read %d", expect, type); return -1; } if (strcmp(token, expect_tok) != 0) { if (warn) warning("Error: expected '%s' but read '%s'", expect_tok, token); return -1; } return 0; } static int test_type_token(enum event_type type, char *token, enum event_type expect, const char *expect_tok) { return __test_type_token(type, token, expect, expect_tok, true); } static int __read_expect_type(enum event_type expect, char **tok, int newline_ok) { enum event_type type; if (newline_ok) type = read_token(tok); else type = read_token_item(tok); return test_type(type, expect); } static int read_expect_type(enum event_type expect, char **tok) { return __read_expect_type(expect, tok, 1); } static int __read_expected(enum event_type expect, const char *str, int newline_ok, bool warn) { enum event_type type; char *token; int ret; if (newline_ok) type = read_token(&token); else type = read_token_item(&token); ret = __test_type_token(type, token, expect, str, warn); free_token(token); return ret; } static int read_expected(enum event_type expect, const char *str) { return __read_expected(expect, str, 1, true); } static int read_expected_item(enum event_type expect, const char *str) { return __read_expected(expect, str, 0, true); } static char *event_read_name(void) { char *token; if (read_expected(EVENT_ITEM, "name") < 0) return NULL; if (read_expected(EVENT_OP, ":") < 0) return NULL; if (read_expect_type(EVENT_ITEM, &token) < 0) goto fail; return token; fail: free_token(token); return NULL; } static int event_read_id(void) { char *token; int id; if (read_expected_item(EVENT_ITEM, "ID") < 0) return -1; if (read_expected(EVENT_OP, ":") < 0) return -1; if (read_expect_type(EVENT_ITEM, &token) < 0) goto fail; id = strtoul(token, NULL, 0); free_token(token); return id; fail: free_token(token); return -1; } static int field_is_string(struct format_field *field) { if ((field->flags & FIELD_IS_ARRAY) && (!strstr(field->type, "char") || !strstr(field->type, "u8") || !strstr(field->type, "s8"))) return 1; return 0; } static int field_is_dynamic(struct format_field *field) { if (!strncmp(field->type, "__data_loc", 10)) return 1; return 0; } static int event_read_fields(struct event *event, struct format_field **fields) { struct format_field *field = NULL; enum event_type type; char *token; char *last_token; int count = 0; do { type = read_token(&token); if (type == EVENT_NEWLINE) { free_token(token); return count; } count++; if (test_type_token(type, token, EVENT_ITEM, "field")) goto fail; free_token(token); type = read_token(&token); /* * The ftrace fields may still use the "special" name. * Just ignore it. */ if (event->flags & EVENT_FL_ISFTRACE && type == EVENT_ITEM && strcmp(token, "special") == 0) { free_token(token); type = read_token(&token); } if (test_type_token(type, token, EVENT_OP, ":") < 0) return -1; if (read_expect_type(EVENT_ITEM, &token) < 0) goto fail; last_token = token; field = malloc_or_die(sizeof(*field)); memset(field, 0, sizeof(*field)); /* read the rest of the type */ for (;;) { type = read_token(&token); if (type == EVENT_ITEM || (type == EVENT_OP && strcmp(token, "*") == 0) || /* * Some of the ftrace fields are broken and have * an illegal "." in them. */ (event->flags & EVENT_FL_ISFTRACE && type == EVENT_OP && strcmp(token, ".") == 0)) { if (strcmp(token, "*") == 0) field->flags |= FIELD_IS_POINTER; if (field->type) { field->type = realloc(field->type, strlen(field->type) + strlen(last_token) + 2); strcat(field->type, " "); strcat(field->type, last_token); } else field->type = last_token; last_token = token; continue; } break; } if (!field->type) { die("no type found"); goto fail; } field->name = last_token; if (test_type(type, EVENT_OP)) goto fail; if (strcmp(token, "[") == 0) { enum event_type last_type = type; char *brackets = token; int len; field->flags |= FIELD_IS_ARRAY; type = read_token(&token); while (strcmp(token, "]") != 0) { if (last_type == EVENT_ITEM && type == EVENT_ITEM) len = 2; else len = 1; last_type = type; brackets = realloc(brackets, strlen(brackets) + strlen(token) + len); if (len == 2) strcat(brackets, " "); strcat(brackets, token); free_token(token); type = read_token(&token); if (type == EVENT_NONE) { die("failed to find token"); goto fail; } } free_token(token); brackets = realloc(brackets, strlen(brackets) + 2); strcat(brackets, "]"); /* add brackets to type */ type = read_token(&token); /* * If the next token is not an OP, then it is of * the format: type [] item; */ if (type == EVENT_ITEM) { field->type = realloc(field->type, strlen(field->type) + strlen(field->name) + strlen(brackets) + 2); strcat(field->type, " "); strcat(field->type, field->name); free_token(field->name); strcat(field->type, brackets); field->name = token; type = read_token(&token); } else { field->type = realloc(field->type, strlen(field->type) + strlen(brackets) + 1); strcat(field->type, brackets); } free(brackets); } if (field_is_string(field)) { field->flags |= FIELD_IS_STRING; if (field_is_dynamic(field)) field->flags |= FIELD_IS_DYNAMIC; } if (test_type_token(type, token, EVENT_OP, ";")) goto fail; free_token(token); if (read_expected(EVENT_ITEM, "offset") < 0) goto fail_expect; if (read_expected(EVENT_OP, ":") < 0) goto fail_expect; if (read_expect_type(EVENT_ITEM, &token)) goto fail; field->offset = strtoul(token, NULL, 0); free_token(token); if (read_expected(EVENT_OP, ";") < 0) goto fail_expect; if (read_expected(EVENT_ITEM, "size") < 0) goto fail_expect; if (read_expected(EVENT_OP, ":") < 0) goto fail_expect; if (read_expect_type(EVENT_ITEM, &token)) goto fail; field->size = strtoul(token, NULL, 0); free_token(token); if (read_expected(EVENT_OP, ";") < 0) goto fail_expect; type = read_token(&token); if (type != EVENT_NEWLINE) { /* newer versions of the kernel have a "signed" type */ if (test_type_token(type, token, EVENT_ITEM, "signed")) goto fail; free_token(token); if (read_expected(EVENT_OP, ":") < 0) goto fail_expect; if (read_expect_type(EVENT_ITEM, &token)) goto fail; if (strtoul(token, NULL, 0)) field->flags |= FIELD_IS_SIGNED; free_token(token); if (read_expected(EVENT_OP, ";") < 0) goto fail_expect; if (read_expect_type(EVENT_NEWLINE, &token)) goto fail; } free_token(token); *fields = field; fields = &field->next; } while (1); return 0; fail: free_token(token); fail_expect: if (field) free(field); return -1; } static int event_read_format(struct event *event) { char *token; int ret; if (read_expected_item(EVENT_ITEM, "format") < 0) return -1; if (read_expected(EVENT_OP, ":") < 0) return -1; if (read_expect_type(EVENT_NEWLINE, &token)) goto fail; free_token(token); ret = event_read_fields(event, &event->format.common_fields); if (ret < 0) return ret; event->format.nr_common = ret; ret = event_read_fields(event, &event->format.fields); if (ret < 0) return ret; event->format.nr_fields = ret; return 0; fail: free_token(token); return -1; } enum event_type process_arg_token(struct event *event, struct print_arg *arg, char **tok, enum event_type type); static enum event_type process_arg(struct event *event, struct print_arg *arg, char **tok) { enum event_type type; char *token; type = read_token(&token); *tok = token; return process_arg_token(event, arg, tok, type); } static enum event_type process_cond(struct event *event, struct print_arg *top, char **tok) { struct print_arg *arg, *left, *right; enum event_type type; char *token = NULL; arg = malloc_or_die(sizeof(*arg)); memset(arg, 0, sizeof(*arg)); left = malloc_or_die(sizeof(*left)); right = malloc_or_die(sizeof(*right)); arg->type = PRINT_OP; arg->op.left = left; arg->op.right = right; *tok = NULL; type = process_arg(event, left, &token); if (test_type_token(type, token, EVENT_OP, ":")) goto out_free; arg->op.op = token; type = process_arg(event, right, &token); top->op.right = arg; *tok = token; return type; out_free: free_token(*tok); free(right); free(left); free_arg(arg); return EVENT_ERROR; } static enum event_type process_array(struct event *event, struct print_arg *top, char **tok) { struct print_arg *arg; enum event_type type; char *token = NULL; arg = malloc_or_die(sizeof(*arg)); memset(arg, 0, sizeof(*arg)); *tok = NULL; type = process_arg(event, arg, &token); if (test_type_token(type, token, EVENT_OP, "]")) goto out_free; top->op.right = arg; free_token(token); type = read_token_item(&token); *tok = token; return type; out_free: free_token(*tok); free_arg(arg); return EVENT_ERROR; } static int get_op_prio(char *op) { if (!op[1]) { switch (op[0]) { case '*': case '/': case '%': return 6; case '+': case '-': return 7; /* '>>' and '<<' are 8 */ case '<': case '>': return 9; /* '==' and '!=' are 10 */ case '&': return 11; case '^': return 12; case '|': return 13; case '?': return 16; default: die("unknown op '%c'", op[0]); return -1; } } else { if (strcmp(op, "++") == 0 || strcmp(op, "--") == 0) { return 3; } else if (strcmp(op, ">>") == 0 || strcmp(op, "<<") == 0) { return 8; } else if (strcmp(op, ">=") == 0 || strcmp(op, "<=") == 0) { return 9; } else if (strcmp(op, "==") == 0 || strcmp(op, "!=") == 0) { return 10; } else if (strcmp(op, "&&") == 0) { return 14; } else if (strcmp(op, "||") == 0) { return 15; } else { die("unknown op '%s'", op); return -1; } } } static void set_op_prio(struct print_arg *arg) { /* single ops are the greatest */ if (!arg->op.left || arg->op.left->type == PRINT_NULL) { arg->op.prio = 0; return; } arg->op.prio = get_op_prio(arg->op.op); } static enum event_type process_op(struct event *event, struct print_arg *arg, char **tok) { struct print_arg *left, *right = NULL; enum event_type type; char *token; /* the op is passed in via tok */ token = *tok; if (arg->type == PRINT_OP && !arg->op.left) { /* handle single op */ if (token[1]) { die("bad op token %s", token); return EVENT_ERROR; } switch (token[0]) { case '!': case '+': case '-': break; default: die("bad op token %s", token); return EVENT_ERROR; } /* make an empty left */ left = malloc_or_die(sizeof(*left)); left->type = PRINT_NULL; arg->op.left = left; right = malloc_or_die(sizeof(*right)); arg->op.right = right; type = process_arg(event, right, tok); } else if (strcmp(token, "?") == 0) { left = malloc_or_die(sizeof(*left)); /* copy the top arg to the left */ *left = *arg; arg->type = PRINT_OP; arg->op.op = token; arg->op.left = left; arg->op.prio = 0; type = process_cond(event, arg, tok); } else if (strcmp(token, ">>") == 0 || strcmp(token, "<<") == 0 || strcmp(token, "&") == 0 || strcmp(token, "|") == 0 || strcmp(token, "&&") == 0 || strcmp(token, "||") == 0 || strcmp(token, "-") == 0 || strcmp(token, "+") == 0 || strcmp(token, "*") == 0 || strcmp(token, "^") == 0 || strcmp(token, "/") == 0 || strcmp(token, "<") == 0 || strcmp(token, ">") == 0 || strcmp(token, "==") == 0 || strcmp(token, "!=") == 0) { left = malloc_or_die(sizeof(*left)); /* copy the top arg to the left */ *left = *arg; arg->type = PRINT_OP; arg->op.op = token; arg->op.left = left; set_op_prio(arg); right = malloc_or_die(sizeof(*right)); type = read_token_item(&token); *tok = token; /* could just be a type pointer */ if ((strcmp(arg->op.op, "*") == 0) && type == EVENT_DELIM && (strcmp(token, ")") == 0)) { if (left->type != PRINT_ATOM) die("bad pointer type"); left->atom.atom = realloc(left->atom.atom, sizeof(left->atom.atom) + 3); strcat(left->atom.atom, " *"); *arg = *left; free(arg); return type; } type = process_arg_token(event, right, tok, type); arg->op.right = right; } else if (strcmp(token, "[") == 0) { left = malloc_or_die(sizeof(*left)); *left = *arg; arg->type = PRINT_OP; arg->op.op = token; arg->op.left = left; arg->op.prio = 0; type = process_array(event, arg, tok); } else { warning("unknown op '%s'", token); event->flags |= EVENT_FL_FAILED; /* the arg is now the left side */ return EVENT_NONE; } if (type == EVENT_OP) { int prio; /* higher prios need to be closer to the root */ prio = get_op_prio(*tok); if (prio > arg->op.prio) return process_op(event, arg, tok); return process_op(event, right, tok); } return type; } static enum event_type process_entry(struct event *event __unused, struct print_arg *arg, char **tok) { enum event_type type; char *field; char *token; if (read_expected(EVENT_OP, "->") < 0) return EVENT_ERROR; if (read_expect_type(EVENT_ITEM, &token) < 0) goto fail; field = token; arg->type = PRINT_FIELD; arg->field.name = field; if (is_flag_field) { arg->field.field = find_any_field(event, arg->field.name); arg->field.field->flags |= FIELD_IS_FLAG; is_flag_field = 0; } else if (is_symbolic_field) { arg->field.field = find_any_field(event, arg->field.name); arg->field.field->flags |= FIELD_IS_SYMBOLIC; is_symbolic_field = 0; } type = read_token(&token); *tok = token; return type; fail: free_token(token); return EVENT_ERROR; } static char *arg_eval (struct print_arg *arg); static long long arg_num_eval(struct print_arg *arg) { long long left, right; long long val = 0; switch (arg->type) { case PRINT_ATOM: val = strtoll(arg->atom.atom, NULL, 0); break; case PRINT_TYPE: val = arg_num_eval(arg->typecast.item); break; case PRINT_OP: switch (arg->op.op[0]) { case '|': left = arg_num_eval(arg->op.left); right = arg_num_eval(arg->op.right); if (arg->op.op[1]) val = left || right; else val = left | right; break; case '&': left = arg_num_eval(arg->op.left); right = arg_num_eval(arg->op.right); if (arg->op.op[1]) val = left && right; else val = left & right; break; case '<': left = arg_num_eval(arg->op.left); right = arg_num_eval(arg->op.right); switch (arg->op.op[1]) { case 0: val = left < right; break; case '<': val = left << right; break; case '=': val = left <= right; break; default: die("unknown op '%s'", arg->op.op); } break; case '>': left = arg_num_eval(arg->op.left); right = arg_num_eval(arg->op.right); switch (arg->op.op[1]) { case 0: val = left > right; break; case '>': val = left >> right; break; case '=': val = left >= right; break; default: die("unknown op '%s'", arg->op.op); } break; case '=': left = arg_num_eval(arg->op.left); right = arg_num_eval(arg->op.right); if (arg->op.op[1] != '=') die("unknown op '%s'", arg->op.op); val = left == right; break; case '!': left = arg_num_eval(arg->op.left); right = arg_num_eval(arg->op.right); switch (arg->op.op[1]) { case '=': val = left != right; break; default: die("unknown op '%s'", arg->op.op); } break; default: die("unknown op '%s'", arg->op.op); } break; case PRINT_NULL: case PRINT_FIELD ... PRINT_SYMBOL: case PRINT_STRING: default: die("invalid eval type %d", arg->type); } return val; } static char *arg_eval (struct print_arg *arg) { long long val; static char buf[20]; switch (arg->type) { case PRINT_ATOM: return arg->atom.atom; case PRINT_TYPE: return arg_eval(arg->typecast.item); case PRINT_OP: val = arg_num_eval(arg); sprintf(buf, "%lld", val); return buf; case PRINT_NULL: case PRINT_FIELD ... PRINT_SYMBOL: case PRINT_STRING: default: die("invalid eval type %d", arg->type); break; } return NULL; } static enum event_type process_fields(struct event *event, struct print_flag_sym **list, char **tok) { enum event_type type; struct print_arg *arg = NULL; struct print_flag_sym *field; char *token = NULL; char *value; do { free_token(token); type = read_token_item(&token); if (test_type_token(type, token, EVENT_OP, "{")) break; arg = malloc_or_die(sizeof(*arg)); free_token(token); type = process_arg(event, arg, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free; field = malloc_or_die(sizeof(*field)); memset(field, 0, sizeof(*field)); value = arg_eval(arg); field->value = strdup(value); free_token(token); type = process_arg(event, arg, &token); if (test_type_token(type, token, EVENT_OP, "}")) goto out_free; value = arg_eval(arg); field->str = strdup(value); free_arg(arg); arg = NULL; *list = field; list = &field->next; free_token(token); type = read_token_item(&token); } while (type == EVENT_DELIM && strcmp(token, ",") == 0); *tok = token; return type; out_free: free_arg(arg); free_token(token); return EVENT_ERROR; } static enum event_type process_flags(struct event *event, struct print_arg *arg, char **tok) { struct print_arg *field; enum event_type type; char *token; memset(arg, 0, sizeof(*arg)); arg->type = PRINT_FLAGS; if (read_expected_item(EVENT_DELIM, "(") < 0) return EVENT_ERROR; field = malloc_or_die(sizeof(*field)); type = process_arg(event, field, &token); while (type == EVENT_OP) type = process_op(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free; arg->flags.field = field; type = read_token_item(&token); if (event_item_type(type)) { arg->flags.delim = token; type = read_token_item(&token); } if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free; type = process_fields(event, &arg->flags.flags, &token); if (test_type_token(type, token, EVENT_DELIM, ")")) goto out_free; free_token(token); type = read_token_item(tok); return type; out_free: free_token(token); return EVENT_ERROR; } static enum event_type process_symbols(struct event *event, struct print_arg *arg, char **tok) { struct print_arg *field; enum event_type type; char *token; memset(arg, 0, sizeof(*arg)); arg->type = PRINT_SYMBOL; if (read_expected_item(EVENT_DELIM, "(") < 0) return EVENT_ERROR; field = malloc_or_die(sizeof(*field)); type = process_arg(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free; arg->symbol.field = field; type = process_fields(event, &arg->symbol.symbols, &token); if (test_type_token(type, token, EVENT_DELIM, ")")) goto out_free; free_token(token); type = read_token_item(tok); return type; out_free: free_token(token); return EVENT_ERROR; } static enum event_type process_paren(struct event *event, struct print_arg *arg, char **tok) { struct print_arg *item_arg; enum event_type type; char *token; type = process_arg(event, arg, &token); if (type == EVENT_ERROR) return EVENT_ERROR; if (type == EVENT_OP) type = process_op(event, arg, &token); if (type == EVENT_ERROR) return EVENT_ERROR; if (test_type_token(type, token, EVENT_DELIM, ")")) { free_token(token); return EVENT_ERROR; } free_token(token); type = read_token_item(&token); /* * If the next token is an item or another open paren, then * this was a typecast. */ if (event_item_type(type) || (type == EVENT_DELIM && strcmp(token, "(") == 0)) { /* make this a typecast and contine */ /* prevous must be an atom */ if (arg->type != PRINT_ATOM) die("previous needed to be PRINT_ATOM"); item_arg = malloc_or_die(sizeof(*item_arg)); arg->type = PRINT_TYPE; arg->typecast.type = arg->atom.atom; arg->typecast.item = item_arg; type = process_arg_token(event, item_arg, &token, type); } *tok = token; return type; } static enum event_type process_str(struct event *event __unused, struct print_arg *arg, char **tok) { enum event_type type; char *token; if (read_expected(EVENT_DELIM, "(") < 0) return EVENT_ERROR; if (read_expect_type(EVENT_ITEM, &token) < 0) goto fail; arg->type = PRINT_STRING; arg->string.string = token; arg->string.offset = -1; if (read_expected(EVENT_DELIM, ")") < 0) return EVENT_ERROR; type = read_token(&token); *tok = token; return type; fail: free_token(token); return EVENT_ERROR; } enum event_type process_arg_token(struct event *event, struct print_arg *arg, char **tok, enum event_type type) { char *token; char *atom; token = *tok; switch (type) { case EVENT_ITEM: if (strcmp(token, "REC") == 0) { free_token(token); type = process_entry(event, arg, &token); } else if (strcmp(token, "__print_flags") == 0) { free_token(token); is_flag_field = 1; type = process_flags(event, arg, &token); } else if (strcmp(token, "__print_symbolic") == 0) { free_token(token); is_symbolic_field = 1; type = process_symbols(event, arg, &token); } else if (strcmp(token, "__get_str") == 0) { free_token(token); type = process_str(event, arg, &token); } else { atom = token; /* test the next token */ type = read_token_item(&token); /* atoms can be more than one token long */ while (type == EVENT_ITEM) { atom = realloc(atom, strlen(atom) + strlen(token) + 2); strcat(atom, " "); strcat(atom, token); free_token(token); type = read_token_item(&token); } /* todo, test for function */ arg->type = PRINT_ATOM; arg->atom.atom = atom; } break; case EVENT_DQUOTE: case EVENT_SQUOTE: arg->type = PRINT_ATOM; arg->atom.atom = token; type = read_token_item(&token); break; case EVENT_DELIM: if (strcmp(token, "(") == 0) { free_token(token); type = process_paren(event, arg, &token); break; } case EVENT_OP: /* handle single ops */ arg->type = PRINT_OP; arg->op.op = token; arg->op.left = NULL; type = process_op(event, arg, &token); break; case EVENT_ERROR ... EVENT_NEWLINE: default: die("unexpected type %d", type); } *tok = token; return type; } static int event_read_print_args(struct event *event, struct print_arg **list) { enum event_type type = EVENT_ERROR; struct print_arg *arg; char *token; int args = 0; do { if (type == EVENT_NEWLINE) { free_token(token); type = read_token_item(&token); continue; } arg = malloc_or_die(sizeof(*arg)); memset(arg, 0, sizeof(*arg)); type = process_arg(event, arg, &token); if (type == EVENT_ERROR) { free_arg(arg); return -1; } *list = arg; args++; if (type == EVENT_OP) { type = process_op(event, arg, &token); list = &arg->next; continue; } if (type == EVENT_DELIM && strcmp(token, ",") == 0) { free_token(token); *list = arg; list = &arg->next; continue; } break; } while (type != EVENT_NONE); if (type != EVENT_NONE) free_token(token); return args; } static int event_read_print(struct event *event) { enum event_type type; char *token; int ret; if (read_expected_item(EVENT_ITEM, "print") < 0) return -1; if (read_expected(EVENT_ITEM, "fmt") < 0) return -1; if (read_expected(EVENT_OP, ":") < 0) return -1; if (read_expect_type(EVENT_DQUOTE, &token) < 0) goto fail; concat: event->print_fmt.format = token; event->print_fmt.args = NULL; /* ok to have no arg */ type = read_token_item(&token); if (type == EVENT_NONE) return 0; /* Handle concatination of print lines */ if (type == EVENT_DQUOTE) { char *cat; cat = malloc_or_die(strlen(event->print_fmt.format) + strlen(token) + 1); strcpy(cat, event->print_fmt.format); strcat(cat, token); free_token(token); free_token(event->print_fmt.format); event->print_fmt.format = NULL; token = cat; goto concat; } if (test_type_token(type, token, EVENT_DELIM, ",")) goto fail; free_token(token); ret = event_read_print_args(event, &event->print_fmt.args); if (ret < 0) return -1; return ret; fail: free_token(token); return -1; } static struct format_field * find_common_field(struct event *event, const char *name) { struct format_field *format; for (format = event->format.common_fields; format; format = format->next) { if (strcmp(format->name, name) == 0) break; } return format; } static struct format_field * find_field(struct event *event, const char *name) { struct format_field *format; for (format = event->format.fields; format; format = format->next) { if (strcmp(format->name, name) == 0) break; } return format; } static struct format_field * find_any_field(struct event *event, const char *name) { struct format_field *format; format = find_common_field(event, name); if (format) return format; return find_field(event, name); } unsigned long long read_size(void *ptr, int size) { switch (size) { case 1: return *(unsigned char *)ptr; case 2: return data2host2(ptr); case 4: return data2host4(ptr); case 8: return data2host8(ptr); default: /* BUG! */ return 0; } } unsigned long long raw_field_value(struct event *event, const char *name, void *data) { struct format_field *field; field = find_any_field(event, name); if (!field) return 0ULL; return read_size(data + field->offset, field->size); } void *raw_field_ptr(struct event *event, const char *name, void *data) { struct format_field *field; field = find_any_field(event, name); if (!field) return NULL; if (field->flags & FIELD_IS_DYNAMIC) { int offset; offset = *(int *)(data + field->offset); offset &= 0xffff; return data + offset; } return data + field->offset; } static int get_common_info(const char *type, int *offset, int *size) { struct event *event; struct format_field *field; /* * All events should have the same common elements. * Pick any event to find where the type is; */ if (!event_list) die("no event_list!"); event = event_list; field = find_common_field(event, type); if (!field) die("field '%s' not found", type); *offset = field->offset; *size = field->size; return 0; } static int __parse_common(void *data, int *size, int *offset, const char *name) { int ret; if (!*size) { ret = get_common_info(name, offset, size); if (ret < 0) return ret; } return read_size(data + *offset, *size); } int trace_parse_common_type(void *data) { static int type_offset; static int type_size; return __parse_common(data, &type_size, &type_offset, "common_type"); } int trace_parse_common_pid(void *data) { static int pid_offset; static int pid_size; return __parse_common(data, &pid_size, &pid_offset, "common_pid"); } int parse_common_pc(void *data) { static int pc_offset; static int pc_size; return __parse_common(data, &pc_size, &pc_offset, "common_preempt_count"); } int parse_common_flags(void *data) { static int flags_offset; static int flags_size; return __parse_common(data, &flags_size, &flags_offset, "common_flags"); } int parse_common_lock_depth(void *data) { static int ld_offset; static int ld_size; int ret; ret = __parse_common(data, &ld_size, &ld_offset, "common_lock_depth"); if (ret < 0) return -1; return ret; } struct event *trace_find_event(int id) { struct event *event; for (event = event_list; event; event = event->next) { if (event->id == id) break; } return event; } struct event *trace_find_next_event(struct event *event) { if (!event) return event_list; return event->next; } static unsigned long long eval_num_arg(void *data, int size, struct event *event, struct print_arg *arg) { unsigned long long val = 0; unsigned long long left, right; struct print_arg *larg; switch (arg->type) { case PRINT_NULL: /* ?? */ return 0; case PRINT_ATOM: return strtoull(arg->atom.atom, NULL, 0); case PRINT_FIELD: if (!arg->field.field) { arg->field.field = find_any_field(event, arg->field.name); if (!arg->field.field) die("field %s not found", arg->field.name); } /* must be a number */ val = read_size(data + arg->field.field->offset, arg->field.field->size); break; case PRINT_FLAGS: case PRINT_SYMBOL: break; case PRINT_TYPE: return eval_num_arg(data, size, event, arg->typecast.item); case PRINT_STRING: return 0; break; case PRINT_OP: if (strcmp(arg->op.op, "[") == 0) { /* * Arrays are special, since we don't want * to read the arg as is. */ if (arg->op.left->type != PRINT_FIELD) goto default_op; /* oops, all bets off */ larg = arg->op.left; if (!larg->field.field) { larg->field.field = find_any_field(event, larg->field.name); if (!larg->field.field) die("field %s not found", larg->field.name); } right = eval_num_arg(data, size, event, arg->op.right); val = read_size(data + larg->field.field->offset + right * long_size, long_size); break; } default_op: left = eval_num_arg(data, size, event, arg->op.left); right = eval_num_arg(data, size, event, arg->op.right); switch (arg->op.op[0]) { case '|': if (arg->op.op[1]) val = left || right; else val = left | right; break; case '&': if (arg->op.op[1]) val = left && right; else val = left & right; break; case '<': switch (arg->op.op[1]) { case 0: val = left < right; break; case '<': val = left << right; break; case '=': val = left <= right; break; default: die("unknown op '%s'", arg->op.op); } break; case '>': switch (arg->op.op[1]) { case 0: val = left > right; break; case '>': val = left >> right; break; case '=': val = left >= right; break; default: die("unknown op '%s'", arg->op.op); } break; case '=': if (arg->op.op[1] != '=') die("unknown op '%s'", arg->op.op); val = left == right; break; case '-': val = left - right; break; case '+': val = left + right; break; default: die("unknown op '%s'", arg->op.op); } break; default: /* not sure what to do there */ return 0; } return val; } struct flag { const char *name; unsigned long long value; }; static const struct flag flags[] = { { "HI_SOFTIRQ", 0 }, { "TIMER_SOFTIRQ", 1 }, { "NET_TX_SOFTIRQ", 2 }, { "NET_RX_SOFTIRQ", 3 }, { "BLOCK_SOFTIRQ", 4 }, { "BLOCK_IOPOLL_SOFTIRQ", 5 }, { "TASKLET_SOFTIRQ", 6 }, { "SCHED_SOFTIRQ", 7 }, { "HRTIMER_SOFTIRQ", 8 }, { "RCU_SOFTIRQ", 9 }, { "HRTIMER_NORESTART", 0 }, { "HRTIMER_RESTART", 1 }, }; unsigned long long eval_flag(const char *flag) { int i; /* * Some flags in the format files do not get converted. * If the flag is not numeric, see if it is something that * we already know about. */ if (isdigit(flag[0])) return strtoull(flag, NULL, 0); for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) if (strcmp(flags[i].name, flag) == 0) return flags[i].value; return 0; } static void print_str_arg(void *data, int size, struct event *event, struct print_arg *arg) { struct print_flag_sym *flag; unsigned long long val, fval; char *str; int print; switch (arg->type) { case PRINT_NULL: /* ?? */ return; case PRINT_ATOM: printf("%s", arg->atom.atom); return; case PRINT_FIELD: if (!arg->field.field) { arg->field.field = find_any_field(event, arg->field.name); if (!arg->field.field) die("field %s not found", arg->field.name); } str = malloc_or_die(arg->field.field->size + 1); memcpy(str, data + arg->field.field->offset, arg->field.field->size); str[arg->field.field->size] = 0; printf("%s", str); free(str); break; case PRINT_FLAGS: val = eval_num_arg(data, size, event, arg->flags.field); print = 0; for (flag = arg->flags.flags; flag; flag = flag->next) { fval = eval_flag(flag->value); if (!val && !fval) { printf("%s", flag->str); break; } if (fval && (val & fval) == fval) { if (print && arg->flags.delim) printf("%s", arg->flags.delim); printf("%s", flag->str); print = 1; val &= ~fval; } } break; case PRINT_SYMBOL: val = eval_num_arg(data, size, event, arg->symbol.field); for (flag = arg->symbol.symbols; flag; flag = flag->next) { fval = eval_flag(flag->value); if (val == fval) { printf("%s", flag->str); break; } } break; case PRINT_TYPE: break; case PRINT_STRING: { int str_offset; if (arg->string.offset == -1) { struct format_field *f; f = find_any_field(event, arg->string.string); arg->string.offset = f->offset; } str_offset = *(int *)(data + arg->string.offset); str_offset &= 0xffff; printf("%s", ((char *)data) + str_offset); break; } case PRINT_OP: /* * The only op for string should be ? : */ if (arg->op.op[0] != '?') return; val = eval_num_arg(data, size, event, arg->op.left); if (val) print_str_arg(data, size, event, arg->op.right->op.left); else print_str_arg(data, size, event, arg->op.right->op.right); break; default: /* well... */ break; } } static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event) { static struct format_field *field, *ip_field; struct print_arg *args, *arg, **next; unsigned long long ip, val; char *ptr; void *bptr; if (!field) { field = find_field(event, "buf"); if (!field) die("can't find buffer field for binary printk"); ip_field = find_field(event, "ip"); if (!ip_field) die("can't find ip field for binary printk"); } ip = read_size(data + ip_field->offset, ip_field->size); /* * The first arg is the IP pointer. */ args = malloc_or_die(sizeof(*args)); arg = args; arg->next = NULL; next = &arg->next; arg->type = PRINT_ATOM; arg->atom.atom = malloc_or_die(32); sprintf(arg->atom.atom, "%lld", ip); /* skip the first "%pf : " */ for (ptr = fmt + 6, bptr = data + field->offset; bptr < data + size && *ptr; ptr++) { int ls = 0; if (*ptr == '%') { process_again: ptr++; switch (*ptr) { case '%': break; case 'l': ls++; goto process_again; case 'L': ls = 2; goto process_again; case '0' ... '9': goto process_again; case 'p': ls = 1; /* fall through */ case 'd': case 'u': case 'x': case 'i': /* the pointers are always 4 bytes aligned */ bptr = (void *)(((unsigned long)bptr + 3) & ~3); switch (ls) { case 0: case 1: ls = long_size; break; case 2: ls = 8; default: break; } val = read_size(bptr, ls); bptr += ls; arg = malloc_or_die(sizeof(*arg)); arg->next = NULL; arg->type = PRINT_ATOM; arg->atom.atom = malloc_or_die(32); sprintf(arg->atom.atom, "%lld", val); *next = arg; next = &arg->next; break; case 's': arg = malloc_or_die(sizeof(*arg)); arg->next = NULL; arg->type = PRINT_STRING; arg->string.string = strdup(bptr); bptr += strlen(bptr) + 1; *next = arg; next = &arg->next; default: break; } } } return args; } static void free_args(struct print_arg *args) { struct print_arg *next; while (args) { next = args->next; if (args->type == PRINT_ATOM) free(args->atom.atom); else free(args->string.string); free(args); args = next; } } static char *get_bprint_format(void *data, int size __unused, struct event *event) { unsigned long long addr; static struct format_field *field; struct printk_map *printk; char *format; char *p; if (!field) { field = find_field(event, "fmt"); if (!field) die("can't find format field for binary printk"); printf("field->offset = %d size=%d\n", field->offset, field->size); } addr = read_size(data + field->offset, field->size); printk = find_printk(addr); if (!printk) { format = malloc_or_die(45); sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr); return format; } p = printk->printk; /* Remove any quotes. */ if (*p == '"') p++; format = malloc_or_die(strlen(p) + 10); sprintf(format, "%s : %s", "%pf", p); /* remove ending quotes and new line since we will add one too */ p = format + strlen(format) - 1; if (*p == '"') *p = 0; p -= 2; if (strcmp(p, "\\n") == 0) *p = 0; return format; } static void pretty_print(void *data, int size, struct event *event) { struct print_fmt *print_fmt = &event->print_fmt; struct print_arg *arg = print_fmt->args; struct print_arg *args = NULL; const char *ptr = print_fmt->format; unsigned long long val; struct func_map *func; const char *saveptr; char *bprint_fmt = NULL; char format[32]; int show_func; int len; int ls; if (event->flags & EVENT_FL_ISFUNC) ptr = " %pF <-- %pF"; if (event->flags & EVENT_FL_ISBPRINT) { bprint_fmt = get_bprint_format(data, size, event); args = make_bprint_args(bprint_fmt, data, size, event); arg = args; ptr = bprint_fmt; } for (; *ptr; ptr++) { ls = 0; if (*ptr == '\\') { ptr++; switch (*ptr) { case 'n': printf("\n"); break; case 't': printf("\t"); break; case 'r': printf("\r"); break; case '\\': printf("\\"); break; default: printf("%c", *ptr); break; } } else if (*ptr == '%') { saveptr = ptr; show_func = 0; cont_process: ptr++; switch (*ptr) { case '%': printf("%%");