*
* @APPLE_LICENSE_HEADER_START@
*
- * 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. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * 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.
*
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
struct zone *unp_zone;
static unp_gen_t unp_gencnt;
static u_int unp_count;
-static lck_mtx_t *unp_mutex;
+
+static lck_attr_t *unp_mtx_attr;
+static lck_grp_t *unp_mtx_grp;
+static lck_grp_attr_t *unp_mtx_grp_attr;
+static lck_rw_t *unp_list_mtx;
extern lck_mtx_t * uipc_lock;
static struct unp_head unp_shead, unp_dhead;
if (unp == NULL)
return (ENOBUFS);
bzero(unp, sizeof *unp);
- lck_mtx_lock(unp_mutex);
+ lck_rw_lock_exclusive(unp_list_mtx);
LIST_INIT(&unp->unp_refs);
unp->unp_socket = so;
unp->unp_gencnt = ++unp_gencnt;
LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
: &unp_shead, unp, unp_link);
so->so_pcb = (caddr_t)unp;
- lck_mtx_unlock(unp_mutex);
+ lck_rw_done(unp_list_mtx);
return (0);
}
static void
unp_detach(struct unpcb *unp)
{
- lck_mtx_assert(unp_mutex, LCK_MTX_ASSERT_OWNED);
+ lck_rw_lock_exclusive(unp_list_mtx);
LIST_REMOVE(unp, unp_link);
unp->unp_gencnt = ++unp_gencnt;
+ lck_rw_done(unp_list_mtx);
--unp_count;
if (unp->unp_vnode) {
struct vnode *tvp = unp->unp_vnode;
if (error)
goto bad;
so2 = vp->v_socket;
- if (so2 == 0) {
+ if (so2 == 0 || so2->so_pcb == NULL ) {
error = ECONNREFUSED;
goto bad;
}
}
error = unp_connect2(so, so2);
bad:
- if (so2 != NULL)
- so2->so_usecount--; /* release count on socket */
+
+ if (so2 != NULL)
+ so2->so_usecount--; /* release count on socket */
+
vnode_put(vp);
return (error);
}
if (unp2 == 0)
return;
- lck_mtx_assert(unp_mutex, LCK_MTX_ASSERT_OWNED);
unp->unp_conn = 0;
switch (unp->unp_socket->so_type) {
case SOCK_DGRAM:
+ lck_rw_lock_exclusive(unp_list_mtx);
LIST_REMOVE(unp, unp_reflink);
+ lck_rw_done(unp_list_mtx);
unp->unp_socket->so_state &= ~SS_ISCONNECTED;
break;
struct xunpgen xug;
struct unp_head *head;
- lck_mtx_lock(unp_mutex);
+ lck_rw_lock_shared(unp_list_mtx);
head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
/*
n = unp_count;
req->oldidx = 2 * (sizeof xug)
+ (n + n/8) * sizeof(struct xunpcb);
- lck_mtx_unlock(unp_mutex);
+ lck_rw_done(unp_list_mtx);
return 0;
}
if (req->newptr != USER_ADDR_NULL) {
- lck_mtx_unlock(unp_mutex);
+ lck_rw_done(unp_list_mtx);
return EPERM;
}
xug.xug_sogen = so_gencnt;
error = SYSCTL_OUT(req, &xug, sizeof xug);
if (error) {
- lck_mtx_unlock(unp_mutex);
+ lck_rw_done(unp_list_mtx);
return error;
}
* We are done if there is no pcb
*/
if (n == 0) {
- lck_mtx_unlock(unp_mutex);
+ lck_rw_done(unp_list_mtx);
return 0;
}
MALLOC(unp_list, struct unpcb **, n * sizeof *unp_list, M_TEMP, M_WAITOK);
if (unp_list == 0) {
- lck_mtx_unlock(unp_mutex);
+ lck_rw_done(unp_list_mtx);
return ENOMEM;
}
error = SYSCTL_OUT(req, &xug, sizeof xug);
}
FREE(unp_list, M_TEMP);
- lck_mtx_unlock(unp_mutex);
+ lck_rw_done(unp_list_mtx);
return error;
}
LIST_INIT(&unp_dhead);
LIST_INIT(&unp_shead);
- unp_mutex = localdomain.dom_mtx;
+ /*
+ * allocate lock group attribute and group for udp pcb mutexes
+ */
+ unp_mtx_grp_attr = lck_grp_attr_alloc_init();
+
+ unp_mtx_grp = lck_grp_alloc_init("unp_list", unp_mtx_grp_attr);
+
+ unp_mtx_attr = lck_attr_alloc_init();
+
+ if ((unp_list_mtx = lck_rw_alloc_init(unp_mtx_grp, unp_mtx_attr)) == NULL)
+ return; /* pretty much dead if this fails... */
+
}
#ifndef MIN