On Tue, Oct 23, 2001 at 03:17:04PM -0400, Garrett Wollman wrote: > <<On Tue, 23 Oct 2001 11:03:07 -0700, Luigi Rizzo <[EMAIL PROTECTED]> said: > > > Similar things could be done in m_pullup() to avoid the > > extra allocation. > > Can't be done in m_pullup: the whole purpose of m_pullup is to > *guarantee* that the data in question will never be shared. It might > be worth having a new interface which doesn't provide such a > guarantee.
You are right, we cannot change the semantics of m_pullup() without carefully analysing how it is used, and this definitely calls for one or two new interfaces (m_pullup_readonly(), m_pullup_writable()). Technically, it is correct that m_pullup guarantees that the data in question will never be shared, but it seems to me more an artifact of its implementation than a real goal. >From what i see, m_pullup() is mostly used to make sure that a block is contiguous, and in some other cases to have a writable copy of the block. In both cases being able to write into the cluster would save a bit of work. Yes, there are situations (e.g. where you are replicating a packet and changing some things in the header for each replica -- see EXAMPLE 1) where the current semantics of m_pullup() _seems_ to save something, but this comes at the price of an m_copy() so there is really no saving compared to EXAMPLE 2. By having the new m_pullup_XXX() calls, you could rewrite the same code as in EXAMPLE 3, with the advantage that the first instance could turn into a no-op, and you replicate only if really necessary. cheers luigi ----------------------------------------------------------------- EXAMPLE 1: /* some pieces of the kernel are like this */ m = m_pullup(m, some_len); for (;;) { <change something in the private part of m> n = m_copy(m, 0, M_COPYALL); <pass n around> if (some_condition) break ; } m_free(m); EXAMPLE 2: /* they could be rewritten in this way */ canfree = 1; for (;;) { n = m_pullup(m, some_len); if (n == m) canfree=0; <change something in the private part of n> <pass n around> if (some_condition) break ; } if (canfree) m_free(m); EXAMPLE 3: /* or in this way with a new m_pullupXXX() interface */ for (;;) { n = m_pullup_writable(m, some_len); if (n == m) canfree=0; <change something in n> <pass n around> if (some_condition) break ; } if (canfree) m_free(m); ----------------------------------+----------------------------------------- Luigi RIZZO, [EMAIL PROTECTED] . ACIRI/ICSI (on leave from Univ. di Pisa) http://www.iet.unipi.it/~luigi/ . 1947 Center St, Berkeley CA 94704 Phone: (510) 666 2927 ----------------------------------+----------------------------------------- To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-net" in the body of the message