2 * Copyright (c) 2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <kern/debug.h>
30 #include <kern/locks.h>
31 #include <kern/thread.h>
32 #include <kern/thread_call.h>
33 #include <net/nwk_wq.h>
34 #include <sys/proc_internal.h>
35 #include <sys/systm.h>
36 #include <sys/mcache.h>
38 MALLOC_DEFINE(M_NWKWQ
, "nwkwq", "Network work-queue");
40 static TAILQ_HEAD(, nwk_wq_entry
) nwk_wq_head
;
41 decl_lck_mtx_data(static, nwk_wq_lock
);
43 /* Lock group and attributes */
44 static lck_grp_attr_t
*nwk_wq_lock_grp_attributes
= NULL
;
45 static lck_grp_t
*nwk_wq_lock_group
= NULL
;
47 /* Lock and lock attributes */
48 static lck_attr_t
*nwk_wq_lock_attributes
= NULL
;
49 decl_lck_mtx_data(static, nwk_wq_lock
);
51 /* Wait channel for Network work queue */
52 static void *nwk_wq_waitch
= NULL
;
53 static void nwk_wq_thread_func(void *, wait_result_t
);
55 static int nwk_wq_thread_cont(int err
);
56 static void nwk_wq_thread_func(void *v
, wait_result_t w
);
61 thread_t nwk_wq_thread
= THREAD_NULL
;
63 TAILQ_INIT(&nwk_wq_head
);
64 nwk_wq_lock_grp_attributes
= lck_grp_attr_alloc_init();
65 nwk_wq_lock_group
= lck_grp_alloc_init("Network work queue lock",
66 nwk_wq_lock_grp_attributes
);
68 nwk_wq_lock_attributes
= lck_attr_alloc_init();
69 lck_mtx_init(&nwk_wq_lock
, nwk_wq_lock_group
, nwk_wq_lock_attributes
);
70 if (kernel_thread_start(nwk_wq_thread_func
,
71 NULL
, &nwk_wq_thread
) != KERN_SUCCESS
) {
72 panic_plain("%s: couldn't create network work queue thread", __func__
);
75 thread_deallocate(nwk_wq_thread
);
79 nwk_wq_thread_cont(int err
)
81 TAILQ_HEAD(, nwk_wq_entry
) temp_nwk_wq_head
;
82 struct nwk_wq_entry
*nwk_item
;
83 struct nwk_wq_entry
*nwk_item_next
;
89 TAILQ_INIT(&temp_nwk_wq_head
);
91 LCK_MTX_ASSERT(&nwk_wq_lock
, LCK_MTX_ASSERT_OWNED
);
92 while (TAILQ_FIRST(&nwk_wq_head
) == NULL
) {
93 (void) msleep0(&nwk_wq_waitch
, &nwk_wq_lock
,
94 (PZERO
- 1), "nwk_wq_thread_cont", 0,
99 TAILQ_SWAP(&temp_nwk_wq_head
, &nwk_wq_head
, nwk_wq_entry
, nwk_wq_link
);
100 VERIFY(TAILQ_EMPTY(&nwk_wq_head
));
101 lck_mtx_unlock(&nwk_wq_lock
);
103 VERIFY(TAILQ_FIRST(&temp_nwk_wq_head
) != NULL
);
104 TAILQ_FOREACH_SAFE(nwk_item
, &temp_nwk_wq_head
, nwk_wq_link
, nwk_item_next
) {
105 nwk_item
->func(nwk_item
->arg
);
106 if (nwk_item
->is_arg_managed
== FALSE
) {
107 FREE(nwk_item
->arg
, M_NWKWQ
);
109 FREE(nwk_item
, M_NWKWQ
);
111 lck_mtx_lock(&nwk_wq_lock
);
117 nwk_wq_thread_func(void *v
, wait_result_t w
)
120 lck_mtx_lock(&nwk_wq_lock
);
121 (void) msleep0(&nwk_wq_waitch
, &nwk_wq_lock
,
122 (PZERO
- 1), "nwk_wq_thread_func", 0, nwk_wq_thread_cont
);
124 * msleep0() shouldn't have returned as PCATCH was not set;
125 * therefore assert in this case.
127 lck_mtx_unlock(&nwk_wq_lock
);
132 nwk_wq_enqueue(struct nwk_wq_entry
*nwk_item
)
134 lck_mtx_lock(&nwk_wq_lock
);
135 TAILQ_INSERT_TAIL(&nwk_wq_head
, nwk_item
, nwk_wq_link
);
136 lck_mtx_unlock(&nwk_wq_lock
);
137 wakeup((caddr_t
)&nwk_wq_waitch
);