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); }
int boot_script_exec_cmd (void *hook, task_t task, char *path, int argc, char **argv, char *strings, int stringlen) { struct multiboot_module *mod = hook; int err; if (task != MACH_PORT_NULL) { thread_t thread; struct user_bootstrap_info info = { mod, argv, 0, }; simple_lock_init (&info.lock); simple_lock (&info.lock); err = thread_create ((task_t)task, &thread); assert(err == 0); thread->saved.other = &info; thread_start (thread, user_bootstrap); thread_resume (thread); /* We need to synchronize with the new thread and block this main thread until it has finished referring to our local state. */ while (! info.done) { thread_sleep ((event_t) &info, simple_lock_addr(info.lock), FALSE); simple_lock (&info.lock); } printf ("\n"); } return 0; }
/* * 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; }
/* * 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 db_show_one_lock( lock_t *lock) { db_printf("Read_count = 0x%x, %swant_upgrade, %swant_write, ", lock->read_count, lock->want_upgrade ? "" : "!", lock->want_write ? "" : "!"); db_printf("%swaiting, %scan_sleep\n", lock->waiting ? "" : "!", lock->can_sleep ? "" : "!"); db_printf("Interlock:\n"); db_show_one_simple_lock((db_expr_t)simple_lock_addr(lock->interlock), TRUE, (db_expr_t)0, (char *)0); }
void db_show_one_lock( lock_t *lock) { db_printf("Read_count = 0x%x, %swant_upgrade, %swant_write, ", lock->lck_rw_shared_count, lock->lck_rw_want_upgrade ? "" : "!", lock->lck_rw_want_write ? "" : "!"); db_printf("%swaiting, %scan_sleep\n", (lock->lck_r_waiting || lock->lck_w_waiting) ? "" : "!", lock->lck_rw_can_sleep ? "" : "!"); db_printf("Interlock:\n"); db_show_one_simple_lock((db_expr_t) ((vm_offset_t)simple_lock_addr(lock->lck_rw_interlock)), TRUE, (db_expr_t)0, (char *)0); }
vm_offset_t himem_convert( vm_offset_t phys_addr, vm_size_t length, int io_op, hil_t *hil) { hil_t h; spl_t ipl; vm_offset_t offset = phys_addr & (I386_PGBYTES - 1); assert (offset + length <= I386_PGBYTES); ipl = splhi(); simple_lock(&hil_lock); while (!(h = hil_head)) { printf("WARNING: out of HIMEM pages\n"); thread_sleep_simple_lock((event_t)&hil_head, simple_lock_addr(hil_lock), FALSE); simple_lock (&hil_lock); } hil_head = hil_head->next; simple_unlock(&hil_lock); splx(ipl); h->high_addr = phys_addr; if (io_op == D_WRITE) { bcopy((char *)phystokv(phys_addr), (char *)phystokv(h->low_page + offset), length); h->length = 0; } else { h->length = length; } h->offset = offset; assert(!*hil || (*hil)->high_addr); h->next = *hil; *hil = h; return(h->low_page + offset); }
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); }
void lock_write( register lock_t * l) { register int i; start_data_node_t entry = {0}; boolean_t lock_miss = FALSE; unsigned short dynamic = 0; unsigned short trace = 0; etap_time_t total_time; etap_time_t stop_wait_time; pc_t pc; #if MACH_LDEBUG int decrementer; #endif /* MACH_LDEBUG */ ETAP_STAMP(lock_event_table(l), trace, dynamic); ETAP_CREATE_ENTRY(entry, trace); MON_ASSIGN_PC(entry->start_pc, pc, trace); simple_lock(&l->interlock); /* * Link the new start_list entry */ ETAP_LINK_ENTRY(l, entry, trace); #if MACH_LDEBUG decrementer = DECREMENTER_TIMEOUT; #endif /* MACH_LDEBUG */ /* * Try to acquire the want_write bit. */ while (l->want_write) { if (!lock_miss) { ETAP_CONTENTION_TIMESTAMP(entry, trace); lock_miss = TRUE; } i = lock_wait_time[l->can_sleep ? 1 : 0]; if (i != 0) { simple_unlock(&l->interlock); #if MACH_LDEBUG if (!--decrementer) Debugger("timeout - want_write"); #endif /* MACH_LDEBUG */ while (--i != 0 && l->want_write) continue; simple_lock(&l->interlock); } if (l->can_sleep && l->want_write) { l->waiting = TRUE; ETAP_SET_REASON(current_thread(), BLOCKED_ON_COMPLEX_LOCK); thread_sleep_simple_lock((event_t) l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } } l->want_write = TRUE; /* Wait for readers (and upgrades) to finish */ #if MACH_LDEBUG decrementer = DECREMENTER_TIMEOUT; #endif /* MACH_LDEBUG */ while ((l->read_count != 0) || l->want_upgrade) { if (!lock_miss) { ETAP_CONTENTION_TIMESTAMP(entry,trace); lock_miss = TRUE; } i = lock_wait_time[l->can_sleep ? 1 : 0]; if (i != 0) { simple_unlock(&l->interlock); #if MACH_LDEBUG if (!--decrementer) Debugger("timeout - wait for readers"); #endif /* MACH_LDEBUG */ 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; ETAP_SET_REASON(current_thread(), BLOCKED_ON_COMPLEX_LOCK); thread_sleep_simple_lock((event_t) l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } } /* * do not collect wait data if either the lock * was free or no wait traces are enabled. */ if (lock_miss && ETAP_CONTENTION_ENABLED(trace)) { ETAP_TIMESTAMP(stop_wait_time); ETAP_TOTAL_TIME(total_time, stop_wait_time, entry->start_wait_time); CUM_WAIT_ACCUMULATE(l->cbuff_write, total_time, dynamic, trace); MON_DATA_COLLECT(l, entry, total_time, WRITE_LOCK, MON_CONTENTION, trace); } simple_unlock(&l->interlock); /* * Set start hold time if some type of hold tracing is enabled. * * Note: if the stop_wait_time was already stamped, use * it as the start_hold_time instead of doing an * expensive bus access. * */ if (lock_miss && ETAP_CONTENTION_ENABLED(trace)) ETAP_COPY_START_HOLD_TIME(entry, stop_wait_time, trace); else ETAP_DURATION_TIMESTAMP(entry, trace); }
boolean_t lock_read_to_write( register lock_t * l) { register int i; boolean_t do_wakeup = FALSE; start_data_node_t entry = {0}; boolean_t lock_miss = FALSE; unsigned short dynamic = 0; unsigned short trace = 0; etap_time_t total_time; etap_time_t stop_time; pc_t pc; #if MACH_LDEBUG int decrementer; #endif /* MACH_LDEBUG */ ETAP_STAMP(lock_event_table(l), trace, dynamic); simple_lock(&l->interlock); l->read_count--; /* * Since the read lock is lost whether the write lock * is acquired or not, read hold data is collected here. * This, of course, is assuming some type of hold * tracing is enabled. * * Note: trace is set to zero if the entry does not exist. */ ETAP_FIND_ENTRY(l, entry, trace); if (ETAP_DURATION_ENABLED(trace)) { ETAP_TIMESTAMP(stop_time); ETAP_TOTAL_TIME(total_time, stop_time, entry->start_hold_time); CUM_HOLD_ACCUMULATE(l->cbuff_read, total_time, dynamic, trace); MON_ASSIGN_PC(entry->end_pc, pc, trace); MON_DATA_COLLECT(l, entry, total_time, READ_LOCK, MON_DURATION, trace); } 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; do_wakeup = TRUE; } ETAP_UNLINK_ENTRY(l, entry); simple_unlock(&l->interlock); ETAP_DESTROY_ENTRY(entry); if (do_wakeup) thread_wakeup((event_t) l); return (TRUE); } l->want_upgrade = TRUE; MON_ASSIGN_PC(entry->start_pc, pc, trace); #if MACH_LDEBUG decrementer = DECREMENTER_TIMEOUT; #endif /* MACH_LDEBUG */ while (l->read_count != 0) { if (!lock_miss) { ETAP_CONTENTION_TIMESTAMP(entry, trace); lock_miss = TRUE; } i = lock_wait_time[l->can_sleep ? 1 : 0]; if (i != 0) { simple_unlock(&l->interlock); #if MACH_LDEBUG if (!--decrementer) Debugger("timeout - read_count"); #endif /* MACH_LDEBUG */ 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_simple_lock((event_t) l, simple_lock_addr(l->interlock), FALSE); simple_lock(&l->interlock); } } /* * do not collect wait data if the lock was free * or if no wait traces are enabled. */ if (lock_miss && ETAP_CONTENTION_ENABLED(trace)) { ETAP_TIMESTAMP (stop_time); ETAP_TOTAL_TIME(total_time, stop_time, entry->start_wait_time); CUM_WAIT_ACCUMULATE(l->cbuff_write, total_time, dynamic, trace); MON_DATA_COLLECT(l, entry, total_time, WRITE_LOCK, MON_CONTENTION, trace); } simple_unlock(&l->interlock); /* * Set start hold time if some type of hold tracing is enabled * * Note: if the stop_time was already stamped, use * it as the new start_hold_time instead of doing * an expensive VME access. * */ if (lock_miss && ETAP_CONTENTION_ENABLED(trace)) ETAP_COPY_START_HOLD_TIME(entry, stop_time, trace); else ETAP_DURATION_TIMESTAMP(entry, trace); return (FALSE); }