|
23 | 23 | * Use is subject to license terms.
|
24 | 24 | */
|
25 | 25 |
|
| 26 | +/* |
| 27 | + * Copyright (c) 2013 by Delphix. All rights reserved. |
| 28 | + */ |
| 29 | + |
26 | 30 | #ifndef _SYS_TXG_IMPL_H
|
27 | 31 | #define _SYS_TXG_IMPL_H
|
28 | 32 |
|
|
33 | 37 | extern "C" {
|
34 | 38 | #endif
|
35 | 39 |
|
| 40 | +/* |
| 41 | + * The tx_cpu structure is a per-cpu structure that is used to track |
| 42 | + * the number of active transaction holds (tc_count). As transactions |
| 43 | + * are assigned into a transaction group the appropriate tc_count is |
| 44 | + * incremented to indicate that there are pending changes that have yet |
| 45 | + * to quiesce. Consumers evenutally call txg_rele_to_sync() to decrement |
| 46 | + * the tc_count. A transaction group is not considered quiesced until all |
| 47 | + * tx_cpu structures have reached a tc_count of zero. |
| 48 | + * |
| 49 | + * This structure is a per-cpu structure by design. Updates to this structure |
| 50 | + * are frequent and concurrent. Having a single structure would result in |
| 51 | + * heavy lock contention so a per-cpu design was implemented. With the fanned |
| 52 | + * out mutex design, consumers only need to lock the mutex associated with |
| 53 | + * thread's cpu. |
| 54 | + * |
| 55 | + * The tx_cpu contains two locks, the tc_lock and tc_open_lock. |
| 56 | + * The tc_lock is used to protect all members of the tx_cpu structure with |
| 57 | + * the exception of the tc_open_lock. This lock should only be held for a |
| 58 | + * short period of time, typically when updating the value of tc_count. |
| 59 | + * |
| 60 | + * The tc_open_lock protects the tx_open_txg member of the tx_state structure. |
| 61 | + * This lock is used to ensure that transactions are only assigned into |
| 62 | + * the current open transaction group. In order to move the current open |
| 63 | + * transaction group to the quiesce phase, the txg_quiesce thread must |
| 64 | + * grab all tc_open_locks, increment the tx_open_txg, and drop the locks. |
| 65 | + * The tc_open_lock is held until the transaction is assigned into the |
| 66 | + * transaction group. Typically, this is a short operation but if throttling |
| 67 | + * is occuring it may be held for longer periods of time. |
| 68 | + */ |
36 | 69 | struct tx_cpu {
|
37 |
| - kmutex_t tc_lock; |
| 70 | + kmutex_t tc_open_lock; /* protects tx_open_txg */ |
| 71 | + kmutex_t tc_lock; /* protects the rest of this struct */ |
38 | 72 | kcondvar_t tc_cv[TXG_SIZE];
|
39 | 73 | uint64_t tc_count[TXG_SIZE];
|
40 | 74 | list_t tc_callbacks[TXG_SIZE]; /* commit cb list */
|
41 |
| - char tc_pad[16]; |
| 75 | + char tc_pad[8]; /* pad to fill 3 cache lines */ |
42 | 76 | };
|
43 | 77 |
|
| 78 | +/* |
| 79 | + * The tx_state structure maintains the state information about the different |
| 80 | + * stages of the pool's transcation groups. A per pool tx_state structure |
| 81 | + * is used to track this information. The tx_state structure also points to |
| 82 | + * an array of tx_cpu structures (described above). Although the tx_sync_lock |
| 83 | + * is used to protect the members of this structure, it is not used to |
| 84 | + * protect the tx_open_txg. Instead a special lock in the tx_cpu structure |
| 85 | + * is used. Readers of tx_open_txg must grab the per-cpu tc_open_lock. |
| 86 | + * Any thread wishing to update tx_open_txg must grab the tc_open_lock on |
| 87 | + * every cpu (see txg_quiesce()). |
| 88 | + */ |
44 | 89 | typedef struct tx_state {
|
45 | 90 | tx_cpu_t *tx_cpu; /* protects right to enter txg */
|
46 | 91 | kmutex_t tx_sync_lock; /* protects tx_state_t */
|
|
0 commit comments