* Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)uipc_mbuf.c 7.4.1.1 (Berkeley) %G%
#include "../machine/pte.h"
#define NCL_INIT (4096/CLBYTES)
if (m_clalloc(NCL_INIT
, MPG_MBUFS
, M_DONTWAIT
) == 0)
if (m_clalloc(NCL_INIT
, MPG_CLUSTERS
, M_DONTWAIT
) == 0)
* Must be called at splimp.
m_clalloc(ncl
, how
, canwait
)
mbx
= rmalloc(mbmap
, (long)npg
);
log(LOG_ERR
, "mbuf map full\n");
m
= cltom(mbx
* NBPG
/ MCLBYTES
);
if (memall(&Mbmap
[mbx
], npg
, proc
, CSYS
) == 0) {
rmfree(mbmap
, (long)npg
, (long)mbx
);
vmaccess(&Mbmap
[mbx
], (caddr_t
)m
, npg
);
ncl
= ncl
* CLBYTES
/ MCLBYTES
;
for (i
= 0; i
< ncl
; i
++) {
m
+= MCLBYTES
/ sizeof (*m
);
mbstat
.m_clusters
+= ncl
;
for (i
= ncl
* CLBYTES
/ sizeof (*m
); i
> 0; i
--) {
mbstat
.m_mtypes
[MT_DATA
]++;
* Must be called at splimp.
register struct domain
*dp
;
register struct protosw
*pr
;
if (m_clalloc(1, MPG_MBUFS
, canwait
))
if (canwait
== 0 || tries
++)
/* ask protocols to free space */
for (dp
= domains
; dp
; dp
= dp
->dom_next
)
for (pr
= dp
->dom_protosw
; pr
< dp
->dom_protoswNPROTOSW
;
/* NEED SOME WAY TO RELEASE SPACE */
* Space allocation routines.
* These are also available as macros
bzero(mtod(m
, caddr_t
), MLEN
);
* Get more mbufs; called from MGET macro if mfree list is empty.
* Must be called at splimp.
while (m_expand(canwait
) == 0) {
sleep((caddr_t
)&mfree
, PZERO
- 1);
#define m_more(x,y) (panic("m_more"), (struct mbuf *)0)
* Mbuffer utility routines.
* Make a copy of an mbuf chain starting "off" bytes from the beginning,
* continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
* Should get M_WAIT/M_DONTWAIT from caller.
register struct mbuf
*n
, **np
;
MGET(n
, M_DONTWAIT
, m
->m_type
);
n
->m_len
= MIN(len
, m
->m_len
- off
);
if (m
->m_off
> MMAXOFF
) {
p
= mtod(m
, struct mbuf
*);
n
->m_off
= ((int)p
- (int)n
) + off
;
bcopy(mtod(m
, caddr_t
)+off
, mtod(n
, caddr_t
),
register struct mbuf
*m
, *n
;
if (m
->m_off
>= MMAXOFF
||
m
->m_off
+ m
->m_len
+ n
->m_len
> MMAXOFF
) {
/* just join the two chains */
/* splat the data from one into the other */
bcopy(mtod(n
, caddr_t
), mtod(m
, caddr_t
) + m
->m_len
,
while (m
!= NULL
&& len
> 0) {
* Trim from tail. Scan the mbuf chain,
* calculating its length and finding the last mbuf.
* If the adjustment only affects this mbuf, then just
* adjust and return. Otherwise, rescan and truncate
* after the remaining size.
if (m
->m_next
== (struct mbuf
*)0)
* Correct length for chain is "count".
* Find the mbuf with last data, adjust its length,
* and toss data from remaining mbufs on chain.
for (m
= mp
; m
; m
= m
->m_next
) {
* Rearange an mbuf chain so that len bytes are contiguous
* and in the data area of an mbuf (so that mtod and dtom
* will work for a structure of size len). Returns the resulting
* mbuf chain on success, frees it and returns null on failure.
* If there is room, it will add up to MPULL_EXTRA bytes to the
* contiguous region in an attempt to avoid being called next time.
if (n
->m_off
+ len
<= MMAXOFF
&& n
->m_next
) {
MGET(m
, M_DONTWAIT
, n
->m_type
);
space
= MMAXOFF
- m
->m_off
;
count
= MIN(MIN(space
- m
->m_len
, len
+ MPULL_EXTRA
), n
->m_len
);
bcopy(mtod(n
, caddr_t
), mtod(m
, caddr_t
)+m
->m_len
,