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.
Showing the changes to include/linux (1 of 1 file). Show all
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 | { |