- i = lock_wait_time[l->can_sleep ? 1 : 0];
- if (i != 0) {
- lck_spin_unlock(&l->interlock);
- while (--i != 0 && l->want_write)
- continue;
- lck_spin_lock(&l->interlock);
- }
-
- if (l->can_sleep && l->want_write) {
- l->waiting = TRUE;
- lck_spin_sleep( &l->interlock, LCK_SLEEP_DEFAULT,
- (event_t) l, THREAD_UNINT);
- /* interlock relocked */
- }
- }
- l->want_write = TRUE;
-
- /* Wait for readers (and upgrades) to finish */
-
- while ((l->read_count != 0) || l->want_upgrade) {
-
- i = lock_wait_time[l->can_sleep ? 1 : 0];
- if (i != 0) {
- lck_spin_unlock(&l->interlock);
- while (--i != 0 && (l->read_count != 0 ||
- l->want_upgrade))
- continue;
- lck_spin_lock(&l->interlock);
- }
-
- if (l->can_sleep && (l->read_count != 0 || l->want_upgrade)) {
- l->waiting = TRUE;
- lck_spin_sleep( &l->interlock, LCK_SLEEP_DEFAULT,
- (event_t) l, THREAD_UNINT);
- /* interlock relocked */
- }
- }
-
- lck_spin_unlock(&l->interlock);
-}
-
-static void
-s_lock_done(
- register s_lock_t * l)
-{
- boolean_t do_wakeup = FALSE;
-
- lck_spin_lock(&l->interlock);
-
- if (l->read_count != 0) {
- l->read_count -= 1;
- }
- else {
- if (l->want_upgrade) {
- l->want_upgrade = FALSE;
- }
- else {
- l->want_write = FALSE;
- }
- }
-
- /*
- * There is no reason to wakeup a waiting thread
- * if the read-count is non-zero. Consider:
- * we must be dropping a read lock
- * threads are waiting only if one wants a write lock
- * if there are still readers, they can't proceed
- */
- if (l->waiting && (l->read_count == 0)) {
- l->waiting = FALSE;
- do_wakeup = TRUE;
- }
-
- lck_spin_unlock(&l->interlock);
-
- if (do_wakeup)
- thread_wakeup((event_t) l);
-}
-
-static void
-s_lock_read(
- register s_lock_t * l)
-{
- register int i;
-
- lck_spin_lock(&l->interlock);
-
- while ( l->want_upgrade || ((0 == l->read_count) && l->want_write )) {
-
- i = lock_wait_time[l->can_sleep ? 1 : 0];
-
- if (i != 0) {
- lck_spin_unlock(&l->interlock);
- while (--i != 0 &&
- (l->want_upgrade || ((0 == l->read_count) && l->want_write )))
- continue;
- lck_spin_lock(&l->interlock);
- }
-
- if (l->can_sleep &&
- (l->want_upgrade || ((0 == l->read_count) && l->want_write ))) {
- l->waiting = TRUE;
- lck_spin_sleep( &l->interlock, LCK_SLEEP_DEFAULT,
- (event_t) l, THREAD_UNINT);
- /* interlock relocked */
- }
- }
-
- l->read_count += 1;
- lck_spin_unlock(&l->interlock);
-
-}