/* * Routine: lock_try_read_to_write * Function: * Improves a read-only lock to one with * write permission. If another reader has * already requested an upgrade to a write lock, * the read lock is still held upon return. * * Returns FALSE if the upgrade *failed*. */ boolean_t lock_try_read_to_write( register lock_t l) { check_simple_locks(); simple_lock(&l->interlock); if (l->thread == current_thread()) { /* * Recursive lock */ l->read_count--; l->recursion_depth++; simple_unlock(&l->interlock); return TRUE; } if (l->want_upgrade) { simple_unlock(&l->interlock); return FALSE; } l->want_upgrade = TRUE; l->read_count--; while (l->read_count != 0) { l->waiting = TRUE; thread_sleep(l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } simple_unlock(&l->interlock); return TRUE; }
void lock_write( register lock_t l) { register int i; check_simple_locks(); simple_lock(&l->interlock); if (l->thread == current_thread()) { /* * Recursive lock. */ l->recursion_depth++; simple_unlock(&l->interlock); return; } /* * Try to acquire the want_write bit. */ while (l->want_write) { if ((i = lock_wait_time) > 0) { simple_unlock(&l->interlock); while (--i > 0 && l->want_write) continue; simple_lock(&l->interlock); } if (l->can_sleep && l->want_write) { l->waiting = TRUE; thread_sleep(l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } } l->want_write = TRUE; /* Wait for readers (and upgrades) to finish */ while ((l->read_count != 0) || l->want_upgrade) { if ((i = lock_wait_time) > 0) { simple_unlock(&l->interlock); while (--i > 0 && (l->read_count != 0 || l->want_upgrade)) continue; simple_lock(&l->interlock); } if (l->can_sleep && (l->read_count != 0 || l->want_upgrade)) { l->waiting = TRUE; thread_sleep(l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } } simple_unlock(&l->interlock); }
/* * Routine: lock_read_to_write * Function: * Improves a read-only lock to one with * write permission. If another reader has * already requested an upgrade to a write lock, * no lock is held upon return. * * Returns TRUE if the upgrade *failed*. */ boolean_t lock_read_to_write( register lock_t l) { register int i; check_simple_locks(); simple_lock(&l->interlock); l->read_count--; if (l->thread == current_thread()) { /* * Recursive lock. */ l->recursion_depth++; simple_unlock(&l->interlock); return(FALSE); } if (l->want_upgrade) { /* * Someone else has requested upgrade. * Since we've released a read lock, wake * him up. */ if (l->waiting && (l->read_count == 0)) { l->waiting = FALSE; thread_wakeup(l); } simple_unlock(&l->interlock); return TRUE; } l->want_upgrade = TRUE; while (l->read_count != 0) { if ((i = lock_wait_time) > 0) { simple_unlock(&l->interlock); while (--i > 0 && l->read_count != 0) continue; simple_lock(&l->interlock); } if (l->can_sleep && l->read_count != 0) { l->waiting = TRUE; thread_sleep(l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } } simple_unlock(&l->interlock); return FALSE; }
void ipc_port_release_send( ipc_port_t port) { ipc_port_t nsrequest = IP_NULL; mach_port_mscount_t mscount; assert(IP_VALID(port)); ip_lock(port); if (!ip_active(port)) { ip_unlock(port); ip_release(port); return; } assert(port->ip_srights > 0); if (--port->ip_srights == 0 && port->ip_nsrequest != IP_NULL) { nsrequest = port->ip_nsrequest; port->ip_nsrequest = IP_NULL; mscount = port->ip_mscount; ip_unlock(port); ipc_notify_no_senders(nsrequest, mscount); #if 0 /* * Check that there are no other locks taken, because * [norma_]ipc_notify_no_senders routines may block. */ check_simple_locks(); #endif } else ip_unlock(port); ip_release(port); }
void lock_read( register lock_t l) { register int i; check_simple_locks(); simple_lock(&l->interlock); if (l->thread == current_thread()) { /* * Recursive lock. */ l->read_count++; simple_unlock(&l->interlock); return; } while (l->want_write || l->want_upgrade) { if ((i = lock_wait_time) > 0) { simple_unlock(&l->interlock); while (--i > 0 && (l->want_write || l->want_upgrade)) continue; simple_lock(&l->interlock); } if (l->can_sleep && (l->want_write || l->want_upgrade)) { l->waiting = TRUE; thread_sleep(l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } } l->read_count++; simple_unlock(&l->interlock); }