Align the code samples and note sections inside kernel-doc comments with tabs. This way they can be properly parsed and rendered by Sphinx. It also makes the code samples easier to read from text editors.
Unified · Split
| @@ -263,32 +263,32 @@ static inline void raw_write_seqcount_end(seqcount_t *s) · 262 unmodified lines | |||
| 263 | * atomically, avoiding compiler optimizations; b) to document which writes are | 263 | * atomically, avoiding compiler optimizations; b) to document which writes are |
| 264 | * meant to propagate to the reader critical section. This is necessary because | 264 | * meant to propagate to the reader critical section. This is necessary because |
| 265 | * neither writes before and after the barrier are enclosed in a seq-writer | 265 | * neither writes before and after the barrier are enclosed in a seq-writer |
| 266 | * critical section that would ensure readers are aware of ongoing writes. | 266 | * critical section that would ensure readers are aware of ongoing writes:: |
| 267 | * | 267 | * |
| 268 | * seqcount_t seq; | 268 | * seqcount_t seq; |
| 269 | * bool X = true, Y = false; | 269 | * bool X = true, Y = false; |
| 270 | * | 270 | * |
| 271 | * void read(void) | 271 | * void read(void) |
| 272 | * { | 272 | * { |
| 273 | * bool x, y; | 273 | * bool x, y; |
| 274 | * | 274 | * |
| 275 | * do { | 275 | * do { |
| 276 | * int s = read_seqcount_begin(&seq); | 276 | * int s = read_seqcount_begin(&seq); |
| 277 | * | 277 | * |
| 278 | * x = X; y = Y; | 278 | * x = X; y = Y; |
| 279 | * | 279 | * |
| 280 | * } while (read_seqcount_retry(&seq, s)); | 280 | * } while (read_seqcount_retry(&seq, s)); |
| 281 | * | 281 | * |
| 282 | * BUG_ON(!x && !y); | 282 | * BUG_ON(!x && !y); |
| 283 | * } | 283 | * } |
| 284 | * | 284 | * |
| 285 | * void write(void) | 285 | * void write(void) |
| 286 | * { | 286 | * { |
| 287 | * WRITE_ONCE(Y, true); | 287 | * WRITE_ONCE(Y, true); |
| 288 | * | 288 | * |
| 289 | * raw_write_seqcount_barrier(seq); | 289 | * raw_write_seqcount_barrier(seq); |
| 290 | * | 290 | * |
| 291 | * WRITE_ONCE(X, false); | 291 | * WRITE_ONCE(X, false); |
| 292 | * } | 292 | * } |
| 293 | */ | 293 | */ |
| 294 | static inline void raw_write_seqcount_barrier(seqcount_t *s) | 294 | static inline void raw_write_seqcount_barrier(seqcount_t *s) |
| @@ -325,64 +325,68 @@ static inline int raw_read_seqcount_latch(seqcount_t *s) · 30 unmodified lines | |||
| 325 | * Very simply put: we first modify one copy and then the other. This ensures | 325 | * Very simply put: we first modify one copy and then the other. This ensures |
| 326 | * there is always one copy in a stable state, ready to give us an answer. | 326 | * there is always one copy in a stable state, ready to give us an answer. |
| 327 | * | 327 | * |
| 328 | * The basic form is a data structure like: | 328 | * The basic form is a data structure like:: |
| 329 | * | 329 | * |
| 330 | * struct latch_struct { | 330 | * struct latch_struct { |
| 331 | * seqcount_t seq; | 331 | * seqcount_t seq; |
| 332 | * struct data_struct data[2]; | 332 | * struct data_struct data[2]; |
| 333 | * }; | 333 | * }; |
| 334 | * | 334 | * |
| 335 | * Where a modification, which is assumed to be externally serialized, does the | 335 | * Where a modification, which is assumed to be externally serialized, does the |
| 336 | * following: | 336 | * following:: |
| 337 | * | 337 | * |
| 338 | * void latch_modify(struct latch_struct *latch, ...) | 338 | * void latch_modify(struct latch_struct *latch, ...) |
| 339 | * { | 339 | * { |
| 340 | * smp_wmb(); <- Ensure that the last data[1] update is visible | 340 | * smp_wmb(); // Ensure that the last data[1] update is visible |
| 341 | * latch->seq++; | 341 | * latch->seq++; |
| 342 | * smp_wmb(); <- Ensure that the seqcount update is visible | 342 | * smp_wmb(); // Ensure that the seqcount update is visible |
| 343 | * | 343 | * |
| 344 | * modify(latch->data[0], ...); | 344 | * modify(latch->data[0], ...); |
| 345 | * | 345 | * |
| 346 | * smp_wmb(); <- Ensure that the data[0] update is visible | 346 | * smp_wmb(); // Ensure that the data[0] update is visible |
| 347 | * latch->seq++; | 347 | * latch->seq++; |
| 348 | * smp_wmb(); <- Ensure that the seqcount update is visible | 348 | * smp_wmb(); // Ensure that the seqcount update is visible |
| 349 | * | 349 | * |
| 350 | * modify(latch->data[1], ...); | 350 | * modify(latch->data[1], ...); |
| 351 | * } | 351 | * } |
| 352 | * | 352 | * |
| 353 | * The query will have a form like: | 353 | * The query will have a form like:: |
| 354 | * | 354 | * |
| 355 | * struct entry *latch_query(struct latch_struct *latch, ...) | 355 | * struct entry *latch_query(struct latch_struct *latch, ...) |
| 356 | * { | 356 | * { |
| 357 | * struct entry *entry; | 357 | * struct entry *entry; |
| 358 | * unsigned seq, idx; | 358 | * unsigned seq, idx; |
| 359 | * | 359 | * |
| 360 | * do { | 360 | * do { |
| 361 | * seq = raw_read_seqcount_latch(&latch->seq); | 361 | * seq = raw_read_seqcount_latch(&latch->seq); |
| 362 | * | 362 | * |
| 363 | * idx = seq & 0x01; | 363 | * idx = seq & 0x01; |
| 364 | * entry = data_query(latch->data[idx], ...); | 364 | * entry = data_query(latch->data[idx], ...); |
| 365 | * | 365 | * |
| 366 | * smp_rmb(); | 366 | * smp_rmb(); |
| 367 | * } while (seq != latch->seq); | 367 | * } while (seq != latch->seq); |
| 368 | * | 368 | * |
| 369 | * return entry; | 369 | * return entry; |
| 370 | * } | 370 | * } |
| 371 | * | 371 | * |
| 372 | * So during the modification, queries are first redirected to data[1]. Then we | 372 | * So during the modification, queries are first redirected to data[1]. Then we |
| 373 | * modify data[0]. When that is complete, we redirect queries back to data[0] | 373 | * modify data[0]. When that is complete, we redirect queries back to data[0] |
| 374 | * and we can modify data[1]. | 374 | * and we can modify data[1]. |
| 375 | * | 375 | * |
| 376 | * NOTE: The non-requirement for atomic modifications does _NOT_ include | 376 | * NOTE: |
| 377 | * the publishing of new entries in the case where data is a dynamic | 377 | * |
| 378 | * data structure. | 378 | * The non-requirement for atomic modifications does _NOT_ include |
| 379 | * the publishing of new entries in the case where data is a dynamic | ||
| 380 | * data structure. | ||
| 381 | * | ||
| 382 | * An iteration might start in data[0] and get suspended long enough | ||
| 383 | * to miss an entire modification sequence, once it resumes it might | ||
| 384 | * observe the new entry. | ||
| 379 | * | 385 | * |
| 380 | * An iteration might start in data[0] and get suspended long enough | 386 | * NOTE: |
| 381 | * to miss an entire modification sequence, once it resumes it might | ||
| 382 | * observe the new entry. | ||
| 383 | * | 387 | * |
| 384 | * NOTE: When data is a dynamic data structure; one should use regular RCU | 388 | * When data is a dynamic data structure; one should use regular RCU |
| 385 | * patterns to manage the lifetimes of the objects within. | 389 | * patterns to manage the lifetimes of the objects within. |
| 386 | */ | 390 | */ |
| 387 | static inline void raw_write_seqcount_latch(seqcount_t *s) | 391 | static inline void raw_write_seqcount_latch(seqcount_t *s) |
| 388 | { | 392 | { |