* Get an sf_buf from the freelist. May block if none are available. */
| 111 | * Get an sf_buf from the freelist. May block if none are available. |
| 112 | */ |
| 113 | struct sf_buf * |
| 114 | sf_buf_alloc(struct vm_page *m, int flags) |
| 115 | { |
| 116 | struct sf_head *hash_list; |
| 117 | struct sf_buf *sf; |
| 118 | int error; |
| 119 | |
| 120 | if (PMAP_HAS_DMAP) |
| 121 | return ((struct sf_buf *)m); |
| 122 | |
| 123 | KASSERT(curthread->td_pinned > 0 || (flags & SFB_CPUPRIVATE) == 0, |
| 124 | ("sf_buf_alloc(SFB_CPUPRIVATE): curthread not pinned")); |
| 125 | hash_list = &sf_buf_active[SF_BUF_HASH(m)]; |
| 126 | mtx_lock(&sf_buf_lock); |
| 127 | LIST_FOREACH(sf, hash_list, list_entry) { |
| 128 | if (sf->m == m) { |
| 129 | sf->ref_count++; |
| 130 | if (sf->ref_count == 1) { |
| 131 | TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); |
| 132 | nsfbufsused++; |
| 133 | nsfbufspeak = imax(nsfbufspeak, nsfbufsused); |
| 134 | } |
| 135 | #if defined(SMP) && defined(SFBUF_CPUSET) |
| 136 | sf_buf_shootdown(sf, flags); |
| 137 | #endif |
| 138 | goto done; |
| 139 | } |
| 140 | } |
| 141 | while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) { |
| 142 | if (flags & SFB_NOWAIT) |
| 143 | goto done; |
| 144 | sf_buf_alloc_want++; |
| 145 | SFSTAT_INC(sf_allocwait); |
| 146 | error = msleep(&sf_buf_freelist, &sf_buf_lock, |
| 147 | (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); |
| 148 | sf_buf_alloc_want--; |
| 149 | |
| 150 | /* |
| 151 | * If we got a signal, don't risk going back to sleep. |
| 152 | */ |
| 153 | if (error) |
| 154 | goto done; |
| 155 | } |
| 156 | TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); |
| 157 | if (sf->m != NULL) |
| 158 | LIST_REMOVE(sf, list_entry); |
| 159 | LIST_INSERT_HEAD(hash_list, sf, list_entry); |
| 160 | sf->ref_count = 1; |
| 161 | sf->m = m; |
| 162 | nsfbufsused++; |
| 163 | nsfbufspeak = imax(nsfbufspeak, nsfbufsused); |
| 164 | sf_buf_map(sf, flags); |
| 165 | done: |
| 166 | mtx_unlock(&sf_buf_lock); |
| 167 | return (sf); |
| 168 | } |
| 169 | |
| 170 | /* |
no test coverage detected