Print this page
patch as-lock-macro-simplification


 185 {
 186         caddr_t addr = (caddr_t)a;
 187         caddr_t page;
 188         caddr_t vaddr;
 189         struct seg *seg;
 190         int error = 0;
 191         int err = 0;
 192         uint_t prot;
 193         uint_t prot_rw = writing ? PROT_WRITE : PROT_READ;
 194         int protchanged;
 195         on_trap_data_t otd;
 196         int retrycnt;
 197         struct as *as = p->p_as;
 198         enum seg_rw rw;
 199 
 200         /*
 201          * Locate segment containing address of interest.
 202          */
 203         page = (caddr_t)(uintptr_t)((uintptr_t)addr & PAGEMASK);
 204         retrycnt = 0;
 205         AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
 206 retry:
 207         if ((seg = as_segat(as, page)) == NULL ||
 208             !page_valid(seg, page)) {
 209                 AS_LOCK_EXIT(as, &as->a_lock);
 210                 return (ENXIO);
 211         }
 212         SEGOP_GETPROT(seg, page, 0, &prot);
 213 
 214         protchanged = 0;
 215         if ((prot & prot_rw) == 0) {
 216                 protchanged = 1;
 217                 err = SEGOP_SETPROT(seg, page, PAGESIZE, prot | prot_rw);
 218 
 219                 if (err == IE_RETRY) {
 220                         protchanged = 0;
 221                         ASSERT(retrycnt == 0);
 222                         retrycnt++;
 223                         goto retry;
 224                 }
 225 
 226                 if (err != 0) {
 227                         AS_LOCK_EXIT(as, &as->a_lock);
 228                         return (ENXIO);
 229                 }
 230         }
 231 
 232         /*
 233          * segvn may do a copy-on-write for F_SOFTLOCK/S_READ case to break
 234          * sharing to avoid a copy on write of a softlocked page by another
 235          * thread. But since we locked the address space as a writer no other
 236          * thread can cause a copy on write. S_READ_NOCOW is passed as the
 237          * access type to tell segvn that it's ok not to do a copy-on-write
 238          * for this SOFTLOCK fault.
 239          */
 240         if (writing)
 241                 rw = S_WRITE;
 242         else if (seg->s_ops == &segvn_ops)
 243                 rw = S_READ_NOCOW;
 244         else
 245                 rw = S_READ;
 246 
 247         if (SEGOP_FAULT(as->a_hat, seg, page, PAGESIZE, F_SOFTLOCK, rw)) {
 248                 if (protchanged)
 249                         (void) SEGOP_SETPROT(seg, page, PAGESIZE, prot);
 250                 AS_LOCK_EXIT(as, &as->a_lock);
 251                 return (ENXIO);
 252         }
 253         CPU_STATS_ADD_K(vm, softlock, 1);
 254 
 255         /*
 256          * Make sure we're not trying to read or write off the end of the page.
 257          */
 258         ASSERT(len <= page + PAGESIZE - addr);
 259 
 260         /*
 261          * Map in the locked page, copy to our local buffer,
 262          * then map the page out and unlock it.
 263          */
 264         vaddr = mapin(as, addr, writing);
 265 
 266         /*
 267          * Since we are copying memory on behalf of the user process,
 268          * protect against memory error correction faults.
 269          */
 270         if (!on_trap(&otd, OT_DATA_EC)) {


 291         }
 292         no_trap();
 293 
 294         /*
 295          * If we're writing to an executable page, we may need to sychronize
 296          * the I$ with the modifications we made through the D$.
 297          */
 298         if (writing && (prot & PROT_EXEC))
 299                 sync_icache(vaddr, (uint_t)len);
 300 
 301         mapout(as, addr, vaddr, writing);
 302 
 303         if (rw == S_READ_NOCOW)
 304                 rw = S_READ;
 305 
 306         (void) SEGOP_FAULT(as->a_hat, seg, page, PAGESIZE, F_SOFTUNLOCK, rw);
 307 
 308         if (protchanged)
 309                 (void) SEGOP_SETPROT(seg, page, PAGESIZE, prot);
 310 
 311         AS_LOCK_EXIT(as, &as->a_lock);
 312 
 313         return (error);
 314 }
 315 
 316 int
 317 uread(proc_t *p, void *buf, size_t len, uintptr_t a)
 318 {
 319         return (urw(p, 0, buf, len, a));
 320 }
 321 
 322 int
 323 uwrite(proc_t *p, void *buf, size_t len, uintptr_t a)
 324 {
 325         return (urw(p, 1, buf, len, a));
 326 }


 185 {
 186         caddr_t addr = (caddr_t)a;
 187         caddr_t page;
 188         caddr_t vaddr;
 189         struct seg *seg;
 190         int error = 0;
 191         int err = 0;
 192         uint_t prot;
 193         uint_t prot_rw = writing ? PROT_WRITE : PROT_READ;
 194         int protchanged;
 195         on_trap_data_t otd;
 196         int retrycnt;
 197         struct as *as = p->p_as;
 198         enum seg_rw rw;
 199 
 200         /*
 201          * Locate segment containing address of interest.
 202          */
 203         page = (caddr_t)(uintptr_t)((uintptr_t)addr & PAGEMASK);
 204         retrycnt = 0;
 205         AS_LOCK_ENTER(as, RW_WRITER);
 206 retry:
 207         if ((seg = as_segat(as, page)) == NULL ||
 208             !page_valid(seg, page)) {
 209                 AS_LOCK_EXIT(as);
 210                 return (ENXIO);
 211         }
 212         SEGOP_GETPROT(seg, page, 0, &prot);
 213 
 214         protchanged = 0;
 215         if ((prot & prot_rw) == 0) {
 216                 protchanged = 1;
 217                 err = SEGOP_SETPROT(seg, page, PAGESIZE, prot | prot_rw);
 218 
 219                 if (err == IE_RETRY) {
 220                         protchanged = 0;
 221                         ASSERT(retrycnt == 0);
 222                         retrycnt++;
 223                         goto retry;
 224                 }
 225 
 226                 if (err != 0) {
 227                         AS_LOCK_EXIT(as);
 228                         return (ENXIO);
 229                 }
 230         }
 231 
 232         /*
 233          * segvn may do a copy-on-write for F_SOFTLOCK/S_READ case to break
 234          * sharing to avoid a copy on write of a softlocked page by another
 235          * thread. But since we locked the address space as a writer no other
 236          * thread can cause a copy on write. S_READ_NOCOW is passed as the
 237          * access type to tell segvn that it's ok not to do a copy-on-write
 238          * for this SOFTLOCK fault.
 239          */
 240         if (writing)
 241                 rw = S_WRITE;
 242         else if (seg->s_ops == &segvn_ops)
 243                 rw = S_READ_NOCOW;
 244         else
 245                 rw = S_READ;
 246 
 247         if (SEGOP_FAULT(as->a_hat, seg, page, PAGESIZE, F_SOFTLOCK, rw)) {
 248                 if (protchanged)
 249                         (void) SEGOP_SETPROT(seg, page, PAGESIZE, prot);
 250                 AS_LOCK_EXIT(as);
 251                 return (ENXIO);
 252         }
 253         CPU_STATS_ADD_K(vm, softlock, 1);
 254 
 255         /*
 256          * Make sure we're not trying to read or write off the end of the page.
 257          */
 258         ASSERT(len <= page + PAGESIZE - addr);
 259 
 260         /*
 261          * Map in the locked page, copy to our local buffer,
 262          * then map the page out and unlock it.
 263          */
 264         vaddr = mapin(as, addr, writing);
 265 
 266         /*
 267          * Since we are copying memory on behalf of the user process,
 268          * protect against memory error correction faults.
 269          */
 270         if (!on_trap(&otd, OT_DATA_EC)) {


 291         }
 292         no_trap();
 293 
 294         /*
 295          * If we're writing to an executable page, we may need to sychronize
 296          * the I$ with the modifications we made through the D$.
 297          */
 298         if (writing && (prot & PROT_EXEC))
 299                 sync_icache(vaddr, (uint_t)len);
 300 
 301         mapout(as, addr, vaddr, writing);
 302 
 303         if (rw == S_READ_NOCOW)
 304                 rw = S_READ;
 305 
 306         (void) SEGOP_FAULT(as->a_hat, seg, page, PAGESIZE, F_SOFTUNLOCK, rw);
 307 
 308         if (protchanged)
 309                 (void) SEGOP_SETPROT(seg, page, PAGESIZE, prot);
 310 
 311         AS_LOCK_EXIT(as);
 312 
 313         return (error);
 314 }
 315 
 316 int
 317 uread(proc_t *p, void *buf, size_t len, uintptr_t a)
 318 {
 319         return (urw(p, 0, buf, len, a));
 320 }
 321 
 322 int
 323 uwrite(proc_t *p, void *buf, size_t len, uintptr_t a)
 324 {
 325         return (urw(p, 1, buf, len, a));
 326 }