Date: Tue, 9 Feb 2016 13:00:28 +0900
   From: Ryota Ozaki <[email protected]>

   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.)

Reply via email to