/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1995 Apple Computer, Inc.
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/fcntl.h>
+#include <sys/file_internal.h>
#include <sys/mbuf.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
+#include <kern/locks.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/ioccom.h>
+#include <sys/uio_internal.h>
#include <sys/sysctl.h>
#include <netat/debug.h>
extern struct atpcb ddp_head;
+extern lck_mtx_t * atalk_mutex;
extern void
ddp_putmsg(gref_t *gref, gbuf_t *m),
aurp_wput(gref_t *gref, gbuf_t *m),
#endif
adsp_wput(gref_t *gref, gbuf_t *m);
+
+int atp_free_cluster_timeout_set = 0;
+
void atalk_putnext(gref_t *gref, gbuf_t *m);
-static int gref_close(gref_t *gref);
+/* bms: make gref_close non static so its callable from kernel */
+int gref_close(gref_t *gref);
SYSCTL_DECL(_net_appletalk);
dbgBits_t dbgBits;
&dbgBits, dbgBits, "AppleTalk Debug Flags");
volatile int RouterMix = RT_MIX_DEFAULT; /* default for nbr of ppsec */
SYSCTL_INT(_net_appletalk, OID_AUTO, routermix, CTLFLAG_WR,
- &RouterMix, 0, "Appletalk RouterMix");
+ (int *)&RouterMix, 0, "Appletalk RouterMix");
at_ddp_stats_t at_ddp_stats; /* DDP statistics */
SYSCTL_STRUCT(_net_appletalk, OID_AUTO, ddpstats, CTLFLAG_RD,
&at_ddp_stats, at_ddp_stats, "AppleTalk DDP Stats");
-atlock_t refall_lock;
+static void ioccmd_t_32_to_64( ioccmd_t *from_p, user_ioccmd_t *to_p );
+static void ioccmd_t_64_to_32( user_ioccmd_t *from_p, ioccmd_t *to_p );
+
-static void gref_wput(gref, m)
+caddr_t atp_free_cluster_list = 0;
+
+void gref_wput(gref, m)
gref_t *gref;
gbuf_t *m;
{
gbuf_freem(gbuf_cont(m));
gbuf_cont(m) = 0;
((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
- ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTO;
+ ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTOTYPE;
gbuf_set_type(m, MSG_IOCNAK);
atalk_putnext(gref, m);
} else
case ATPROTO_ATP:
case ATPROTO_ASP:
+#ifdef AURP_SUPPORT
case ATPROTO_AURP:
+#endif
case ATPROTO_ADSP:
break;
default:
return -1;
}
gref->proto = proto;
- gref->pid = ((struct proc *)proc)->p_pid;
+ gref->pid = proc_pid((struct proc *)proc);
/* open the specified protocol */
switch (gref->proto) {
int rc = -1;
gref_t *gref;
- if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
+ if ((*err = atalk_getref(0, fd, &gref, proc, 1)) == 0) {
switch (gref->proto) {
case ATPROTO_ASP:
- rc = ASPgetmsg(gref, ctlptr, datptr, flags, err);
+ rc = ASPgetmsg(gref, ctlptr, datptr, NULL, flags, err);
break;
case ATPROTO_AURP:
#ifdef AURP_SUPPORT
*err = EPROTONOSUPPORT;
break;
}
+ file_drop(fd);
}
/* kprintf("_ATgetmsg: return=%d\n", *err);*/
int rc = -1;
gref_t *gref;
- if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
+ if ((*err = atalk_getref(0, fd, &gref, proc, 1)) == 0) {
switch (gref->proto) {
case ATPROTO_ASP:
- rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break;
+ rc = ASPputmsg(gref, ctlptr, datptr, NULL, flags, err); break;
default:
*err = EPROTONOSUPPORT; break;
}
+ file_drop(fd);
}
/* kprintf("_ATputmsg: return=%d\n", *err); */
return rc;
}
-int _ATclose(fp, proc)
- struct file *fp;
+int _ATclose(fg, proc)
+ struct fileglob *fg;
struct proc *proc;
{
int err;
gref_t *gref;
-
-
- if ((err = atalk_closeref(fp, &gref)) == 0) {
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+ if ((err = atalk_closeref(fg, &gref)) == 0) {
+ atalk_lock();
(void)gref_close(gref);
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ atalk_unlock();
}
return err;
}
-int _ATrw(fp, rw, uio, ext)
+int _ATrw(fp, rw, uio, p)
void *fp;
enum uio_rw rw;
struct uio *uio;
- int ext;
+ struct proc *p;
{
- int s, err, len, clen = 0, res;
+ int err, len, clen = 0, res;
gref_t *gref;
gbuf_t *m, *mhead, *mprev;
- if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
+ /* no need to get/drop iocount as the fp already has one */
+ if ((err = atalk_getref_locked(fp, 0, &gref, p, 1)) != 0)
return err;
- if ((len = uio->uio_resid) == 0)
+ // LP64todo - fix this!
+ if ((len = uio_resid(uio)) == 0)
return 0;
- ATDISABLE(s, gref->lock);
if (rw == UIO_READ) {
KERNEL_DEBUG(DBG_ADSP_ATRW, 0, gref, len, gref->rdhead, 0);
while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) {
gref->sevents |= POLLMSG;
- err = tsleep(&gref->event, PSOCK | PCATCH, "AT read", 0);
+ err = msleep(&gref->event, atalk_mutex, PSOCK | PCATCH, "AT read", 0);
gref->sevents &= ~POLLMSG;
- if (err != 0) {
- ATENABLE(s, gref->lock);
+ if (err != 0)
return err;
- }
KERNEL_DEBUG(DBG_ADSP_ATRW, 1, gref, gref->rdhead, mhead, gbuf_next(mhead));
}
- if (gref->errno) {
- ATENABLE(s, gref->lock);
+ if (gref->errno)
return EPIPE;
- }
if ((gref->rdhead = gbuf_next(mhead)) == 0)
gref->rdtail = 0;
KERNEL_DEBUG(DBG_ADSP_ATRW, 2, gref, gref->rdhead, mhead, gbuf_next(mhead));
- ATENABLE(s, gref->lock);
//##### LD TEST 08/05
// simple_lock(&gref->lock);
gbuf_cont(mprev) = 0;
else
mhead = 0;
- ATDISABLE(s, gref->lock);
if (gref->rdhead == 0)
gref->rdtail = m;
gbuf_next(m) = gref->rdhead;
gref->rdhead = m;
- ATENABLE(s, gref->lock);
}
if (mhead)
gbuf_freem(mhead);
while (!(*gref->writeable)(gref)) {
/* flow control on, wait to be enabled to write */
gref->sevents |= POLLSYNC;
- err = tsleep(&gref->event, PSOCK | PCATCH, "AT write", 0);
+ err = msleep(&gref->event, atalk_mutex, PSOCK | PCATCH, "AT write", 0);
gref->sevents &= ~POLLSYNC;
- if (err != 0) {
- ATENABLE(s, gref->lock);
+ if (err != 0)
return err;
- }
}
}
- ATENABLE(s, gref->lock);
/* allocate a buffer to copy in the write data */
if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0)
return 0;
} /* _ATrw */
-int _ATread(fp, uio, cred)
- void *fp;
+int _ATread(fp, uio, cred, flags, p)
+ struct fileproc *fp;
struct uio *uio;
void *cred;
+ int flags;
+ struct proc *p;
{
int stat;
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
- stat = _ATrw(fp, UIO_READ, uio, 0);
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ atalk_lock();
+ stat = _ATrw(fp, UIO_READ, uio, p);
+ atalk_unlock();
return stat;
}
-int _ATwrite(fp, uio, cred)
- void *fp;
+int _ATwrite(fp, uio, cred, flags, p)
+ struct fileproc *fp;
struct uio *uio;
void *cred;
+ int flags;
+ struct proc *p;
{
int stat;
-
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
- stat = _ATrw(fp, UIO_WRITE, uio, 0);
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ atalk_lock();
+ stat = _ATrw(fp, UIO_WRITE, uio, p);
+ atalk_unlock();
return stat;
}
/* Most of the processing from _ATioctl, so that it can be called
from the new ioctl code */
-int at_ioctl(gref, cmd, arg)
- gref_t *gref;
- register caddr_t arg;
+/* bms: update to be callable from kernel */
+int at_ioctl(gref_t *gref, u_long cmd, caddr_t arg, int fromKernel)
{
- int s, err = 0, len;
- gbuf_t *m, *mdata;
- ioc_t *ioc;
- ioccmd_t ioccmd;
-
- /* error if not for us */
- if ((cmd & 0xffff) != 0xff99)
- return EOPNOTSUPP;
-
- /* copy in ioc command info */
-/*
- kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n",
- ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len,
- gref->lock, gref->event);
-*/
- if ((err = copyin((caddr_t)arg,
- (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) {
+ int err = 0, len;
+ u_int size;
+ gbuf_t *m, *mdata;
+ ioc_t *ioc;
+ user_addr_t user_arg;
+ user_ioccmd_t user_ioccmd;
+ boolean_t is64bit;
+
+ /* error if not for us */
+ if ((cmd & 0xffff) != 0xff99)
+ return EOPNOTSUPP;
+
+ size = IOCPARM_LEN(cmd);
+ if (size != sizeof(user_addr_t))
+ return EINVAL;
+
+ user_arg = *((user_addr_t *)arg);
+
+ /* copy in ioc command info */
+ is64bit = proc_is64bit(current_proc());
+ if (fromKernel) {
+ ioccmd_t tmp;
+ bcopy (CAST_DOWN(caddr_t, user_arg), &tmp, sizeof (tmp));
+ ioccmd_t_32_to_64(&tmp, &user_ioccmd);
+ }
+ else {
+ if (is64bit) {
+ err = copyin(user_arg, (caddr_t)&user_ioccmd, sizeof(user_ioccmd));
+ }
+ else {
+ ioccmd_t tmp;
+ err = copyin(user_arg, (caddr_t)&tmp, sizeof(tmp));
+ ioccmd_t_32_to_64(&tmp, &user_ioccmd);
+ }
+ if (err != 0) {
#ifdef APPLETALK_DEBUG
- kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err,
- (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t));
+ kprintf("at_ioctl: err = %d, copyin(%llx, %x, %d)\n", err,
+ user_arg, (caddr_t)&user_ioccmd, sizeof(user_ioccmd));
#endif
- return err;
- }
-
- /* allocate a buffer to create an ioc command */
- if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
- return ENOBUFS;
- gbuf_wset(m,sizeof(ioc_t));
- gbuf_set_type(m, MSG_IOCTL);
-
- /* create the ioc command */
- if (ioccmd.ic_len) {
- if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) {
- gbuf_freem(m);
+ return err;
+ }
+ }
+
+ /* allocate a buffer to create an ioc command
+ first mbuf contains ioc command */
+ if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
+ return ENOBUFS;
+ gbuf_wset(m, sizeof(ioc_t)); /* mbuf->m_len */
+ gbuf_set_type(m, MSG_IOCTL); /* mbuf->m_type */
+
+ /* create the ioc command
+ second mbuf contains the actual ASP command */
+ if (user_ioccmd.ic_len) {
+ if ((gbuf_cont(m) = gbuf_alloc(user_ioccmd.ic_len, PRI_HI)) == 0) {
+ gbuf_freem(m);
#ifdef APPLETALK_DEBUG
kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS);
#endif
- return ENOBUFS;
- }
- gbuf_wset(gbuf_cont(m),ioccmd.ic_len);
- if ((err = copyin((caddr_t)ioccmd.ic_dp,
- (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) {
- gbuf_freem(m);
- return err;
- }
- }
- ioc = (ioc_t *)gbuf_rptr(m);
- ioc->ioc_cmd = ioccmd.ic_cmd;
- ioc->ioc_count = ioccmd.ic_len;
- ioc->ioc_error = 0;
- ioc->ioc_rval = 0;
-
- /* send the ioc command to the appropriate recipient */
+ return ENOBUFS;
+ }
+ gbuf_wset(gbuf_cont(m), user_ioccmd.ic_len); /* mbuf->m_len */
+ if (fromKernel)
+ bcopy (CAST_DOWN(caddr_t, user_ioccmd.ic_dp), gbuf_rptr(gbuf_cont(m)), user_ioccmd.ic_len);
+ else {
+ if ((err = copyin(user_ioccmd.ic_dp, (caddr_t)gbuf_rptr(gbuf_cont(m)), user_ioccmd.ic_len)) != 0) {
+ gbuf_freem(m);
+ return err;
+ }
+ }
+ }
+ ioc = (ioc_t *) gbuf_rptr(m);
+ ioc->ioc_cmd = user_ioccmd.ic_cmd;
+ ioc->ioc_count = user_ioccmd.ic_len;
+ ioc->ioc_error = 0;
+ ioc->ioc_rval = 0;
+
+ /* send the ioc command to the appropriate recipient */
gref_wput(gref, m);
- /* wait for the ioc ack */
- ATDISABLE(s, gref->lock);
- while ((m = gref->ichead) == 0) {
- gref->sevents |= POLLPRI;
+ /* wait for the ioc ack */
+ while ((m = gref->ichead) == 0) {
+ gref->sevents |= POLLPRI;
#ifdef APPLETALK_DEBUG
kprintf("sleep gref = 0x%x\n", (unsigned)gref);
#endif
- err = tsleep(&gref->iocevent, PSOCK | PCATCH, "AT ioctl", 0);
+ err = msleep(&gref->iocevent, atalk_mutex, PSOCK | PCATCH, "AT ioctl", 0);
gref->sevents &= ~POLLPRI;
if (err != 0) {
- ATENABLE(s, gref->lock);
#ifdef APPLETALK_DEBUG
kprintf("at_ioctl: EINTR\n");
#endif
gref->ichead = gbuf_next(m);
- ATENABLE(s, gref->lock);
#ifdef APPLETALK_DEBUG
kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n",
(unsigned)gref);
#endif
- /* process the ioc response */
- ioc = (ioc_t *)gbuf_rptr(m);
- if ((err = ioc->ioc_error) == 0) {
- ioccmd.ic_timout = ioc->ioc_rval;
- ioccmd.ic_len = 0;
- mdata = gbuf_cont(m);
- if (mdata && ioccmd.ic_dp) {
- ioccmd.ic_len = gbuf_msgsize(mdata);
- for (len=0; mdata; mdata=gbuf_cont(mdata)) {
- if ((err = copyout((caddr_t)gbuf_rptr(mdata),
- (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) {
+
+ /* process the ioc response */
+ ioc = (ioc_t *) gbuf_rptr(m);
+ if ((err = ioc->ioc_error) == 0) {
+ user_ioccmd.ic_timout = ioc->ioc_rval;
+ user_ioccmd.ic_len = 0;
+ mdata = gbuf_cont(m);
+ if (mdata && user_ioccmd.ic_dp) {
+ user_ioccmd.ic_len = gbuf_msgsize(mdata);
+ for (len = 0; mdata; mdata = gbuf_cont(mdata)) {
+ if (fromKernel)
+ bcopy (gbuf_rptr(mdata), CAST_DOWN(caddr_t, (user_ioccmd.ic_dp + len)), gbuf_len(mdata));
+ else {
+ if ((err = copyout((caddr_t)gbuf_rptr(mdata), (user_ioccmd.ic_dp + len), gbuf_len(mdata))) < 0) {
#ifdef APPLETALK_DEBUG
- kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
- len, err, (caddr_t)gbuf_rptr(mdata),
- (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata));
+ kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
+ len, err, (caddr_t)gbuf_rptr(mdata), (caddr_t)&user_ioccmd.ic_dp[len], gbuf_len(mdata));
#endif
- goto l_done;
+ goto l_done;
+ }
+ }
+ len += gbuf_len(mdata);
+ }
+ }
+
+ if (fromKernel) {
+ ioccmd_t tmp;
+ ioccmd_t_64_to_32(&user_ioccmd, &tmp);
+ bcopy (&tmp, CAST_DOWN(caddr_t, user_arg), sizeof(tmp));
+ }
+ else {
+ if (is64bit) {
+ err = copyout((caddr_t)&user_ioccmd, user_arg, sizeof(user_ioccmd));
}
- len += gbuf_len(mdata);
- }
- }
- if ((err = copyout((caddr_t)&ioccmd,
- (caddr_t)arg, sizeof(ioccmd_t))) != 0) {
-#ifdef APPLETALK_DEBUG
- kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n",
- err, &ioccmd, arg, sizeof(ioccmd_t));
-#endif
- goto l_done;
- }
- }
+ else {
+ ioccmd_t tmp;
+ ioccmd_t_64_to_32(&user_ioccmd, &tmp);
+ err = copyout((caddr_t)&tmp, user_arg, sizeof(tmp));
+ }
+ if (err != 0) {
+ goto l_done;
+ }
+ }
+ }
l_done:
gbuf_freem(m);
int err;
gref_t *gref;
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
- if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) {
+ atalk_lock();
+ /* No need to get a reference on fp as it already has one */
+ if ((err = atalk_getref_locked(fp, 0, &gref, 0, 0)) != 0) {
#ifdef APPLETALK_DEBUG
kprintf("_ATioctl: atalk_getref err = %d\n", err);
#endif
}
else
- err = at_ioctl(gref, cmd, arg);
+ err = at_ioctl(gref, cmd, arg, 0);
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ atalk_unlock();
return err;
}
-int _ATselect(fp, which, proc)
- struct file *fp;
+int _ATselect(fp, which, wql, proc)
+ struct fileproc *fp;
int which;
+ void * wql;
struct proc *proc;
{
- int s, err, rc = 0;
+ int err, rc = 0;
gref_t *gref;
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
- err = atalk_getref(fp, 0, &gref, 0);
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ /* Radar 4128949: Drop the proc_fd lock here to avoid lock inversion issues with the other AT calls
+ * select() is already holding a reference on the fd, so it won't go away during the time it is unlocked.
+ */
+ proc_fdunlock(proc);
+
+ atalk_lock();
+ /* no need to drop the iocount as select covers that */
+ err = atalk_getref_locked(fp, 0, &gref, 0, 0);
+ atalk_unlock();
+ /* Safe to re-grab the proc_fdlock at that point */
+ proc_fdlock(proc);
if (err != 0)
rc = 1;
else {
- ATDISABLE(s, gref->lock);
if (which == FREAD) {
if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
rc = 1;
else {
gref->sevents |= POLLIN;
- selrecord(proc, &gref->si);
+ selrecord(proc, &gref->si, wql);
}
}
else if (which == POLLOUT) {
rc = 1;
else {
gref->sevents |= POLLOUT;
- selrecord(proc, &gref->si);
+ selrecord(proc, &gref->si, wql);
}
} else
rc = 1;
}
- ATENABLE(s, gref->lock);
}
return rc;
}
+int _ATkqfilter(fp, kn, p)
+ struct fileproc *fp;
+ struct knote *kn;
+ struct proc *p;
+{
+ return (EOPNOTSUPP);
+}
+
void atalk_putnext(gref, m)
gref_t *gref;
gbuf_t *m;
{
- int s;
- ATDISABLE(s, gref->lock);
/* *** potential leak? *** */
gbuf_next(m) = 0;
#ifdef APPLETALK_DEBUG
kprintf("wakeup gref = 0x%x\n", (unsigned)gref);
#endif
- thread_wakeup(&gref->iocevent);
+ wakeup(&gref->iocevent);
}
}
break;
gref->rdhead = m;
if (gref->sevents & POLLMSG) {
gref->sevents &= ~POLLMSG;
- thread_wakeup(&gref->event);
+ wakeup(&gref->event);
}
if (gref->sevents & POLLIN) {
gref->sevents &= ~POLLIN;
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
selwakeup(&gref->si);
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
}
gref->rdtail = m;
}
} /* switch gbuf_type(m) */
- ATENABLE(s, gref->lock);
} /* atalk_putnext */
void atalk_enablew(gref)
gref_t *gref;
{
if (gref->sevents & POLLSYNC)
- thread_wakeup(&gref->event);
+ wakeup(&gref->event);
}
void atalk_flush(gref)
gref_t *gref;
{
- int s;
- ATDISABLE(s, gref->lock);
if (gref->rdhead) {
gbuf_freel(gref->rdhead);
gref->rdhead = 0;
gbuf_freel(gref->ichead);
gref->ichead = 0;
}
- ATENABLE(s, gref->lock);
}
/*
register gref_t *gref;
int errno;
{
- int s;
- ATDISABLE(s, gref->lock);
if (gref->atpcb_socket) {
/* For DDP --
/* blocked read */
if (gref->sevents & POLLMSG) {
gref->sevents &= ~POLLMSG;
- thread_wakeup(&gref->event);
+ wakeup(&gref->event);
}
/* select */
if (gref->sevents & POLLIN) {
gref->sevents &= ~POLLIN;
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
selwakeup(&gref->si);
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
}
}
}
- ATENABLE(s, gref->lock);
} /* atalk_notify */
void atalk_notify_sel(gref)
gref_t *gref;
{
- int s;
- ATDISABLE(s, gref->lock);
if (gref->sevents & POLLIN) {
gref->sevents &= ~POLLIN;
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
selwakeup(&gref->si);
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
}
- ATENABLE(s, gref->lock);
}
int atalk_peek(gref, event)
gref_t *gref;
unsigned char *event;
{
- int s, rc;
+ int rc;
- ATDISABLE(s, gref->lock);
if (gref->rdhead) {
*event = *gbuf_rptr(gref->rdhead);
rc = 0;
} else
rc = -1;
- ATENABLE(s, gref->lock);
return rc;
}
gref_t **grefp;
{
extern gbuf_t *atp_resource_m;
- int i, s;
+ int i;
gbuf_t *m;
gref_t *gref, *gref_array;
*grefp = (gref_t *)NULL;
- ATDISABLE(s, refall_lock);
if (gref_free_list == 0) {
- ATENABLE(s, refall_lock);
#ifdef APPLETALK_DEBUG
kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t));
#endif
gref_array = (gref_t *)gbuf_rptr(m);
for (i=0; i < GREF_PER_BLK-1; i++)
gref_array[i].atpcb_next = (gref_t *)&gref_array[i+1];
- ATDISABLE(s, refall_lock);
gbuf_cont(m) = atp_resource_m;
atp_resource_m = m;
gref_array[i].atpcb_next = gref_free_list;
gref = gref_free_list;
gref_free_list = gref->atpcb_next;
- ATENABLE(s, refall_lock);
- ATLOCKINIT(gref->lock);
-//### LD Test 08/05/98
-// simple_lock_init(&gref->lock);
ATEVENTINIT(gref->event);
ATEVENTINIT(gref->iocevent);
return 0;
} /* gref_alloc */
-static int gref_close(gref)
- gref_t *gref;
+/* bms: make gref_close callable from kernel */
+int gref_close(gref_t *gref)
{
- int s, rc;
+ int rc;
switch (gref->proto) {
selthreadclear(&gref->si);
/* from original gref_free() */
- ATDISABLE(s, refall_lock);
bzero((char *)gref, sizeof(gref_t));
gref->atpcb_next = gref_free_list;
gref_free_list = gref;
- ATENABLE(s, refall_lock);
}
return rc;
struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait)
caddr_t extbuf;
- int (*extfree)();
- int extsize;
- int extarg;
+ void (*extfree)(caddr_t , u_int, caddr_t);
+ u_int extsize;
+ caddr_t extarg;
int wait;
{
struct mbuf *m;
m->m_ext.ext_size = extsize;
m->m_ext.ext_arg = extarg;
m->m_ext.ext_refs.forward =
- m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
+ m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
m->m_data = extbuf;
m->m_flags |= M_EXT;
return (m);
}
+
+
+/*
+ temp fix for bug 2731148 - until this code is re-written to use standard clusters
+ Deletes any free clusters on the free list.
+*/
+void atp_delete_free_clusters()
+{
+ caddr_t cluster;
+ caddr_t cluster_list;
+
+
+ /* check for free clusters on the free_cluster_list to be deleted */
+ MBUF_LOCK(); /* lock used by mbuf routines */
+
+ untimeout(&atp_delete_free_clusters, NULL);
+ atp_free_cluster_timeout_set = 0;
+
+ cluster_list = atp_free_cluster_list;
+ atp_free_cluster_list = 0;
+
+ MBUF_UNLOCK();
+
+ while (cluster = cluster_list)
+ {
+ cluster_list = *((caddr_t*)cluster);
+ FREE(cluster, M_MCLUST);
+ }
+
+}
+
+
/*
Used as the "free" routine for over-size clusters allocated using
- m_lgbuf_alloc().
+ m_lgbuf_alloc(). Called by m_free while under MBUF_LOCK.
*/
void m_lgbuf_free(buf, size, arg)
- void *buf;
- int size, arg; /* not needed, but they're in m_free() */
+ caddr_t buf;
+ u_int size;
+ caddr_t arg; /* not needed, but they're in m_free() */
{
- FREE(buf, M_MCLUST);
+ /* FREE(buf, M_MCLUST); - can't free here - called from m_free while under lock */
+
+ /* move to free_cluster_list to be deleted later */
+ caddr_t cluster = (caddr_t)buf;
+
+ /* don't need a lock because this is only called called from m_free which */
+ /* is under MBUF_LOCK */
+ *((caddr_t*)cluster) = atp_free_cluster_list;
+ atp_free_cluster_list = cluster;
+
+ if (atp_free_cluster_timeout_set == 0)
+ {
+ atp_free_cluster_timeout_set = 1;
+ timeout(&atp_delete_free_clusters, NULL, (1 * HZ));
+ }
}
/*
{
struct mbuf *m;
+ if (atp_free_cluster_list)
+ atp_delete_free_clusters(); /* delete any free clusters on the free list */
+
/* If size is too large, allocate a cluster, otherwise, use the
standard mbuf allocation routines.*/
if (size > MCLBYTES) {
if (NULL ==
(m = m_clattach(buf, m_lgbuf_free, size, 0,
(wait)? M_WAIT: M_DONTWAIT))) {
- m_lgbuf_free(buf);
+ m_lgbuf_free(buf, 0, 0);
return(NULL);
}
} else {
atalk_putnext(gref, m);
}
+
+static void ioccmd_t_32_to_64( ioccmd_t *from_p, user_ioccmd_t *to_p )
+{
+ to_p->ic_cmd = from_p->ic_cmd;
+ to_p->ic_timout = from_p->ic_timout;
+ to_p->ic_len = from_p->ic_len;
+ to_p->ic_dp = CAST_USER_ADDR_T(from_p->ic_dp);
+}
+
+
+static void ioccmd_t_64_to_32( user_ioccmd_t *from_p, ioccmd_t *to_p )
+{
+ to_p->ic_cmd = from_p->ic_cmd;
+ to_p->ic_timout = from_p->ic_timout;
+ to_p->ic_len = from_p->ic_len;
+ to_p->ic_dp = CAST_DOWN(caddr_t, from_p->ic_dp);
+}