root / lab4 / .minix-src / include / sys / lwp.h @ 13
History | View | Annotate | Download (17.3 KB)
1 | 13 | up20180614 | /* $NetBSD: lwp.h,v 1.170 2015/03/31 01:10:02 matt Exp $ */
|
---|---|---|---|
2 | |||
3 | /*-
|
||
4 | * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
|
||
5 | * The NetBSD Foundation, Inc.
|
||
6 | * All rights reserved.
|
||
7 | *
|
||
8 | * This code is derived from software contributed to The NetBSD Foundation
|
||
9 | * by Nathan J. Williams and Andrew Doran.
|
||
10 | *
|
||
11 | * Redistribution and use in source and binary forms, with or without
|
||
12 | * modification, are permitted provided that the following conditions
|
||
13 | * are met:
|
||
14 | * 1. Redistributions of source code must retain the above copyright
|
||
15 | * notice, this list of conditions and the following disclaimer.
|
||
16 | * 2. Redistributions in binary form must reproduce the above copyright
|
||
17 | * notice, this list of conditions and the following disclaimer in the
|
||
18 | * documentation and/or other materials provided with the distribution.
|
||
19 | *
|
||
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
30 | * POSSIBILITY OF SUCH DAMAGE.
|
||
31 | */
|
||
32 | |||
33 | #ifndef _SYS_LWP_H_
|
||
34 | #define _SYS_LWP_H_
|
||
35 | |||
36 | #if defined(_KERNEL) || defined(_KMEMUSER)
|
||
37 | |||
38 | #include <sys/param.h> |
||
39 | #include <sys/time.h> |
||
40 | #include <sys/queue.h> |
||
41 | #include <sys/callout.h> |
||
42 | #include <sys/kcpuset.h> |
||
43 | #include <sys/mutex.h> |
||
44 | #include <sys/condvar.h> |
||
45 | #include <sys/signalvar.h> |
||
46 | #include <sys/sched.h> |
||
47 | #include <sys/specificdata.h> |
||
48 | #include <sys/syncobj.h> |
||
49 | #include <sys/resource.h> |
||
50 | |||
51 | #if defined(_KERNEL)
|
||
52 | struct lwp;
|
||
53 | /* forward declare this for <machine/cpu.h> so it can get l_cpu. */
|
||
54 | static inline struct cpu_info *lwp_getcpu(struct lwp *); |
||
55 | #include <machine/cpu.h> /* curcpu() and cpu_info */ |
||
56 | #endif
|
||
57 | |||
58 | #include <machine/proc.h> /* Machine-dependent proc substruct. */ |
||
59 | |||
60 | /*
|
||
61 | * Lightweight process. Field markings and the corresponding locks:
|
||
62 | *
|
||
63 | * a: proc_lock
|
||
64 | * c: condition variable interlock, passed to cv_wait()
|
||
65 | * l: *l_mutex
|
||
66 | * p: l_proc->p_lock
|
||
67 | * s: spc_mutex, which may or may not be referenced by l_mutex
|
||
68 | * S: l_selcluster->sc_lock
|
||
69 | * (: unlocked, stable
|
||
70 | * !: unlocked, may only be reliably accessed by the LWP itself
|
||
71 | *
|
||
72 | * Fields are clustered together by usage (to increase the likelyhood
|
||
73 | * of cache hits) and by size (to reduce dead space in the structure).
|
||
74 | */
|
||
75 | |||
76 | #include <sys/pcu.h> |
||
77 | |||
78 | struct lockdebug;
|
||
79 | struct sysent;
|
||
80 | |||
81 | struct lwp {
|
||
82 | /* Scheduling and overall state. */
|
||
83 | TAILQ_ENTRY(lwp) l_runq; /* s: run queue */
|
||
84 | union {
|
||
85 | void * info; /* s: scheduler-specific structure */ |
||
86 | u_int timeslice; /* l: time-quantum for SCHED_M2 */
|
||
87 | } l_sched; |
||
88 | struct cpu_info *volatile l_cpu;/* s: CPU we're on if LSONPROC */ |
||
89 | kmutex_t * volatile l_mutex; /* l: ptr to mutex on sched state */ |
||
90 | int l_ctxswtch; /* l: performing a context switch */ |
||
91 | void *l_addr; /* l: PCB address; use lwp_getpcb() */ |
||
92 | struct mdlwp l_md; /* l: machine-dependent fields. */ |
||
93 | int l_flag; /* l: misc flag values */ |
||
94 | int l_stat; /* l: overall LWP status */ |
||
95 | struct bintime l_rtime; /* l: real time */ |
||
96 | struct bintime l_stime; /* l: start time (while ONPROC) */ |
||
97 | u_int l_swtime; /* l: time swapped in or out */
|
||
98 | u_int l_rticks; /* l: Saved start time of run */
|
||
99 | u_int l_rticksum; /* l: Sum of ticks spent running */
|
||
100 | u_int l_slpticks; /* l: Saved start time of sleep */
|
||
101 | u_int l_slpticksum; /* l: Sum of ticks spent sleeping */
|
||
102 | int l_biglocks; /* l: biglock count before sleep */ |
||
103 | int l_class; /* l: scheduling class */ |
||
104 | int l_kpriority; /* !: has kernel priority boost */ |
||
105 | pri_t l_kpribase; /* !: kernel priority base level */
|
||
106 | pri_t l_priority; /* l: scheduler priority */
|
||
107 | pri_t l_inheritedprio;/* l: inherited priority */
|
||
108 | SLIST_HEAD(, turnstile) l_pi_lenders; /* l: ts lending us priority */
|
||
109 | uint64_t l_ncsw; /* l: total context switches */
|
||
110 | uint64_t l_nivcsw; /* l: involuntary context switches */
|
||
111 | u_int l_cpticks; /* (: Ticks of CPU time */
|
||
112 | fixpt_t l_pctcpu; /* p: %cpu during l_swtime */
|
||
113 | fixpt_t l_estcpu; /* l: cpu time for SCHED_4BSD */
|
||
114 | psetid_t l_psid; /* l: assigned processor-set ID */
|
||
115 | struct cpu_info *l_target_cpu; /* l: target CPU to migrate */ |
||
116 | struct lwpctl *l_lwpctl; /* p: lwpctl block kernel address */ |
||
117 | struct lcpage *l_lcpage; /* p: lwpctl containing page */ |
||
118 | kcpuset_t *l_affinity; /* l: CPU set for affinity */
|
||
119 | |||
120 | /* Synchronisation. */
|
||
121 | struct turnstile *l_ts; /* l: current turnstile */ |
||
122 | struct syncobj *l_syncobj; /* l: sync object operations set */ |
||
123 | TAILQ_ENTRY(lwp) l_sleepchain; /* l: sleep queue */
|
||
124 | wchan_t l_wchan; /* l: sleep address */
|
||
125 | const char *l_wmesg; /* l: reason for sleep */ |
||
126 | struct sleepq *l_sleepq; /* l: current sleep queue */ |
||
127 | int l_sleeperr; /* !: error before unblock */ |
||
128 | u_int l_slptime; /* l: time since last blocked */
|
||
129 | callout_t l_timeout_ch; /* !: callout for tsleep */
|
||
130 | u_int l_emap_gen; /* !: emap generation number */
|
||
131 | kcondvar_t l_waitcv; /* a: vfork() wait */
|
||
132 | |||
133 | #if PCU_UNIT_COUNT > 0 |
||
134 | struct cpu_info * volatile l_pcu_cpu[PCU_UNIT_COUNT]; |
||
135 | uint32_t l_pcu_valid; |
||
136 | #endif
|
||
137 | |||
138 | /* Process level and global state, misc. */
|
||
139 | LIST_ENTRY(lwp) l_list; /* a: entry on list of all LWPs */
|
||
140 | void *l_ctxlink; /* p: uc_link {get,set}context */ |
||
141 | struct proc *l_proc; /* p: parent process */ |
||
142 | LIST_ENTRY(lwp) l_sibling; /* p: entry on proc's list of LWPs */
|
||
143 | lwpid_t l_waiter; /* p: first LWP waiting on us */
|
||
144 | lwpid_t l_waitingfor; /* p: specific LWP we are waiting on */
|
||
145 | int l_prflag; /* p: process level flags */ |
||
146 | u_int l_refcnt; /* p: reference count on this LWP */
|
||
147 | lwpid_t l_lid; /* (: LWP identifier; local to proc */
|
||
148 | char *l_name; /* (: name, optional */ |
||
149 | |||
150 | /* State of select() or poll(). */
|
||
151 | int l_selflag; /* S: polling state flags */ |
||
152 | SLIST_HEAD(,selinfo) l_selwait; /* S: descriptors waited on */
|
||
153 | int l_selret; /* S: return value of select/poll */ |
||
154 | uintptr_t l_selrec; /* !: argument for selrecord() */
|
||
155 | struct selcluster *l_selcluster;/* !: associated cluster data */ |
||
156 | void * l_selbits; /* (: select() bit-field */ |
||
157 | size_t l_selni; /* (: size of a single bit-field */
|
||
158 | |||
159 | /* Signals. */
|
||
160 | int l_sigrestore; /* p: need to restore old sig mask */ |
||
161 | sigset_t l_sigwaitset; /* p: signals being waited for */
|
||
162 | kcondvar_t l_sigcv; /* p: for sigsuspend() */
|
||
163 | struct ksiginfo *l_sigwaited; /* p: delivered signals from set */ |
||
164 | sigpend_t *l_sigpendset; /* p: XXX issignal()/postsig() baton */
|
||
165 | LIST_ENTRY(lwp) l_sigwaiter; /* p: chain on list of waiting LWPs */
|
||
166 | stack_t l_sigstk; /* p: sp & on stack state variable */
|
||
167 | sigset_t l_sigmask; /* p: signal mask */
|
||
168 | sigpend_t l_sigpend; /* p: signals to this LWP */
|
||
169 | sigset_t l_sigoldmask; /* p: mask for sigpause */
|
||
170 | |||
171 | /* Private data. */
|
||
172 | specificdata_reference |
||
173 | l_specdataref; /* !: subsystem lwp-specific data */
|
||
174 | struct timespec l_ktrcsw; /* !: for ktrace CSW trace XXX */ |
||
175 | void *l_private; /* !: svr4-style lwp-private data */ |
||
176 | struct lwp *l_switchto; /* !: mi_switch: switch to this LWP */ |
||
177 | struct kauth_cred *l_cred; /* !: cached credentials */ |
||
178 | struct filedesc *l_fd; /* !: cached copy of proc::p_fd */ |
||
179 | void *l_emuldata; /* !: kernel lwp-private data */ |
||
180 | u_int l_cv_signalled; /* c: restarted by cv_signal() */
|
||
181 | u_short l_shlocks; /* !: lockdebug: shared locks held */
|
||
182 | u_short l_exlocks; /* !: lockdebug: excl. locks held */
|
||
183 | u_short l_unused; /* !: unused */
|
||
184 | u_short l_blcnt; /* !: count of kernel_lock held */
|
||
185 | int l_nopreempt; /* !: don't preempt me! */ |
||
186 | u_int l_dopreempt; /* s: kernel preemption pending */
|
||
187 | int l_pflag; /* !: LWP private flags */ |
||
188 | int l_dupfd; /* !: side return from cloning devs XXX */ |
||
189 | const struct sysent * volatile l_sysent;/* !: currently active syscall */ |
||
190 | struct rusage l_ru; /* !: accounting information */ |
||
191 | uint64_t l_pfailtime; /* !: for kernel preemption */
|
||
192 | uintptr_t l_pfailaddr; /* !: for kernel preemption */
|
||
193 | uintptr_t l_pfaillock; /* !: for kernel preemption */
|
||
194 | _TAILQ_HEAD(,struct lockdebug,volatile) l_ld_locks;/* !: locks held by LWP */ |
||
195 | int l_tcgen; /* !: for timecounter removal */ |
||
196 | |||
197 | /* These are only used by 'options SYSCALL_TIMES'. */
|
||
198 | uint32_t l_syscall_time; /* !: time epoch for current syscall */
|
||
199 | uint64_t *l_syscall_counter; /* !: counter for current process */
|
||
200 | |||
201 | struct kdtrace_thread *l_dtrace; /* (: DTrace-specific data. */ |
||
202 | }; |
||
203 | |||
204 | /*
|
||
205 | * UAREA_PCB_OFFSET: an offset of PCB structure in the uarea. MD code may
|
||
206 | * define it in <machine/proc.h>, to indicate a different uarea layout.
|
||
207 | */
|
||
208 | #ifndef UAREA_PCB_OFFSET
|
||
209 | #define UAREA_PCB_OFFSET 0 |
||
210 | #endif
|
||
211 | |||
212 | LIST_HEAD(lwplist, lwp); /* A list of LWPs. */
|
||
213 | |||
214 | #ifdef _KERNEL
|
||
215 | extern struct lwplist alllwp; /* List of all LWPs. */ |
||
216 | extern lwp_t lwp0; /* LWP for proc0. */ |
||
217 | extern int maxlwp __read_mostly; /* max number of lwps */ |
||
218 | #ifndef MAXLWP
|
||
219 | #define MAXLWP 2048 |
||
220 | #endif
|
||
221 | #ifndef __HAVE_CPU_MAXLWP
|
||
222 | #define cpu_maxlwp() MAXLWP
|
||
223 | #endif
|
||
224 | #endif
|
||
225 | |||
226 | #endif /* _KERNEL || _KMEMUSER */ |
||
227 | |||
228 | /* These flags are kept in l_flag. */
|
||
229 | #define LW_IDLE 0x00000001 /* Idle lwp. */ |
||
230 | #define LW_LWPCTL 0x00000002 /* Adjust lwpctl in userret */ |
||
231 | #define LW_SINTR 0x00000080 /* Sleep is interruptible. */ |
||
232 | #define LW_SYSTEM 0x00000200 /* Kernel thread */ |
||
233 | #define LW_WSUSPEND 0x00020000 /* Suspend before return to user */ |
||
234 | #define LW_BATCH 0x00040000 /* LWP tends to hog CPU */ |
||
235 | #define LW_WCORE 0x00080000 /* Stop for core dump on return to user */ |
||
236 | #define LW_WEXIT 0x00100000 /* Exit before return to user */ |
||
237 | #define LW_PENDSIG 0x01000000 /* Pending signal for us */ |
||
238 | #define LW_CANCELLED 0x02000000 /* tsleep should not sleep */ |
||
239 | #define LW_WREBOOT 0x08000000 /* System is rebooting, please suspend */ |
||
240 | #define LW_UNPARKED 0x10000000 /* Unpark op pending */ |
||
241 | #define LW_RUMP_CLEAR 0x40000000 /* Clear curlwp in RUMP scheduler */ |
||
242 | #define LW_RUMP_QEXIT 0x80000000 /* LWP should exit ASAP */ |
||
243 | |||
244 | /* The second set of flags is kept in l_pflag. */
|
||
245 | #define LP_KTRACTIVE 0x00000001 /* Executing ktrace operation */ |
||
246 | #define LP_KTRCSW 0x00000002 /* ktrace context switch marker */ |
||
247 | #define LP_KTRCSWUSER 0x00000004 /* ktrace context switch marker */ |
||
248 | #define LP_PIDLID 0x00000008 /* free LID from PID space on exit */ |
||
249 | #define LP_OWEUPC 0x00000010 /* Owe user profiling tick */ |
||
250 | #define LP_MPSAFE 0x00000020 /* Starts life without kernel_lock */ |
||
251 | #define LP_INTR 0x00000040 /* Soft interrupt handler */ |
||
252 | #define LP_SYSCTLWRITE 0x00000080 /* sysctl write lock held */ |
||
253 | #define LP_MUSTJOIN 0x00000100 /* Must join kthread on exit */ |
||
254 | #define LP_VFORKWAIT 0x00000200 /* Waiting at vfork() for a child */ |
||
255 | #define LP_TIMEINTR 0x00010000 /* Time this soft interrupt */ |
||
256 | #define LP_RUNNING 0x20000000 /* Active on a CPU */ |
||
257 | #define LP_BOUND 0x80000000 /* Bound to a CPU */ |
||
258 | |||
259 | /* The third set is kept in l_prflag. */
|
||
260 | #define LPR_DETACHED 0x00800000 /* Won't be waited for. */ |
||
261 | #define LPR_CRMOD 0x00000100 /* Credentials modified */ |
||
262 | |||
263 | /*
|
||
264 | * Mask indicating that there is "exceptional" work to be done on return to
|
||
265 | * user.
|
||
266 | */
|
||
267 | #define LW_USERRET \
|
||
268 | (LW_WEXIT | LW_PENDSIG | LW_WREBOOT | LW_WSUSPEND | LW_WCORE | LW_LWPCTL) |
||
269 | |||
270 | /*
|
||
271 | * Status values.
|
||
272 | *
|
||
273 | * A note about LSRUN and LSONPROC: LSRUN indicates that a process is
|
||
274 | * runnable but *not* yet running, i.e. is on a run queue. LSONPROC
|
||
275 | * indicates that the process is actually executing on a CPU, i.e.
|
||
276 | * it is no longer on a run queue.
|
||
277 | */
|
||
278 | #define LSIDL 1 /* Process being created by fork. */ |
||
279 | #define LSRUN 2 /* Currently runnable. */ |
||
280 | #define LSSLEEP 3 /* Sleeping on an address. */ |
||
281 | #define LSSTOP 4 /* Process debugging or suspension. */ |
||
282 | #define LSZOMB 5 /* Awaiting collection by parent. */ |
||
283 | /* unused, for source compatibility with NetBSD 4.0 and earlier. */
|
||
284 | #define LSDEAD 6 /* Process is almost a zombie. */ |
||
285 | #define LSONPROC 7 /* Process is currently on a CPU. */ |
||
286 | #define LSSUSPENDED 8 /* Not running, not signalable. */ |
||
287 | |||
288 | #if defined(_KERNEL) || defined(_KMEMUSER)
|
||
289 | static inline void * |
||
290 | lwp_getpcb(struct lwp *l)
|
||
291 | { |
||
292 | |||
293 | return l->l_addr;
|
||
294 | } |
||
295 | #endif /* _KERNEL || _KMEMUSER */ |
||
296 | |||
297 | #ifdef _KERNEL
|
||
298 | #define LWP_CACHE_CREDS(l, p) \
|
||
299 | do { \
|
||
300 | (void)p; \
|
||
301 | if (__predict_false((l)->l_prflag & LPR_CRMOD)) \
|
||
302 | lwp_update_creds(l); \ |
||
303 | } while (/* CONSTCOND */ 0) |
||
304 | |||
305 | void lwpinit(void); |
||
306 | void lwp0_init(void); |
||
307 | void lwp_sys_init(void); |
||
308 | |||
309 | void lwp_startup(lwp_t *, lwp_t *);
|
||
310 | void startlwp(void *); |
||
311 | |||
312 | int lwp_locked(lwp_t *, kmutex_t *);
|
||
313 | void lwp_setlock(lwp_t *, kmutex_t *);
|
||
314 | void lwp_unlock_to(lwp_t *, kmutex_t *);
|
||
315 | int lwp_trylock(lwp_t *);
|
||
316 | void lwp_addref(lwp_t *);
|
||
317 | void lwp_delref(lwp_t *);
|
||
318 | void lwp_delref2(lwp_t *);
|
||
319 | void lwp_drainrefs(lwp_t *);
|
||
320 | bool lwp_alive(lwp_t *);
|
||
321 | lwp_t *lwp_find_first(proc_t *); |
||
322 | |||
323 | int lwp_wait(lwp_t *, lwpid_t, lwpid_t *, bool); |
||
324 | void lwp_continue(lwp_t *);
|
||
325 | void lwp_unsleep(lwp_t *, bool); |
||
326 | void lwp_unstop(lwp_t *);
|
||
327 | void lwp_exit(lwp_t *);
|
||
328 | void lwp_exit_switchaway(lwp_t *) __dead;
|
||
329 | int lwp_suspend(lwp_t *, lwp_t *);
|
||
330 | int lwp_create1(lwp_t *, const void *, size_t, u_long, lwpid_t *); |
||
331 | void lwp_update_creds(lwp_t *);
|
||
332 | void lwp_migrate(lwp_t *, struct cpu_info *); |
||
333 | lwp_t * lwp_find2(pid_t, lwpid_t); |
||
334 | lwp_t * lwp_find(proc_t *, int);
|
||
335 | void lwp_userret(lwp_t *);
|
||
336 | void lwp_need_userret(lwp_t *);
|
||
337 | void lwp_free(lwp_t *, bool, bool); |
||
338 | uint64_t lwp_pctr(void);
|
||
339 | int lwp_setprivate(lwp_t *, void *); |
||
340 | int do_lwp_create(lwp_t *, void *, u_long, lwpid_t *); |
||
341 | |||
342 | void lwpinit_specificdata(void); |
||
343 | int lwp_specific_key_create(specificdata_key_t *, specificdata_dtor_t);
|
||
344 | void lwp_specific_key_delete(specificdata_key_t);
|
||
345 | void lwp_initspecific(lwp_t *);
|
||
346 | void lwp_finispecific(lwp_t *);
|
||
347 | void *lwp_getspecific(specificdata_key_t);
|
||
348 | #if defined(_LWP_API_PRIVATE)
|
||
349 | void *_lwp_getspecific_by_lwp(lwp_t *, specificdata_key_t);
|
||
350 | #endif
|
||
351 | void lwp_setspecific(specificdata_key_t, void *); |
||
352 | |||
353 | /* Syscalls. */
|
||
354 | int lwp_park(clockid_t, int, struct timespec *, const void *); |
||
355 | int lwp_unpark(lwpid_t, const void *); |
||
356 | |||
357 | /* DDB. */
|
||
358 | void lwp_whatis(uintptr_t, void (*)(const char *, ...) __printflike(1, 2)); |
||
359 | |||
360 | /*
|
||
361 | * Lock an LWP. XXX _MODULE
|
||
362 | */
|
||
363 | static inline void |
||
364 | lwp_lock(lwp_t *l) |
||
365 | { |
||
366 | kmutex_t *old = l->l_mutex; |
||
367 | |||
368 | /*
|
||
369 | * Note: mutex_spin_enter() will have posted a read barrier.
|
||
370 | * Re-test l->l_mutex. If it has changed, we need to try again.
|
||
371 | */
|
||
372 | mutex_spin_enter(old); |
||
373 | while (__predict_false(l->l_mutex != old)) {
|
||
374 | mutex_spin_exit(old); |
||
375 | old = l->l_mutex; |
||
376 | mutex_spin_enter(old); |
||
377 | } |
||
378 | } |
||
379 | |||
380 | /*
|
||
381 | * Unlock an LWP. XXX _MODULE
|
||
382 | */
|
||
383 | static inline void |
||
384 | lwp_unlock(lwp_t *l) |
||
385 | { |
||
386 | mutex_spin_exit(l->l_mutex); |
||
387 | } |
||
388 | |||
389 | static inline void |
||
390 | lwp_changepri(lwp_t *l, pri_t pri) |
||
391 | { |
||
392 | KASSERT(mutex_owned(l->l_mutex)); |
||
393 | |||
394 | if (l->l_priority == pri)
|
||
395 | return;
|
||
396 | |||
397 | (*l->l_syncobj->sobj_changepri)(l, pri); |
||
398 | KASSERT(l->l_priority == pri); |
||
399 | } |
||
400 | |||
401 | static inline void |
||
402 | lwp_lendpri(lwp_t *l, pri_t pri) |
||
403 | { |
||
404 | KASSERT(mutex_owned(l->l_mutex)); |
||
405 | |||
406 | if (l->l_inheritedprio == pri)
|
||
407 | return;
|
||
408 | |||
409 | (*l->l_syncobj->sobj_lendpri)(l, pri); |
||
410 | KASSERT(l->l_inheritedprio == pri); |
||
411 | } |
||
412 | |||
413 | static inline pri_t |
||
414 | lwp_eprio(lwp_t *l) |
||
415 | { |
||
416 | pri_t pri; |
||
417 | |||
418 | pri = l->l_priority; |
||
419 | if ((l->l_flag & LW_SYSTEM) == 0 && l->l_kpriority && pri < PRI_KERNEL) |
||
420 | pri = (pri >> 1) + l->l_kpribase;
|
||
421 | return MAX(l->l_inheritedprio, pri);
|
||
422 | } |
||
423 | |||
424 | int lwp_create(lwp_t *, struct proc *, vaddr_t, int, |
||
425 | void *, size_t, void (*)(void *), void *, lwp_t **, int); |
||
426 | |||
427 | /*
|
||
428 | * XXX _MODULE
|
||
429 | * We should provide real stubs for the below that modules can use.
|
||
430 | */
|
||
431 | |||
432 | static inline void |
||
433 | spc_lock(struct cpu_info *ci)
|
||
434 | { |
||
435 | mutex_spin_enter(ci->ci_schedstate.spc_mutex); |
||
436 | } |
||
437 | |||
438 | static inline void |
||
439 | spc_unlock(struct cpu_info *ci)
|
||
440 | { |
||
441 | mutex_spin_exit(ci->ci_schedstate.spc_mutex); |
||
442 | } |
||
443 | |||
444 | static inline void |
||
445 | spc_dlock(struct cpu_info *ci1, struct cpu_info *ci2) |
||
446 | { |
||
447 | struct schedstate_percpu *spc1 = &ci1->ci_schedstate;
|
||
448 | struct schedstate_percpu *spc2 = &ci2->ci_schedstate;
|
||
449 | |||
450 | KASSERT(ci1 != ci2); |
||
451 | if (ci1 < ci2) {
|
||
452 | mutex_spin_enter(spc1->spc_mutex); |
||
453 | mutex_spin_enter(spc2->spc_mutex); |
||
454 | } else {
|
||
455 | mutex_spin_enter(spc2->spc_mutex); |
||
456 | mutex_spin_enter(spc1->spc_mutex); |
||
457 | } |
||
458 | } |
||
459 | |||
460 | /*
|
||
461 | * Allow machine-dependent code to override curlwp in <machine/cpu.h> for
|
||
462 | * its own convenience. Otherwise, we declare it as appropriate.
|
||
463 | */
|
||
464 | #if !defined(curlwp)
|
||
465 | #if defined(MULTIPROCESSOR)
|
||
466 | #define curlwp curcpu()->ci_curlwp /* Current running LWP */ |
||
467 | #else
|
||
468 | extern struct lwp *curlwp; /* Current running LWP */ |
||
469 | #endif /* MULTIPROCESSOR */ |
||
470 | #endif /* ! curlwp */ |
||
471 | #define curproc (curlwp->l_proc)
|
||
472 | |||
473 | /*
|
||
474 | * This provide a way for <machine/cpu.h> to get l_cpu for curlwp before
|
||
475 | * struct lwp is defined.
|
||
476 | */
|
||
477 | static inline struct cpu_info * |
||
478 | lwp_getcpu(struct lwp *l)
|
||
479 | { |
||
480 | return l->l_cpu;
|
||
481 | } |
||
482 | |||
483 | static inline bool |
||
484 | CURCPU_IDLE_P(void)
|
||
485 | { |
||
486 | struct cpu_info *ci = curcpu();
|
||
487 | return ci->ci_data.cpu_onproc == ci->ci_data.cpu_idlelwp;
|
||
488 | } |
||
489 | |||
490 | /*
|
||
491 | * Disable and re-enable preemption. Only for low-level kernel
|
||
492 | * use. Device drivers and anything that could potentially be
|
||
493 | * compiled as a module should use kpreempt_disable() and
|
||
494 | * kpreempt_enable().
|
||
495 | */
|
||
496 | static inline void |
||
497 | KPREEMPT_DISABLE(lwp_t *l) |
||
498 | { |
||
499 | |||
500 | KASSERT(l == curlwp); |
||
501 | l->l_nopreempt++; |
||
502 | __insn_barrier(); |
||
503 | } |
||
504 | |||
505 | static inline void |
||
506 | KPREEMPT_ENABLE(lwp_t *l) |
||
507 | { |
||
508 | |||
509 | KASSERT(l == curlwp); |
||
510 | KASSERT(l->l_nopreempt > 0);
|
||
511 | __insn_barrier(); |
||
512 | if (--l->l_nopreempt != 0) |
||
513 | return;
|
||
514 | __insn_barrier(); |
||
515 | if (__predict_false(l->l_dopreempt))
|
||
516 | kpreempt(0);
|
||
517 | __insn_barrier(); |
||
518 | } |
||
519 | |||
520 | /* For lwp::l_dopreempt */
|
||
521 | #define DOPREEMPT_ACTIVE 0x01 |
||
522 | #define DOPREEMPT_COUNTED 0x02 |
||
523 | |||
524 | #endif /* _KERNEL */ |
||
525 | |||
526 | /* Flags for _lwp_create(), as per Solaris. */
|
||
527 | #define LWP_DETACHED 0x00000040 |
||
528 | #define LWP_SUSPENDED 0x00000080 |
||
529 | |||
530 | /* Kernel-internal flags for LWP creation. */
|
||
531 | #define LWP_PIDLID 0x40000000 |
||
532 | #define LWP_VFORK 0x80000000 |
||
533 | |||
534 | #endif /* !_SYS_LWP_H_ */ |