Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
0
/*
 *	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;
}
Пример #5
0
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);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
0
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);
}
Пример #9
0
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);

}
Пример #10
0
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);
}