Ejemplo n.º 1
0
static void
notify_irq(u8 vector)
{
	u32 n = cpuno();
	vm_t *v = &cpu_vm[n];

	nested_spinlock(&v->v_notes_lock);

	list_t *elem;
	while ((elem = list_remove_head(&v->v_notes_list)) != NULL) {
		nested_spinunlock(&v->v_notes_lock);

		note_t *note = super(elem, note_t, nb_list[n]);
		if (note->nb_func) {
			note->nb_func(v, note->nb_arg0, note->nb_arg1);
		}
		fence();
		atomic_inc(&note->nb_completion_count);

		nested_spinlock(&v->v_notes_lock);
	}
	nested_spinunlock(&v->v_notes_lock);
}
Ejemplo n.º 2
0
dm_tokevent_t *
dm_find_mount_tevp_and_lock(
	fsid_t		*fsidp,
	int		*lcp)		/* address of returned lock cookie */
{
	dm_fsreg_t	*fsrp;

	if ((fsrp = dm_find_fsreg_and_lock(fsidp, lcp)) == NULL)
		return(NULL);

	if (!fsrp->fr_tevp || fsrp->fr_state != DM_STATE_MOUNTING) {
		mutex_spinunlock(&fsrp->fr_lock, *lcp);
		return(NULL);
	}
	nested_spinlock(&fsrp->fr_tevp->te_lock);
	nested_spinunlock(&fsrp->fr_lock);
	return(fsrp->fr_tevp);
}
Ejemplo n.º 3
0
int
dm_find_msg_and_lock(
	dm_sessid_t	sid,
	dm_token_t	token,
	dm_tokevent_t	**tevpp,
	int		*lcp)		/* address of returned lock cookie */
{
	dm_session_t	*s;
	int		error;

	if ((error = dm_find_session_and_lock(sid, &s, lcp)) != 0)
		return(error);

	if ((error = dm_find_msg(s, token, tevpp)) != 0) {
		mutex_spinunlock(&s->sn_qlock, *lcp);
		return(error);
	}
	nested_spinlock(&(*tevpp)->te_lock);
	nested_spinunlock(&s->sn_qlock);
	return(0);
}
Ejemplo n.º 4
0
void
dm_clear_fsreg(
	dm_session_t	*s)
{
	dm_fsreg_t	*fsrp;
	int		event;
	int		lc;			/* lock cookie */

	lc = mutex_spinlock(&dm_reg_lock);

	for (fsrp = dm_registers; fsrp != NULL; fsrp = fsrp->fr_next) {
		nested_spinlock(&fsrp->fr_lock);
		for (event = 0; event < DM_EVENT_MAX; event++) {
			if (fsrp->fr_sessp[event] != s)
				continue;
			fsrp->fr_sessp[event] = NULL;
			if (event == DM_EVENT_DESTROY)
				bzero(&fsrp->fr_rattr, sizeof(fsrp->fr_rattr));
		}
		nested_spinunlock(&fsrp->fr_lock);
	}

	mutex_spinunlock(&dm_reg_lock, lc);
}
Ejemplo n.º 5
0
void
dm_remove_fsys_entry(
	vfs_t		*vfsp)
{
	dm_fsreg_t	**fsrpp;
	dm_fsreg_t	*fsrp;
	int		lc;			/* lock cookie */

	/* Find the filesystem referenced by the vfsp's fsid_t and dequeue
	   it after verifying that the fr_state shows a filesystem that is
	   either mounting or unmounted.
	*/

	lc = mutex_spinlock(&dm_reg_lock);

	fsrpp = &dm_registers;
	while ((fsrp = *fsrpp) != NULL) {
		if (!bcmp(&fsrp->fr_fsid, vfsp->vfs_altfsid, sizeof(fsrp->fr_fsid)))
			break;
		fsrpp = &fsrp->fr_next;
	}
	if (fsrp == NULL) {
		mutex_spinunlock(&dm_reg_lock, lc);
		panic("dm_remove_fsys_entry: can't find DMAPI fsrp for "
			"vfsp %p\n", vfsp);
	}

	nested_spinlock(&fsrp->fr_lock);

	/* Verify that it makes sense to remove this entry. */

	if (fsrp->fr_state != DM_STATE_MOUNTING &&
	    fsrp->fr_state != DM_STATE_UNMOUNTED) {
		nested_spinunlock(&fsrp->fr_lock);
		mutex_spinunlock(&dm_reg_lock, lc);
		panic("dm_remove_fsys_entry: DMAPI sequence error: old state "
			"%d, fsrp %p\n", fsrp->fr_state, fsrp);
	}

	*fsrpp = fsrp->fr_next;
	dm_fsys_cnt--;

	nested_spinunlock(&dm_reg_lock);

	/* Since the filesystem is about to finish unmounting, we must be sure
	   that no vnodes are being referenced within the filesystem before we
	   let this event thread continue.  If the filesystem is currently in
	   state DM_STATE_MOUNTING, then we know by definition that there can't
	   be any references.  If the filesystem is DM_STATE_UNMOUNTED, then
	   any application threads referencing handles with DM_NO_TOKEN should
	   have already been awakened by dm_change_fsys_entry and should be
	   long gone by now.  Just in case they haven't yet left, sleep here
	   until they are really gone.
	*/

	while (fsrp->fr_hdlcnt) {
		fsrp->fr_unmount++;
		sv_wait(&fsrp->fr_queue, 1, &fsrp->fr_lock, lc);
		lc = mutex_spinlock(&fsrp->fr_lock);
		fsrp->fr_unmount--;
	}
	mutex_spinunlock(&fsrp->fr_lock, lc);

	/* Release all memory. */

#ifdef CONFIG_PROC_FS
	{
	char buf[100];
	sprintf(buf, DMAPI_DBG_PROCFS "/fsreg/0x%p", fsrp);
	remove_proc_entry(buf, NULL);
	}
#endif
	sv_destroy(&fsrp->fr_dispq);
	sv_destroy(&fsrp->fr_queue);
	spinlock_destroy(&fsrp->fr_lock);
	kmem_free(fsrp->fr_msg, fsrp->fr_msgsize);
	kmem_free(fsrp, sizeof(*fsrp));
}
Ejemplo n.º 6
0
void
notify_all(nb_func_t func, nb_arg_t arg0, nb_arg_t arg1)
{
	sn this = cpuno();

	assert(irq_is_disabled());

	if (unlikely(notify_intvec == 0)) {
		func(&cpu_vm[this], arg0, arg1);
		return;
	}

	note_t note;
	un count = 0;

	note.nb_func = func;
	note.nb_arg0 = arg0;
	note.nb_arg1 = arg1;
	note.nb_completion_count = 0;
	/* No need to list_init(&note.nb_list[i]) because adding an element
	 * to a list will overwrite the element's prev and next ptrs.
	 */

	un notify_mask = 0;
	for_each_active_cpu(i) {
		if (i == this) {
			continue;
		}
		vm_t *v = &cpu_vm[i];
		nested_spinlock(&v->v_notes_lock);
		list_add_tail(&v->v_notes_list, &note.nb_list[i]);
		nested_spinunlock(&v->v_notes_lock);
		bit_set(notify_mask, i);

		apic_send_IPI(i, notify_intvec);
		count++;
	}

	func(&cpu_vm[this], arg0, arg1);

	fence();
	u64 timeout = rdtsc() + TSC_TIMEOUT;
	while (volatile_read(&note.nb_completion_count) < count) {
		/* Poll for incoming notifications */
		notify_irq(0);
		if (rdtsc() > timeout) {
			kprintf("notify_all>TIMEOUT %u %ld\n",
				volatile_read(&note.nb_completion_count),
				count /* ,
				note.nb_ack_map */);
			for_each_cpu(i, notify_mask) {
				vm_t *v = &cpu_vm[i];
				nested_spinlock(&v->v_notes_lock);
				/* If the element was already removed, this
				 * is a no-op.
				 */
				list_remove(&note.nb_list[i]);
				nested_spinunlock(&v->v_notes_lock);
			}
			return;
		}