tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: passive references



   Date: Tue, 9 Feb 2016 13:00:28 +0900
   From: Ryota Ozaki <ozaki-r%netbsd.org@localhost>

   One fix: psref_class_create needs to return class before fail1.

Oops!

   One question: can we destroy objects like this?:
     LIST_FOREACH_SAFE(frotz, &frobbotzim.head, frotz_entry, tmp) {
       frotz_destroy(frotz);
     }

   If impossible, please teach me how to destroy all objects in a list
   safely with psref.

If you can guarantee that nobody else will try to insert or destroy
new frobbotzim, then that is safe.

Otherwise, hmm...  Maybe something like this -- like the way
bridge_clone_destroy/bridge_delete_member already work:

struct frotz {
	struct psref_target	f_psref;
	struct frotz		*f_next;
	struct frotz		**f_prevp;
	...
};

static struct {
	kmutex_t		lock;
	pserialize_t		psz;
	struct psref_class	*class;
	struct frotz		*first;
	bool			no_more_please;
} frobbotzim __cacheline_aligned;

static void
frobbotzim_destroy(void)
{
	struct frotz *frotz;

	mutex_enter(&frobbotzim.lock);
	/* Prevent creation of new frobbotzim.  */
	frobbotzim.no_more_please = true;
	/* Destroy all existing frobbotzim.  */
	while ((frotz = frobbotzim.first) != NULL)
		frotz_destroy(frotz);
	mutex_exit(&frobbotzim.lock);
}

static void
frotz_destroy(struct frotz *frotz)
{

	KASSERT(mutex_owned(&frobbotzim.lock));

	/* Prevent new references.  */
	if (frotz->f_next != NULL)
		frotz->f_next->f_prevp = frotz->f_prevp;
	*frotz->f_prevp = frotz->f_next;
	pserialize_perform(frobbotzim.psz);

	/* Release lock while we wait for references to drain.  */
	mutex_exit(&frobbotzim.lock)

	/* Wait for existing references to drain.  */
	psref_target_drain(&frotz->f_psref, frobbotzim.class);

	/* Destroy the frotz for real.  */
	...destroy fields...
	kmem_free(frotz, sizeof(*frotz));

	/* Reacquire lock for caller.  */
	mutex_enter(&frobbotzim.lock);
}

(In the example sketch I wrote for frotz_destroy before, I did things
out of order: drained references with psref_target_drain before
preventing new references by removing it from the list.  I also forgot
that queue(3) is not pserialize-safe.)


Home | Main Index | Thread Index | Old Index