@mytechtoday/augment-extensions 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/augment-extensions/coding-standards/c/CHANGELOG.md +55 -0
- package/augment-extensions/coding-standards/c/LICENSE +22 -0
- package/augment-extensions/coding-standards/c/README.md +167 -0
- package/augment-extensions/coding-standards/c/config/defaults.json +26 -0
- package/augment-extensions/coding-standards/c/config/examples/embedded.yaml +25 -0
- package/augment-extensions/coding-standards/c/config/examples/systems.json +31 -0
- package/augment-extensions/coding-standards/c/config/schema.json +244 -0
- package/augment-extensions/coding-standards/c/docs/API.md +613 -0
- package/augment-extensions/coding-standards/c/docs/CONFIGURATION.md +259 -0
- package/augment-extensions/coding-standards/c/docs/USER_GUIDE.md +567 -0
- package/augment-extensions/coding-standards/c/examples/drivers/Makefile +33 -0
- package/augment-extensions/coding-standards/c/examples/drivers/README.md +192 -0
- package/augment-extensions/coding-standards/c/examples/drivers/dma-example.c +224 -0
- package/augment-extensions/coding-standards/c/examples/drivers/example.dts +64 -0
- package/augment-extensions/coding-standards/c/examples/drivers/platform-driver.c +174 -0
- package/augment-extensions/coding-standards/c/examples/embedded/README.md +167 -0
- package/augment-extensions/coding-standards/c/examples/embedded/gpio-control.c +172 -0
- package/augment-extensions/coding-standards/c/examples/embedded/timer-isr.c +198 -0
- package/augment-extensions/coding-standards/c/examples/embedded/uart-communication.c +212 -0
- package/augment-extensions/coding-standards/c/examples/kernel/Makefile +82 -0
- package/augment-extensions/coding-standards/c/examples/kernel/README.md +168 -0
- package/augment-extensions/coding-standards/c/examples/kernel/char-device.c +198 -0
- package/augment-extensions/coding-standards/c/examples/kernel/proc-file.c +131 -0
- package/augment-extensions/coding-standards/c/examples/kernel/simple-module.c +111 -0
- package/augment-extensions/coding-standards/c/examples/legacy/Makefile +62 -0
- package/augment-extensions/coding-standards/c/examples/legacy/README.md +255 -0
- package/augment-extensions/coding-standards/c/examples/legacy/c89-to-c11-migration.c +268 -0
- package/augment-extensions/coding-standards/c/examples/legacy/compatibility-layer.c +239 -0
- package/augment-extensions/coding-standards/c/examples/networking/Makefile +35 -0
- package/augment-extensions/coding-standards/c/examples/networking/README.md +207 -0
- package/augment-extensions/coding-standards/c/examples/networking/protocol-parser.c +270 -0
- package/augment-extensions/coding-standards/c/examples/networking/tcp-server.c +197 -0
- package/augment-extensions/coding-standards/c/examples/networking/udp-multicast.c +220 -0
- package/augment-extensions/coding-standards/c/examples/realtime/Makefile +53 -0
- package/augment-extensions/coding-standards/c/examples/realtime/README.md +199 -0
- package/augment-extensions/coding-standards/c/examples/realtime/deadline-monitoring.c +260 -0
- package/augment-extensions/coding-standards/c/examples/realtime/priority-scheduling.c +258 -0
- package/augment-extensions/coding-standards/c/examples/systems/Makefile +34 -0
- package/augment-extensions/coding-standards/c/examples/systems/README.md +123 -0
- package/augment-extensions/coding-standards/c/examples/systems/ipc-pipes.c +181 -0
- package/augment-extensions/coding-standards/c/examples/systems/process-management.c +153 -0
- package/augment-extensions/coding-standards/c/examples/systems/signal-handling.c +162 -0
- package/augment-extensions/coding-standards/c/module.json +149 -0
- package/augment-extensions/coding-standards/c/rules/categories/drivers.md +635 -0
- package/augment-extensions/coding-standards/c/rules/categories/embedded.md +510 -0
- package/augment-extensions/coding-standards/c/rules/categories/kernel.md +653 -0
- package/augment-extensions/coding-standards/c/rules/categories/legacy.md +526 -0
- package/augment-extensions/coding-standards/c/rules/categories/networking.md +735 -0
- package/augment-extensions/coding-standards/c/rules/categories/realtime.md +631 -0
- package/augment-extensions/coding-standards/c/rules/categories/systems.md +586 -0
- package/augment-extensions/coding-standards/c/rules/universal/const-correctness.md +275 -0
- package/augment-extensions/coding-standards/c/rules/universal/documentation.md +251 -0
- package/augment-extensions/coding-standards/c/rules/universal/error-handling.md +250 -0
- package/augment-extensions/coding-standards/c/rules/universal/header-guards.md +254 -0
- package/augment-extensions/coding-standards/c/rules/universal/memory-safety.md +233 -0
- package/augment-extensions/coding-standards/c/rules/universal/naming.md +146 -0
- package/augment-extensions/coding-standards/c/src/conflict-detector.ts +461 -0
- package/augment-extensions/coding-standards/c/src/prompt-generator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-evaluator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-override.ts +427 -0
- package/augment-extensions/coding-standards/c/src/template-engine.ts +217 -0
- package/augment-extensions/coding-standards/c/templates/prompts/drivers.txt +191 -0
- package/augment-extensions/coding-standards/c/templates/prompts/embedded.txt +164 -0
- package/augment-extensions/coding-standards/c/templates/prompts/kernel.txt +175 -0
- package/augment-extensions/coding-standards/c/templates/prompts/legacy.txt +280 -0
- package/augment-extensions/coding-standards/c/templates/prompts/networking.txt +259 -0
- package/augment-extensions/coding-standards/c/templates/prompts/realtime.txt +219 -0
- package/augment-extensions/coding-standards/c/templates/prompts/systems.txt +147 -0
- package/augment-extensions/coding-standards/c/tests/integration/category-specific.test.ts +356 -0
- package/augment-extensions/coding-standards/c/tests/integration/end-to-end-workflow.test.ts +377 -0
- package/augment-extensions/coding-standards/c/tests/performance/benchmarks.test.ts +407 -0
- package/augment-extensions/coding-standards/c/tests/unit/config-manager.test.ts +345 -0
- package/augment-extensions/coding-standards/c/tests/unit/conflict-detector.test.ts +294 -0
- package/augment-extensions/coding-standards/c/tests/unit/prompt-generator.test.ts +174 -0
- package/augment-extensions/coding-standards/c/tests/unit/registry.test.ts +313 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-evaluator.test.ts +318 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-override.test.ts +326 -0
- package/augment-extensions/coding-standards/c/tests/unit/template-engine.test.ts +314 -0
- package/augment-extensions/coding-standards/go/CHARACTER-COUNT-REPORT.md +135 -0
- package/augment-extensions/coding-standards/go/PHASE1-COMPLETION.md +146 -0
- package/augment-extensions/coding-standards/go/PHASE4-COMPLETION.md +184 -0
- package/augment-extensions/coding-standards/go/README.md +200 -0
- package/augment-extensions/coding-standards/go/VALIDATION-CHECKLIST.md +154 -0
- package/augment-extensions/coding-standards/go/config/examples/example-cli.json +15 -0
- package/augment-extensions/coding-standards/go/config/examples/example-microservices.json +21 -0
- package/augment-extensions/coding-standards/go/config/examples/example-multi-category.yaml +24 -0
- package/augment-extensions/coding-standards/go/config/examples/example-web.json +15 -0
- package/augment-extensions/coding-standards/go/config/schema.json +110 -0
- package/augment-extensions/coding-standards/go/docs/CATEGORIES.md +221 -0
- package/augment-extensions/coding-standards/go/docs/CONFIGURATION.md +198 -0
- package/augment-extensions/coding-standards/go/docs/TROUBLESHOOTING.md +285 -0
- package/augment-extensions/coding-standards/go/examples/cli/cobra-app.go +287 -0
- package/augment-extensions/coding-standards/go/examples/cloud-native-app.go +217 -0
- package/augment-extensions/coding-standards/go/examples/devops-tool.go +250 -0
- package/augment-extensions/coding-standards/go/examples/distributed-system.go +247 -0
- package/augment-extensions/coding-standards/go/examples/microservices/grpc-service.go +253 -0
- package/augment-extensions/coding-standards/go/examples/rest-api.go +270 -0
- package/augment-extensions/coding-standards/go/examples/web/http-server.go +224 -0
- package/augment-extensions/coding-standards/go/module.json +139 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/api-versioning.md +149 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rate-limiting.md +209 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rest-api-design.md +183 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/cloud-config.md +193 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/health-checks.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/kubernetes.md +180 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/automation.md +179 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/ci-cd-integration.md +147 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/infrastructure-as-code.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/caching.md +150 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/consensus.md +187 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/event-sourcing.md +246 -0
- package/augment-extensions/coding-standards/go/rules/cli/command-parsing.md +264 -0
- package/augment-extensions/coding-standards/go/rules/cli/configuration.md +268 -0
- package/augment-extensions/coding-standards/go/rules/cli/cross-platform.md +324 -0
- package/augment-extensions/coding-standards/go/rules/microservices/distributed-tracing.md +253 -0
- package/augment-extensions/coding-standards/go/rules/microservices/grpc.md +257 -0
- package/augment-extensions/coding-standards/go/rules/microservices/metrics.md +278 -0
- package/augment-extensions/coding-standards/go/rules/microservices/service-discovery.md +249 -0
- package/augment-extensions/coding-standards/go/rules/universal/code-organization.md +221 -0
- package/augment-extensions/coding-standards/go/rules/universal/documentation.md +269 -0
- package/augment-extensions/coding-standards/go/rules/universal/performance.md +323 -0
- package/augment-extensions/coding-standards/go/rules/universal/testing.md +162 -0
- package/augment-extensions/coding-standards/go/rules/web/graceful-shutdown.md +249 -0
- package/augment-extensions/coding-standards/go/rules/web/http-handlers.md +164 -0
- package/augment-extensions/coding-standards/go/rules/web/middleware.md +234 -0
- package/augment-extensions/coding-standards/go/rules/web/routing.md +251 -0
- package/augment-extensions/coding-standards/go/templates/prompts/api.md +160 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cli.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cloud-native.md +121 -0
- package/augment-extensions/coding-standards/go/templates/prompts/devops.md +146 -0
- package/augment-extensions/coding-standards/go/templates/prompts/distributed.md +133 -0
- package/augment-extensions/coding-standards/go/templates/prompts/microservices.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/web.md +181 -0
- package/augment-extensions/coding-standards/go/tests/integration/module-integration.test.ts +164 -0
- package/augment-extensions/coding-standards/go/tests/unit/category-selection.test.ts +147 -0
- package/augment-extensions/coding-standards/go/tests/unit/module-structure.test.ts +154 -0
- package/augment-extensions/coding-standards/go/tests/validate-character-count.ps1 +13 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.ps1 +148 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.sh +135 -0
- package/cli/dist/analysis/ast-parser.d.ts +47 -0
- package/cli/dist/analysis/ast-parser.d.ts.map +1 -0
- package/cli/dist/analysis/ast-parser.js +161 -0
- package/cli/dist/analysis/ast-parser.js.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts +27 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.js +189 -0
- package/cli/dist/analysis/complexity-analyzer.js.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts +23 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.js +237 -0
- package/cli/dist/analysis/dependency-analyzer.js.map +1 -0
- package/cli/dist/analysis/index.d.ts +9 -0
- package/cli/dist/analysis/index.d.ts.map +1 -0
- package/cli/dist/analysis/index.js +25 -0
- package/cli/dist/analysis/index.js.map +1 -0
- package/cli/dist/analysis/security-scanner.d.ts +11 -0
- package/cli/dist/analysis/security-scanner.d.ts.map +1 -0
- package/cli/dist/analysis/security-scanner.js +294 -0
- package/cli/dist/analysis/security-scanner.js.map +1 -0
- package/cli/dist/analysis/types.d.ts +151 -0
- package/cli/dist/analysis/types.d.ts.map +1 -0
- package/cli/dist/analysis/types.js +6 -0
- package/cli/dist/analysis/types.js.map +1 -0
- package/cli/dist/cli.js +24 -0
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/code-analysis.d.ts +11 -0
- package/cli/dist/commands/code-analysis.d.ts.map +1 -0
- package/cli/dist/commands/code-analysis.js +412 -0
- package/cli/dist/commands/code-analysis.js.map +1 -0
- package/modules.md +99 -3
- package/package.json +14 -2
- package/cli/dist/commands/agent.d.ts +0 -37
- package/cli/dist/commands/agent.d.ts.map +0 -1
- package/cli/dist/commands/agent.js +0 -222
- package/cli/dist/commands/agent.js.map +0 -1
- package/cli/dist/commands/beads.d.ts +0 -64
- package/cli/dist/commands/beads.d.ts.map +0 -1
- package/cli/dist/commands/beads.js +0 -377
- package/cli/dist/commands/beads.js.map +0 -1
- package/cli/dist/commands/change.d.ts +0 -54
- package/cli/dist/commands/change.d.ts.map +0 -1
- package/cli/dist/commands/change.js +0 -243
- package/cli/dist/commands/change.js.map +0 -1
- package/cli/dist/commands/clean.d.ts +0 -15
- package/cli/dist/commands/clean.d.ts.map +0 -1
- package/cli/dist/commands/clean.js +0 -63
- package/cli/dist/commands/clean.js.map +0 -1
- package/cli/dist/commands/clone.d.ts +0 -15
- package/cli/dist/commands/clone.d.ts.map +0 -1
- package/cli/dist/commands/clone.js +0 -49
- package/cli/dist/commands/clone.js.map +0 -1
- package/cli/dist/commands/config.d.ts +0 -33
- package/cli/dist/commands/config.d.ts.map +0 -1
- package/cli/dist/commands/config.js +0 -166
- package/cli/dist/commands/config.js.map +0 -1
- package/cli/dist/commands/context.d.ts +0 -38
- package/cli/dist/commands/context.d.ts.map +0 -1
- package/cli/dist/commands/context.js +0 -205
- package/cli/dist/commands/context.js.map +0 -1
- package/cli/dist/commands/create.d.ts +0 -18
- package/cli/dist/commands/create.d.ts.map +0 -1
- package/cli/dist/commands/create.js +0 -178
- package/cli/dist/commands/create.js.map +0 -1
- package/cli/dist/commands/diff.d.ts +0 -19
- package/cli/dist/commands/diff.d.ts.map +0 -1
- package/cli/dist/commands/diff.js +0 -104
- package/cli/dist/commands/diff.js.map +0 -1
- package/cli/dist/commands/doctor.d.ts +0 -14
- package/cli/dist/commands/doctor.d.ts.map +0 -1
- package/cli/dist/commands/doctor.js +0 -62
- package/cli/dist/commands/doctor.js.map +0 -1
- package/cli/dist/commands/export.d.ts +0 -28
- package/cli/dist/commands/export.d.ts.map +0 -1
- package/cli/dist/commands/export.js +0 -135
- package/cli/dist/commands/export.js.map +0 -1
- package/cli/dist/commands/import.d.ts +0 -23
- package/cli/dist/commands/import.d.ts.map +0 -1
- package/cli/dist/commands/import.js +0 -118
- package/cli/dist/commands/import.js.map +0 -1
- package/cli/dist/commands/prompt.d.ts +0 -45
- package/cli/dist/commands/prompt.d.ts.map +0 -1
- package/cli/dist/commands/prompt.js +0 -223
- package/cli/dist/commands/prompt.js.map +0 -1
- package/cli/dist/commands/spec.d.ts +0 -57
- package/cli/dist/commands/spec.d.ts.map +0 -1
- package/cli/dist/commands/spec.js +0 -279
- package/cli/dist/commands/spec.js.map +0 -1
- package/cli/dist/commands/stats.d.ts +0 -18
- package/cli/dist/commands/stats.d.ts.map +0 -1
- package/cli/dist/commands/stats.js +0 -85
- package/cli/dist/commands/stats.js.map +0 -1
- package/cli/dist/commands/task.d.ts +0 -65
- package/cli/dist/commands/task.d.ts.map +0 -1
- package/cli/dist/commands/task.js +0 -282
- package/cli/dist/commands/task.js.map +0 -1
- package/cli/dist/commands/template.d.ts +0 -17
- package/cli/dist/commands/template.d.ts.map +0 -1
- package/cli/dist/commands/template.js +0 -55
- package/cli/dist/commands/template.js.map +0 -1
- package/cli/dist/utils/agent-config.d.ts +0 -129
- package/cli/dist/utils/agent-config.d.ts.map +0 -1
- package/cli/dist/utils/agent-config.js +0 -297
- package/cli/dist/utils/agent-config.js.map +0 -1
- package/cli/dist/utils/beads-graph.d.ts +0 -17
- package/cli/dist/utils/beads-graph.d.ts.map +0 -1
- package/cli/dist/utils/beads-graph.js +0 -150
- package/cli/dist/utils/beads-graph.js.map +0 -1
- package/cli/dist/utils/beads-integration.d.ts +0 -112
- package/cli/dist/utils/beads-integration.d.ts.map +0 -1
- package/cli/dist/utils/beads-integration.js +0 -312
- package/cli/dist/utils/beads-integration.js.map +0 -1
- package/cli/dist/utils/beads-reporter.d.ts +0 -17
- package/cli/dist/utils/beads-reporter.d.ts.map +0 -1
- package/cli/dist/utils/beads-reporter.js +0 -160
- package/cli/dist/utils/beads-reporter.js.map +0 -1
- package/cli/dist/utils/cache-manager.d.ts +0 -55
- package/cli/dist/utils/cache-manager.d.ts.map +0 -1
- package/cli/dist/utils/cache-manager.js +0 -150
- package/cli/dist/utils/cache-manager.js.map +0 -1
- package/cli/dist/utils/change-manager.d.ts +0 -70
- package/cli/dist/utils/change-manager.d.ts.map +0 -1
- package/cli/dist/utils/change-manager.js +0 -412
- package/cli/dist/utils/change-manager.js.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.d.ts +0 -66
- package/cli/dist/utils/config-manager-enhanced.d.ts.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.js +0 -77
- package/cli/dist/utils/config-manager-enhanced.js.map +0 -1
- package/cli/dist/utils/context-manager.d.ts +0 -96
- package/cli/dist/utils/context-manager.d.ts.map +0 -1
- package/cli/dist/utils/context-manager.js +0 -258
- package/cli/dist/utils/context-manager.js.map +0 -1
- package/cli/dist/utils/diff-engine.d.ts +0 -78
- package/cli/dist/utils/diff-engine.d.ts.map +0 -1
- package/cli/dist/utils/diff-engine.js +0 -233
- package/cli/dist/utils/diff-engine.js.map +0 -1
- package/cli/dist/utils/export-system.d.ts +0 -101
- package/cli/dist/utils/export-system.d.ts.map +0 -1
- package/cli/dist/utils/export-system.js +0 -289
- package/cli/dist/utils/export-system.js.map +0 -1
- package/cli/dist/utils/health-checker.d.ts +0 -66
- package/cli/dist/utils/health-checker.d.ts.map +0 -1
- package/cli/dist/utils/health-checker.js +0 -285
- package/cli/dist/utils/health-checker.js.map +0 -1
- package/cli/dist/utils/import-system.d.ts +0 -74
- package/cli/dist/utils/import-system.d.ts.map +0 -1
- package/cli/dist/utils/import-system.js +0 -317
- package/cli/dist/utils/import-system.js.map +0 -1
- package/cli/dist/utils/module-cloner.d.ts +0 -40
- package/cli/dist/utils/module-cloner.d.ts.map +0 -1
- package/cli/dist/utils/module-cloner.js +0 -136
- package/cli/dist/utils/module-cloner.js.map +0 -1
- package/cli/dist/utils/prompt-manager.d.ts +0 -90
- package/cli/dist/utils/prompt-manager.d.ts.map +0 -1
- package/cli/dist/utils/prompt-manager.js +0 -302
- package/cli/dist/utils/prompt-manager.js.map +0 -1
- package/cli/dist/utils/spec-manager.d.ts +0 -65
- package/cli/dist/utils/spec-manager.d.ts.map +0 -1
- package/cli/dist/utils/spec-manager.js +0 -329
- package/cli/dist/utils/spec-manager.js.map +0 -1
- package/cli/dist/utils/stats-collector.d.ts +0 -74
- package/cli/dist/utils/stats-collector.d.ts.map +0 -1
- package/cli/dist/utils/stats-collector.js +0 -164
- package/cli/dist/utils/stats-collector.js.map +0 -1
- package/cli/dist/utils/template-engine.d.ts +0 -47
- package/cli/dist/utils/template-engine.d.ts.map +0 -1
- package/cli/dist/utils/template-engine.js +0 -204
- package/cli/dist/utils/template-engine.js.map +0 -1
|
@@ -0,0 +1,653 @@
|
|
|
1
|
+
# Rule: Kernel Development
|
|
2
|
+
|
|
3
|
+
## Metadata
|
|
4
|
+
- **ID**: category-kernel
|
|
5
|
+
- **Category**: kernel
|
|
6
|
+
- **Severity**: ERROR
|
|
7
|
+
- **Standard**: Linux Kernel Coding Style
|
|
8
|
+
- **Version**: 1.0.0
|
|
9
|
+
|
|
10
|
+
## Description
|
|
11
|
+
Kernel development rules for Linux kernel modules, kernel APIs, locking mechanisms, and kernel subsystem integration.
|
|
12
|
+
|
|
13
|
+
## Rationale
|
|
14
|
+
Kernel code runs in privileged mode with direct hardware access. Bugs can crash the entire system, corrupt data, or create security vulnerabilities. Strict adherence to kernel coding standards ensures stability, security, and maintainability.
|
|
15
|
+
|
|
16
|
+
## Applies To
|
|
17
|
+
- C Standards: c89, c99, c11
|
|
18
|
+
- Categories: kernel
|
|
19
|
+
- Platforms: Linux kernel (2.6+, 3.x, 4.x, 5.x, 6.x)
|
|
20
|
+
|
|
21
|
+
## Rule Details
|
|
22
|
+
|
|
23
|
+
### 1. Module Initialization and Cleanup
|
|
24
|
+
- Use module_init() and module_exit() macros
|
|
25
|
+
- Always provide MODULE_LICENSE()
|
|
26
|
+
- Clean up all resources in exit function
|
|
27
|
+
- Handle initialization failures properly
|
|
28
|
+
|
|
29
|
+
### 2. Kernel Memory Allocation
|
|
30
|
+
- Use kmalloc/kfree for small allocations
|
|
31
|
+
- Use vmalloc/vfree for large allocations
|
|
32
|
+
- Always check allocation return values
|
|
33
|
+
- Use appropriate GFP flags (GFP_KERNEL, GFP_ATOMIC)
|
|
34
|
+
|
|
35
|
+
### 3. Kernel Logging
|
|
36
|
+
- Use pr_* macros (pr_info, pr_err, pr_debug)
|
|
37
|
+
- Use dev_* macros for device-specific messages
|
|
38
|
+
- Avoid printk() directly
|
|
39
|
+
- Use appropriate log levels
|
|
40
|
+
|
|
41
|
+
### 4. Locking Mechanisms
|
|
42
|
+
- Use spinlocks for short critical sections
|
|
43
|
+
- Use mutexes for longer critical sections
|
|
44
|
+
- Never sleep while holding a spinlock
|
|
45
|
+
- Avoid deadlocks with proper lock ordering
|
|
46
|
+
|
|
47
|
+
### 5. User-Kernel Space Interaction
|
|
48
|
+
- Use copy_to_user/copy_from_user for data transfer
|
|
49
|
+
- Validate all user-space pointers
|
|
50
|
+
- Never trust user-space data
|
|
51
|
+
- Use access_ok() to verify addresses
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
### ✅ Example 1: Proper Module Structure
|
|
56
|
+
|
|
57
|
+
```c
|
|
58
|
+
#include <linux/module.h>
|
|
59
|
+
#include <linux/kernel.h>
|
|
60
|
+
#include <linux/init.h>
|
|
61
|
+
|
|
62
|
+
MODULE_LICENSE("GPL");
|
|
63
|
+
MODULE_AUTHOR("Your Name");
|
|
64
|
+
MODULE_DESCRIPTION("Example kernel module");
|
|
65
|
+
MODULE_VERSION("1.0");
|
|
66
|
+
|
|
67
|
+
static int __init example_init(void) {
|
|
68
|
+
pr_info("Example module loaded\n");
|
|
69
|
+
|
|
70
|
+
// Initialize resources
|
|
71
|
+
int ret = initialize_resources();
|
|
72
|
+
if (ret < 0) {
|
|
73
|
+
pr_err("Failed to initialize resources: %d\n", ret);
|
|
74
|
+
return ret;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static void __exit example_exit(void) {
|
|
81
|
+
// Clean up all resources
|
|
82
|
+
cleanup_resources();
|
|
83
|
+
pr_info("Example module unloaded\n");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module_init(example_init);
|
|
87
|
+
module_exit(example_exit);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### ❌ Example 1: Missing Module Metadata
|
|
91
|
+
|
|
92
|
+
```c
|
|
93
|
+
// WRONG: Missing MODULE_LICENSE and proper init/exit
|
|
94
|
+
#include <linux/module.h>
|
|
95
|
+
|
|
96
|
+
void init_module(void) { // Old style, deprecated
|
|
97
|
+
printk("Module loaded\n"); // Should use pr_info
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
void cleanup_module(void) {
|
|
101
|
+
// Missing cleanup code
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### ✅ Example 2: Kernel Memory Allocation
|
|
106
|
+
|
|
107
|
+
```c
|
|
108
|
+
#include <linux/slab.h>
|
|
109
|
+
#include <linux/gfp.h>
|
|
110
|
+
|
|
111
|
+
struct my_data {
|
|
112
|
+
int value;
|
|
113
|
+
char name[64];
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
int allocate_data(void) {
|
|
117
|
+
struct my_data *data;
|
|
118
|
+
|
|
119
|
+
// Use GFP_KERNEL in process context (can sleep)
|
|
120
|
+
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
|
121
|
+
if (!data) {
|
|
122
|
+
pr_err("Failed to allocate memory\n");
|
|
123
|
+
return -ENOMEM;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Initialize data
|
|
127
|
+
data->value = 0;
|
|
128
|
+
memset(data->name, 0, sizeof(data->name));
|
|
129
|
+
|
|
130
|
+
// Use the data...
|
|
131
|
+
|
|
132
|
+
// Free when done
|
|
133
|
+
kfree(data);
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// In interrupt context, use GFP_ATOMIC
|
|
138
|
+
void interrupt_handler(void) {
|
|
139
|
+
void *buffer = kmalloc(256, GFP_ATOMIC); // Cannot sleep
|
|
140
|
+
if (!buffer) {
|
|
141
|
+
pr_err("Allocation failed in interrupt\n");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Use buffer...
|
|
146
|
+
kfree(buffer);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### ❌ Example 2: Improper Memory Allocation
|
|
151
|
+
|
|
152
|
+
```c
|
|
153
|
+
// WRONG: Not checking return value, wrong GFP flags
|
|
154
|
+
void bad_allocation(void) {
|
|
155
|
+
struct my_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
|
|
156
|
+
data->value = 42; // Crash if allocation failed!
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// WRONG: Using GFP_KERNEL in interrupt context
|
|
160
|
+
void bad_interrupt_handler(void) {
|
|
161
|
+
void *buf = kmalloc(256, GFP_KERNEL); // Can sleep - BUG!
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### ✅ Example 3: Spinlock Usage
|
|
166
|
+
|
|
167
|
+
```c
|
|
168
|
+
#include <linux/spinlock.h>
|
|
169
|
+
|
|
170
|
+
static DEFINE_SPINLOCK(my_lock);
|
|
171
|
+
static int shared_counter = 0;
|
|
172
|
+
|
|
173
|
+
void increment_counter(void) {
|
|
174
|
+
unsigned long flags;
|
|
175
|
+
|
|
176
|
+
spin_lock_irqsave(&my_lock, flags);
|
|
177
|
+
shared_counter++;
|
|
178
|
+
spin_unlock_irqrestore(&my_lock, flags);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
int get_counter(void) {
|
|
182
|
+
unsigned long flags;
|
|
183
|
+
int value;
|
|
184
|
+
|
|
185
|
+
spin_lock_irqsave(&my_lock, flags);
|
|
186
|
+
value = shared_counter;
|
|
187
|
+
spin_unlock_irqrestore(&my_lock, flags);
|
|
188
|
+
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### ❌ Example 3: Improper Spinlock Usage
|
|
194
|
+
|
|
195
|
+
```c
|
|
196
|
+
// WRONG: Sleeping while holding spinlock
|
|
197
|
+
void bad_spinlock_usage(void) {
|
|
198
|
+
spin_lock(&my_lock);
|
|
199
|
+
msleep(100); // BUG: Cannot sleep with spinlock!
|
|
200
|
+
spin_unlock(&my_lock);
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### ✅ Example 4: Mutex Usage
|
|
205
|
+
|
|
206
|
+
```c
|
|
207
|
+
#include <linux/mutex.h>
|
|
208
|
+
|
|
209
|
+
static DEFINE_MUTEX(my_mutex);
|
|
210
|
+
static struct list_head device_list;
|
|
211
|
+
|
|
212
|
+
int add_device(struct device *dev) {
|
|
213
|
+
mutex_lock(&my_mutex);
|
|
214
|
+
|
|
215
|
+
// Can sleep here - mutex allows it
|
|
216
|
+
if (need_to_allocate()) {
|
|
217
|
+
void *buf = kmalloc(1024, GFP_KERNEL); // OK with mutex
|
|
218
|
+
if (!buf) {
|
|
219
|
+
mutex_unlock(&my_mutex);
|
|
220
|
+
return -ENOMEM;
|
|
221
|
+
}
|
|
222
|
+
// Use buffer...
|
|
223
|
+
kfree(buf);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
list_add(&dev->list, &device_list);
|
|
227
|
+
mutex_unlock(&my_mutex);
|
|
228
|
+
|
|
229
|
+
return 0;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### ✅ Example 5: User-Kernel Data Transfer
|
|
234
|
+
|
|
235
|
+
```c
|
|
236
|
+
#include <linux/uaccess.h>
|
|
237
|
+
|
|
238
|
+
struct user_data {
|
|
239
|
+
int value;
|
|
240
|
+
char name[64];
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
|
|
244
|
+
struct user_data kdata;
|
|
245
|
+
struct user_data __user *udata = (struct user_data __user *)arg;
|
|
246
|
+
|
|
247
|
+
switch (cmd) {
|
|
248
|
+
case IOCTL_GET_DATA:
|
|
249
|
+
// Copy from kernel to user space
|
|
250
|
+
if (copy_to_user(udata, &kdata, sizeof(kdata))) {
|
|
251
|
+
return -EFAULT;
|
|
252
|
+
}
|
|
253
|
+
break;
|
|
254
|
+
|
|
255
|
+
case IOCTL_SET_DATA:
|
|
256
|
+
// Copy from user to kernel space
|
|
257
|
+
if (copy_from_user(&kdata, udata, sizeof(kdata))) {
|
|
258
|
+
return -EFAULT;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Validate user data
|
|
262
|
+
if (kdata.value < 0 || kdata.value > 100) {
|
|
263
|
+
return -EINVAL;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Ensure string is null-terminated
|
|
267
|
+
kdata.name[sizeof(kdata.name) - 1] = '\0';
|
|
268
|
+
break;
|
|
269
|
+
|
|
270
|
+
default:
|
|
271
|
+
return -ENOTTY;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### ❌ Example 5: Unsafe User-Kernel Transfer
|
|
279
|
+
|
|
280
|
+
```c
|
|
281
|
+
// WRONG: Direct pointer dereference, no validation
|
|
282
|
+
long bad_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
|
|
283
|
+
struct user_data *udata = (struct user_data *)arg;
|
|
284
|
+
|
|
285
|
+
// WRONG: Directly accessing user-space pointer!
|
|
286
|
+
int value = udata->value; // Can crash or security hole!
|
|
287
|
+
|
|
288
|
+
return 0;
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### ✅ Example 6: Character Device Registration
|
|
293
|
+
|
|
294
|
+
```c
|
|
295
|
+
#include <linux/fs.h>
|
|
296
|
+
#include <linux/cdev.h>
|
|
297
|
+
|
|
298
|
+
static dev_t dev_num;
|
|
299
|
+
static struct cdev my_cdev;
|
|
300
|
+
static struct class *my_class;
|
|
301
|
+
|
|
302
|
+
static struct file_operations fops = {
|
|
303
|
+
.owner = THIS_MODULE,
|
|
304
|
+
.open = device_open,
|
|
305
|
+
.release = device_release,
|
|
306
|
+
.read = device_read,
|
|
307
|
+
.write = device_write,
|
|
308
|
+
.unlocked_ioctl = device_ioctl,
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
static int __init chardev_init(void) {
|
|
312
|
+
int ret;
|
|
313
|
+
|
|
314
|
+
// Allocate device number
|
|
315
|
+
ret = alloc_chrdev_region(&dev_num, 0, 1, "mydevice");
|
|
316
|
+
if (ret < 0) {
|
|
317
|
+
pr_err("Failed to allocate device number\n");
|
|
318
|
+
return ret;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Initialize cdev
|
|
322
|
+
cdev_init(&my_cdev, &fops);
|
|
323
|
+
my_cdev.owner = THIS_MODULE;
|
|
324
|
+
|
|
325
|
+
// Add cdev to system
|
|
326
|
+
ret = cdev_add(&my_cdev, dev_num, 1);
|
|
327
|
+
if (ret < 0) {
|
|
328
|
+
pr_err("Failed to add cdev\n");
|
|
329
|
+
unregister_chrdev_region(dev_num, 1);
|
|
330
|
+
return ret;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Create device class
|
|
334
|
+
my_class = class_create(THIS_MODULE, "mydevice");
|
|
335
|
+
if (IS_ERR(my_class)) {
|
|
336
|
+
pr_err("Failed to create class\n");
|
|
337
|
+
cdev_del(&my_cdev);
|
|
338
|
+
unregister_chrdev_region(dev_num, 1);
|
|
339
|
+
return PTR_ERR(my_class);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Create device node
|
|
343
|
+
device_create(my_class, NULL, dev_num, NULL, "mydevice");
|
|
344
|
+
|
|
345
|
+
pr_info("Character device registered\n");
|
|
346
|
+
return 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
static void __exit chardev_exit(void) {
|
|
350
|
+
device_destroy(my_class, dev_num);
|
|
351
|
+
class_destroy(my_class);
|
|
352
|
+
cdev_del(&my_cdev);
|
|
353
|
+
unregister_chrdev_region(dev_num, 1);
|
|
354
|
+
pr_info("Character device unregistered\n");
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### ✅ Example 7: Kernel Linked Lists
|
|
359
|
+
|
|
360
|
+
```c
|
|
361
|
+
#include <linux/list.h>
|
|
362
|
+
#include <linux/slab.h>
|
|
363
|
+
|
|
364
|
+
struct my_device {
|
|
365
|
+
int id;
|
|
366
|
+
char name[32];
|
|
367
|
+
struct list_head list;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
static LIST_HEAD(device_list);
|
|
371
|
+
|
|
372
|
+
int add_device(int id, const char *name) {
|
|
373
|
+
struct my_device *dev;
|
|
374
|
+
|
|
375
|
+
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
|
|
376
|
+
if (!dev)
|
|
377
|
+
return -ENOMEM;
|
|
378
|
+
|
|
379
|
+
dev->id = id;
|
|
380
|
+
strncpy(dev->name, name, sizeof(dev->name) - 1);
|
|
381
|
+
dev->name[sizeof(dev->name) - 1] = '\0';
|
|
382
|
+
|
|
383
|
+
list_add_tail(&dev->list, &device_list);
|
|
384
|
+
return 0;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
void remove_all_devices(void) {
|
|
388
|
+
struct my_device *dev, *tmp;
|
|
389
|
+
|
|
390
|
+
list_for_each_entry_safe(dev, tmp, &device_list, list) {
|
|
391
|
+
list_del(&dev->list);
|
|
392
|
+
kfree(dev);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
struct my_device *find_device(int id) {
|
|
397
|
+
struct my_device *dev;
|
|
398
|
+
|
|
399
|
+
list_for_each_entry(dev, &device_list, list) {
|
|
400
|
+
if (dev->id == id)
|
|
401
|
+
return dev;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return NULL;
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### ✅ Example 8: Kernel Timers
|
|
409
|
+
|
|
410
|
+
```c
|
|
411
|
+
#include <linux/timer.h>
|
|
412
|
+
#include <linux/jiffies.h>
|
|
413
|
+
|
|
414
|
+
static struct timer_list my_timer;
|
|
415
|
+
|
|
416
|
+
void timer_callback(struct timer_list *t) {
|
|
417
|
+
pr_info("Timer expired\n");
|
|
418
|
+
|
|
419
|
+
// Reschedule timer for 1 second from now
|
|
420
|
+
mod_timer(&my_timer, jiffies + HZ);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
int setup_timer(void) {
|
|
424
|
+
timer_setup(&my_timer, timer_callback, 0);
|
|
425
|
+
|
|
426
|
+
// Start timer (expires in 1 second)
|
|
427
|
+
mod_timer(&my_timer, jiffies + HZ);
|
|
428
|
+
|
|
429
|
+
return 0;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
void cleanup_timer(void) {
|
|
433
|
+
del_timer_sync(&my_timer);
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### ✅ Example 9: Work Queues
|
|
438
|
+
|
|
439
|
+
```c
|
|
440
|
+
#include <linux/workqueue.h>
|
|
441
|
+
|
|
442
|
+
static struct workqueue_struct *my_wq;
|
|
443
|
+
|
|
444
|
+
struct work_data {
|
|
445
|
+
struct work_struct work;
|
|
446
|
+
int value;
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
void work_handler(struct work_struct *work) {
|
|
450
|
+
struct work_data *data = container_of(work, struct work_data, work);
|
|
451
|
+
|
|
452
|
+
pr_info("Processing work with value: %d\n", data->value);
|
|
453
|
+
|
|
454
|
+
// Do work (can sleep here)
|
|
455
|
+
msleep(100);
|
|
456
|
+
|
|
457
|
+
kfree(data);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
int queue_work_item(int value) {
|
|
461
|
+
struct work_data *data;
|
|
462
|
+
|
|
463
|
+
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
|
464
|
+
if (!data)
|
|
465
|
+
return -ENOMEM;
|
|
466
|
+
|
|
467
|
+
INIT_WORK(&data->work, work_handler);
|
|
468
|
+
data->value = value;
|
|
469
|
+
|
|
470
|
+
queue_work(my_wq, &data->work);
|
|
471
|
+
return 0;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
int init_workqueue(void) {
|
|
475
|
+
my_wq = create_singlethread_workqueue("my_wq");
|
|
476
|
+
if (!my_wq)
|
|
477
|
+
return -ENOMEM;
|
|
478
|
+
return 0;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
void cleanup_workqueue(void) {
|
|
482
|
+
flush_workqueue(my_wq);
|
|
483
|
+
destroy_workqueue(my_wq);
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### ✅ Example 10: Kernel Threads
|
|
488
|
+
|
|
489
|
+
```c
|
|
490
|
+
#include <linux/kthread.h>
|
|
491
|
+
#include <linux/delay.h>
|
|
492
|
+
|
|
493
|
+
static struct task_struct *my_thread;
|
|
494
|
+
static bool thread_should_stop = false;
|
|
495
|
+
|
|
496
|
+
int thread_function(void *data) {
|
|
497
|
+
while (!kthread_should_stop() && !thread_should_stop) {
|
|
498
|
+
pr_info("Thread running\n");
|
|
499
|
+
|
|
500
|
+
// Do work
|
|
501
|
+
msleep(1000);
|
|
502
|
+
|
|
503
|
+
if (signal_pending(current))
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
pr_info("Thread exiting\n");
|
|
508
|
+
return 0;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
int start_kernel_thread(void) {
|
|
512
|
+
my_thread = kthread_run(thread_function, NULL, "my_thread");
|
|
513
|
+
if (IS_ERR(my_thread)) {
|
|
514
|
+
pr_err("Failed to create thread\n");
|
|
515
|
+
return PTR_ERR(my_thread);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return 0;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
void stop_kernel_thread(void) {
|
|
522
|
+
if (my_thread) {
|
|
523
|
+
thread_should_stop = true;
|
|
524
|
+
kthread_stop(my_thread);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### ✅ Example 11: Proc Filesystem Entry
|
|
530
|
+
|
|
531
|
+
```c
|
|
532
|
+
#include <linux/proc_fs.h>
|
|
533
|
+
#include <linux/seq_file.h>
|
|
534
|
+
|
|
535
|
+
static int my_proc_show(struct seq_file *m, void *v) {
|
|
536
|
+
seq_printf(m, "Hello from proc!\n");
|
|
537
|
+
seq_printf(m, "Counter: %d\n", shared_counter);
|
|
538
|
+
return 0;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
static int my_proc_open(struct inode *inode, struct file *file) {
|
|
542
|
+
return single_open(file, my_proc_show, NULL);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
static const struct proc_ops my_proc_ops = {
|
|
546
|
+
.proc_open = my_proc_open,
|
|
547
|
+
.proc_read = seq_read,
|
|
548
|
+
.proc_lseek = seq_lseek,
|
|
549
|
+
.proc_release = single_release,
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
static struct proc_dir_entry *proc_entry;
|
|
553
|
+
|
|
554
|
+
int create_proc_entry(void) {
|
|
555
|
+
proc_entry = proc_create("mydevice", 0444, NULL, &my_proc_ops);
|
|
556
|
+
if (!proc_entry) {
|
|
557
|
+
pr_err("Failed to create proc entry\n");
|
|
558
|
+
return -ENOMEM;
|
|
559
|
+
}
|
|
560
|
+
return 0;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
void remove_proc_entry(void) {
|
|
564
|
+
proc_remove(proc_entry);
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### ✅ Example 12: RCU (Read-Copy-Update)
|
|
569
|
+
|
|
570
|
+
```c
|
|
571
|
+
#include <linux/rcupdate.h>
|
|
572
|
+
|
|
573
|
+
struct my_data {
|
|
574
|
+
int value;
|
|
575
|
+
struct rcu_head rcu;
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
static struct my_data __rcu *global_data;
|
|
579
|
+
|
|
580
|
+
// Read side (lock-free)
|
|
581
|
+
int read_data(void) {
|
|
582
|
+
struct my_data *data;
|
|
583
|
+
int value;
|
|
584
|
+
|
|
585
|
+
rcu_read_lock();
|
|
586
|
+
data = rcu_dereference(global_data);
|
|
587
|
+
if (data)
|
|
588
|
+
value = data->value;
|
|
589
|
+
else
|
|
590
|
+
value = -1;
|
|
591
|
+
rcu_read_unlock();
|
|
592
|
+
|
|
593
|
+
return value;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Free callback
|
|
597
|
+
static void free_data_rcu(struct rcu_head *rcu) {
|
|
598
|
+
struct my_data *data = container_of(rcu, struct my_data, rcu);
|
|
599
|
+
kfree(data);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Update side
|
|
603
|
+
int update_data(int new_value) {
|
|
604
|
+
struct my_data *new_data, *old_data;
|
|
605
|
+
|
|
606
|
+
new_data = kmalloc(sizeof(*new_data), GFP_KERNEL);
|
|
607
|
+
if (!new_data)
|
|
608
|
+
return -ENOMEM;
|
|
609
|
+
|
|
610
|
+
new_data->value = new_value;
|
|
611
|
+
|
|
612
|
+
old_data = rcu_dereference_protected(global_data,
|
|
613
|
+
lockdep_is_held(&update_lock));
|
|
614
|
+
rcu_assign_pointer(global_data, new_data);
|
|
615
|
+
|
|
616
|
+
if (old_data)
|
|
617
|
+
call_rcu(&old_data->rcu, free_data_rcu);
|
|
618
|
+
|
|
619
|
+
return 0;
|
|
620
|
+
}
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
## References
|
|
624
|
+
|
|
625
|
+
- Linux Kernel Coding Style (Documentation/process/coding-style.rst)
|
|
626
|
+
- Linux Device Drivers, 3rd Edition (LDD3)
|
|
627
|
+
- Linux Kernel Development (Robert Love)
|
|
628
|
+
- Kernel documentation (Documentation/)
|
|
629
|
+
- https://www.kernel.org/doc/html/latest/
|
|
630
|
+
|
|
631
|
+
## Related Rules
|
|
632
|
+
|
|
633
|
+
- universal-error-handling
|
|
634
|
+
- universal-memory-safety
|
|
635
|
+
- category-drivers
|
|
636
|
+
|
|
637
|
+
## Configuration
|
|
638
|
+
|
|
639
|
+
Enable in `.augment/c-standards.json`:
|
|
640
|
+
|
|
641
|
+
```json
|
|
642
|
+
{
|
|
643
|
+
"categories": ["kernel"],
|
|
644
|
+
"category_overrides": {
|
|
645
|
+
"kernel": {
|
|
646
|
+
"require_module_license": true,
|
|
647
|
+
"check_gfp_flags": true,
|
|
648
|
+
"enforce_locking_rules": true
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
```
|
|
653
|
+
|