kernel - Refactor smp collision statistics
[dragonfly.git] / sys / kern / lwkt_token.c
1 /*
2  * Copyright (c) 2003,2004,2009 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 /*
36  * lwkt_token - Implement soft token locks.
37  *
38  * Tokens are locks which serialize a thread only while the thread is
39  * running.  If the thread blocks all tokens are released, then reacquired
40  * when the thread resumes.
41  *
42  * This implementation requires no critical sections or spin locks, but
43  * does use atomic_cmpset_ptr().
44  *
45  * Tokens may be recursively acquired by the same thread.  However the
46  * caller must be sure to release such tokens in reverse order.
47  */
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/proc.h>
52 #include <sys/rtprio.h>
53 #include <sys/queue.h>
54 #include <sys/sysctl.h>
55 #include <sys/ktr.h>
56 #include <sys/kthread.h>
57 #include <machine/cpu.h>
58 #include <sys/lock.h>
59 #include <sys/spinlock.h>
60 #include <sys/indefinite.h>
61
62 #include <sys/thread2.h>
63 #include <sys/spinlock2.h>
64 #include <sys/mplock2.h>
65 #include <sys/indefinite2.h>
66
67 #include <vm/vm.h>
68 #include <vm/vm_param.h>
69 #include <vm/vm_kern.h>
70 #include <vm/vm_object.h>
71 #include <vm/vm_page.h>
72 #include <vm/vm_map.h>
73 #include <vm/vm_pager.h>
74 #include <vm/vm_extern.h>
75 #include <vm/vm_zone.h>
76
77 #include <machine/stdarg.h>
78 #include <machine/smp.h>
79
80 #include "opt_ddb.h"
81 #ifdef DDB
82 #include <ddb/ddb.h>
83 #endif
84
85 extern int lwkt_sched_debug;
86
87 #ifndef LWKT_NUM_POOL_TOKENS
88 #define LWKT_NUM_POOL_TOKENS    4001    /* prime number */
89 #endif
90
91 struct lwkt_pool_token {
92         struct lwkt_token       token;
93 } __cachealign;
94
95 static struct lwkt_pool_token   pool_tokens[LWKT_NUM_POOL_TOKENS];
96 struct spinlock         tok_debug_spin = SPINLOCK_INITIALIZER(&tok_debug_spin, "tok_debug_spin");
97
98 #define TOKEN_STRING    "REF=%p TOK=%p TD=%p"
99 #define TOKEN_ARGS      lwkt_tokref_t ref, lwkt_token_t tok, struct thread *td
100 #define CONTENDED_STRING        TOKEN_STRING " (contention started)"
101 #define UNCONTENDED_STRING      TOKEN_STRING " (contention stopped)"
102 #if !defined(KTR_TOKENS)
103 #define KTR_TOKENS      KTR_ALL
104 #endif
105
106 KTR_INFO_MASTER(tokens);
107 KTR_INFO(KTR_TOKENS, tokens, fail, 0, TOKEN_STRING, TOKEN_ARGS);
108 KTR_INFO(KTR_TOKENS, tokens, succ, 1, TOKEN_STRING, TOKEN_ARGS);
109 #if 0
110 KTR_INFO(KTR_TOKENS, tokens, release, 2, TOKEN_STRING, TOKEN_ARGS);
111 KTR_INFO(KTR_TOKENS, tokens, remote, 3, TOKEN_STRING, TOKEN_ARGS);
112 KTR_INFO(KTR_TOKENS, tokens, reqremote, 4, TOKEN_STRING, TOKEN_ARGS);
113 KTR_INFO(KTR_TOKENS, tokens, reqfail, 5, TOKEN_STRING, TOKEN_ARGS);
114 KTR_INFO(KTR_TOKENS, tokens, drain, 6, TOKEN_STRING, TOKEN_ARGS);
115 KTR_INFO(KTR_TOKENS, tokens, contention_start, 7, CONTENDED_STRING, TOKEN_ARGS);
116 KTR_INFO(KTR_TOKENS, tokens, contention_stop, 7, UNCONTENDED_STRING, TOKEN_ARGS);
117 #endif
118
119 #define logtoken(name, ref)                                             \
120         KTR_LOG(tokens_ ## name, ref, ref->tr_tok, curthread)
121
122 /*
123  * Global tokens.  These replace the MP lock for major subsystem locking.
124  * These tokens are initially used to lockup both global and individual
125  * operations.
126  *
127  * Once individual structures get their own locks these tokens are used
128  * only to protect global lists & other variables and to interlock
129  * allocations and teardowns and such.
130  *
131  * The UP initializer causes token acquisition to also acquire the MP lock
132  * for maximum compatibility.  The feature may be enabled and disabled at
133  * any time, the MP state is copied to the tokref when the token is acquired
134  * and will not race against sysctl changes.
135  */
136 struct lwkt_token mp_token = LWKT_TOKEN_INITIALIZER(mp_token);
137 struct lwkt_token pmap_token = LWKT_TOKEN_INITIALIZER(pmap_token);
138 struct lwkt_token dev_token = LWKT_TOKEN_INITIALIZER(dev_token);
139 struct lwkt_token vm_token = LWKT_TOKEN_INITIALIZER(vm_token);
140 struct lwkt_token vmspace_token = LWKT_TOKEN_INITIALIZER(vmspace_token);
141 struct lwkt_token kvm_token = LWKT_TOKEN_INITIALIZER(kvm_token);
142 struct lwkt_token sigio_token = LWKT_TOKEN_INITIALIZER(sigio_token);
143 struct lwkt_token tty_token = LWKT_TOKEN_INITIALIZER(tty_token);
144 struct lwkt_token vnode_token = LWKT_TOKEN_INITIALIZER(vnode_token);
145
146 static int lwkt_token_spin = 5;
147 SYSCTL_INT(_lwkt, OID_AUTO, token_spin, CTLFLAG_RW,
148     &lwkt_token_spin, 0, "Decontention spin loops");
149 static int lwkt_token_delay = 0;
150 SYSCTL_INT(_lwkt, OID_AUTO, token_delay, CTLFLAG_RW,
151     &lwkt_token_delay, 0, "Decontention spin delay in ns");
152
153 /*
154  * The collision count is bumped every time the LWKT scheduler fails
155  * to acquire needed tokens in addition to a normal lwkt_gettoken()
156  * stall.
157  */
158 SYSCTL_LONG(_lwkt, OID_AUTO, mp_collisions, CTLFLAG_RW,
159     &mp_token.t_collisions, 0, "Collision counter of mp_token");
160 SYSCTL_LONG(_lwkt, OID_AUTO, pmap_collisions, CTLFLAG_RW,
161     &pmap_token.t_collisions, 0, "Collision counter of pmap_token");
162 SYSCTL_LONG(_lwkt, OID_AUTO, dev_collisions, CTLFLAG_RW,
163     &dev_token.t_collisions, 0, "Collision counter of dev_token");
164 SYSCTL_LONG(_lwkt, OID_AUTO, vm_collisions, CTLFLAG_RW,
165     &vm_token.t_collisions, 0, "Collision counter of vm_token");
166 SYSCTL_LONG(_lwkt, OID_AUTO, vmspace_collisions, CTLFLAG_RW,
167     &vmspace_token.t_collisions, 0, "Collision counter of vmspace_token");
168 SYSCTL_LONG(_lwkt, OID_AUTO, kvm_collisions, CTLFLAG_RW,
169     &kvm_token.t_collisions, 0, "Collision counter of kvm_token");
170 SYSCTL_LONG(_lwkt, OID_AUTO, sigio_collisions, CTLFLAG_RW,
171     &sigio_token.t_collisions, 0, "Collision counter of sigio_token");
172 SYSCTL_LONG(_lwkt, OID_AUTO, tty_collisions, CTLFLAG_RW,
173     &tty_token.t_collisions, 0, "Collision counter of tty_token");
174 SYSCTL_LONG(_lwkt, OID_AUTO, vnode_collisions, CTLFLAG_RW,
175     &vnode_token.t_collisions, 0, "Collision counter of vnode_token");
176
177 int tokens_debug_output;
178 SYSCTL_INT(_lwkt, OID_AUTO, tokens_debug_output, CTLFLAG_RW,
179     &tokens_debug_output, 0, "Generate stack trace N times");
180
181
182 #ifdef DEBUG_LOCKS_LATENCY
183
184 static long tokens_add_latency;
185 SYSCTL_LONG(_debug, OID_AUTO, tokens_add_latency, CTLFLAG_RW,
186             &tokens_add_latency, 0,
187             "Add spinlock latency");
188
189 #endif
190
191
192 static int _lwkt_getalltokens_sorted(thread_t td);
193
194 /*
195  * Acquire the initial mplock
196  *
197  * (low level boot only)
198  */
199 void
200 cpu_get_initial_mplock(void)
201 {
202         KKASSERT(mp_token.t_ref == NULL);
203         if (lwkt_trytoken(&mp_token) == FALSE)
204                 panic("cpu_get_initial_mplock");
205 }
206
207 /*
208  * Return a pool token given an address.  Use a prime number to reduce
209  * overlaps.
210  */
211 static __inline
212 lwkt_token_t
213 _lwkt_token_pool_lookup(void *ptr)
214 {
215         u_int i;
216
217         i = (u_int)(uintptr_t)ptr % LWKT_NUM_POOL_TOKENS;
218         return (&pool_tokens[i].token);
219 }
220
221 /*
222  * Initialize a tokref_t prior to making it visible in the thread's
223  * token array.
224  */
225 static __inline
226 void
227 _lwkt_tokref_init(lwkt_tokref_t ref, lwkt_token_t tok, thread_t td, long excl)
228 {
229         ref->tr_tok = tok;
230         ref->tr_count = excl;
231         ref->tr_owner = td;
232 }
233
234 /*
235  * Attempt to acquire a shared or exclusive token.  Returns TRUE on success,
236  * FALSE on failure.
237  *
238  * If TOK_EXCLUSIVE is set in mode we are attempting to get an exclusive
239  * token, otherwise are attempting to get a shared token.
240  *
241  * If TOK_EXCLREQ is set in mode this is a blocking operation, otherwise
242  * it is a non-blocking operation (for both exclusive or shared acquisions).
243  */
244 static __inline
245 int
246 _lwkt_trytokref(lwkt_tokref_t ref, thread_t td, long mode)
247 {
248         lwkt_token_t tok;
249         lwkt_tokref_t oref;
250         long count;
251
252         tok = ref->tr_tok;
253         KASSERT(((mode & TOK_EXCLREQ) == 0 ||   /* non blocking */
254                 td->td_gd->gd_intr_nesting_level == 0 ||
255                 panic_cpu_gd == mycpu),
256                 ("Attempt to acquire token %p not already "
257                 "held in hard code section", tok));
258
259         if (mode & TOK_EXCLUSIVE) {
260                 /*
261                  * Attempt to get an exclusive token
262                  */
263                 for (;;) {
264                         count = tok->t_count;
265                         oref = tok->t_ref;      /* can be NULL */
266                         cpu_ccfence();
267                         if ((count & ~TOK_EXCLREQ) == 0) {
268                                 /*
269                                  * It is possible to get the exclusive bit.
270                                  * We must clear TOK_EXCLREQ on successful
271                                  * acquisition.
272                                  */
273                                 if (atomic_cmpset_long(&tok->t_count, count,
274                                                        (count & ~TOK_EXCLREQ) |
275                                                        TOK_EXCLUSIVE)) {
276                                         KKASSERT(tok->t_ref == NULL);
277                                         tok->t_ref = ref;
278                                         return TRUE;
279                                 }
280                                 /* retry */
281                         } else if ((count & TOK_EXCLUSIVE) &&
282                                    oref >= &td->td_toks_base &&
283                                    oref < td->td_toks_stop) {
284                                 /*
285                                  * Our thread already holds the exclusive
286                                  * bit, we treat this tokref as a shared
287                                  * token (sorta) to make the token release
288                                  * code easier.
289                                  *
290                                  * NOTE: oref cannot race above if it
291                                  *       happens to be ours, so we're good.
292                                  *       But we must still have a stable
293                                  *       variable for both parts of the
294                                  *       comparison.
295                                  *
296                                  * NOTE: Since we already have an exclusive
297                                  *       lock and don't need to check EXCLREQ
298                                  *       we can just use an atomic_add here
299                                  */
300                                 atomic_add_long(&tok->t_count, TOK_INCR);
301                                 ref->tr_count &= ~TOK_EXCLUSIVE;
302                                 return TRUE;
303                         } else if ((mode & TOK_EXCLREQ) &&
304                                    (count & TOK_EXCLREQ) == 0) {
305                                 /*
306                                  * Unable to get the exclusive bit but being
307                                  * asked to set the exclusive-request bit.
308                                  * Since we are going to retry anyway just
309                                  * set the bit unconditionally.
310                                  */
311                                 atomic_set_long(&tok->t_count, TOK_EXCLREQ);
312                                 return FALSE;
313                         } else {
314                                 /*
315                                  * Unable to get the exclusive bit and not
316                                  * being asked to set the exclusive-request
317                                  * (aka lwkt_trytoken()), or EXCLREQ was
318                                  * already set.
319                                  */
320                                 cpu_pause();
321                                 return FALSE;
322                         }
323                         /* retry */
324                 }
325         } else {
326                 /*
327                  * Attempt to get a shared token.  Note that TOK_EXCLREQ
328                  * for shared tokens simply means the caller intends to
329                  * block.  We never actually set the bit in tok->t_count.
330                  */
331                 for (;;) {
332                         count = tok->t_count;
333                         oref = tok->t_ref;      /* can be NULL */
334                         cpu_ccfence();
335                         if ((count & (TOK_EXCLUSIVE/*|TOK_EXCLREQ*/)) == 0) {
336                                 /*
337                                  * It may be possible to get the token shared.
338                                  */
339                                 if ((atomic_fetchadd_long(&tok->t_count, TOK_INCR) & TOK_EXCLUSIVE) == 0) {
340                                         return TRUE;
341                                 }
342                                 atomic_fetchadd_long(&tok->t_count, -TOK_INCR);
343                                 /* retry */
344                         } else if ((count & TOK_EXCLUSIVE) &&
345                                    oref >= &td->td_toks_base &&
346                                    oref < td->td_toks_stop) {
347                                 /*
348                                  * We own the exclusive bit on the token so
349                                  * we can in fact also get it shared.
350                                  */
351                                 atomic_add_long(&tok->t_count, TOK_INCR);
352                                 return TRUE;
353                         } else {
354                                 /*
355                                  * We failed to get the token shared
356                                  */
357                                 return FALSE;
358                         }
359                         /* retry */
360                 }
361         }
362 }
363
364 static __inline
365 int
366 _lwkt_trytokref_spin(lwkt_tokref_t ref, thread_t td, long mode)
367 {
368         int spin;
369
370         if (_lwkt_trytokref(ref, td, mode)) {
371 #ifdef DEBUG_LOCKS_LATENCY
372                 long j;
373                 for (j = tokens_add_latency; j > 0; --j)
374                         cpu_ccfence();
375 #endif
376                 return TRUE;
377         }
378         for (spin = lwkt_token_spin; spin > 0; --spin) {
379                 if (lwkt_token_delay)
380                         tsc_delay(lwkt_token_delay);
381                 else
382                         cpu_pause();
383                 if (_lwkt_trytokref(ref, td, mode)) {
384 #ifdef DEBUG_LOCKS_LATENCY
385                         long j;
386                         for (j = tokens_add_latency; j > 0; --j)
387                                 cpu_ccfence();
388 #endif
389                         return TRUE;
390                 }
391         }
392         return FALSE;
393 }
394
395 /*
396  * Release a token that we hold.
397  */
398 static __inline
399 void
400 _lwkt_reltokref(lwkt_tokref_t ref, thread_t td)
401 {
402         lwkt_token_t tok;
403         long count;
404
405         tok = ref->tr_tok;
406         for (;;) {
407                 count = tok->t_count;
408                 cpu_ccfence();
409                 if (tok->t_ref == ref) {
410                         /*
411                          * We are an exclusive holder.  We must clear tr_ref
412                          * before we clear the TOK_EXCLUSIVE bit.  If we are
413                          * unable to clear the bit we must restore
414                          * tok->t_ref.
415                          */
416                         KKASSERT(count & TOK_EXCLUSIVE);
417                         tok->t_ref = NULL;
418                         if (atomic_cmpset_long(&tok->t_count, count,
419                                                count & ~TOK_EXCLUSIVE)) {
420                                 return;
421                         }
422                         tok->t_ref = ref;
423                         /* retry */
424                 } else {
425                         /*
426                          * We are a shared holder
427                          */
428                         KKASSERT(count & TOK_COUNTMASK);
429                         if (atomic_cmpset_long(&tok->t_count, count,
430                                                count - TOK_INCR)) {
431                                 return;
432                         }
433                         /* retry */
434                 }
435                 /* retry */
436         }
437 }
438
439 /*
440  * Obtain all the tokens required by the specified thread on the current
441  * cpu, return 0 on failure and non-zero on success.  If a failure occurs
442  * any partially acquired tokens will be released prior to return.
443  *
444  * lwkt_getalltokens is called by the LWKT scheduler to re-acquire all
445  * tokens that the thread had to release when it switched away.
446  *
447  * If spinning is non-zero this function acquires the tokens in a particular
448  * order to deal with potential deadlocks.  We simply use address order for
449  * the case.
450  *
451  * Called from a critical section.
452  */
453 int
454 lwkt_getalltokens(thread_t td, int spinning)
455 {
456         lwkt_tokref_t scan;
457         lwkt_token_t tok;
458
459         if (spinning)
460                 return(_lwkt_getalltokens_sorted(td));
461
462         /*
463          * Acquire tokens in forward order, assign or validate tok->t_ref.
464          */
465         for (scan = &td->td_toks_base; scan < td->td_toks_stop; ++scan) {
466                 tok = scan->tr_tok;
467                 for (;;) {
468                         /*
469                          * Only try really hard on the last token
470                          */
471                         if (scan == td->td_toks_stop - 1) {
472                             if (_lwkt_trytokref_spin(scan, td, scan->tr_count))
473                                     break;
474                         } else {
475                             if (_lwkt_trytokref(scan, td, scan->tr_count))
476                                     break;
477                         }
478
479                         /*
480                          * Otherwise we failed to acquire all the tokens.
481                          * Release whatever we did get.
482                          */
483                         KASSERT(tok->t_desc,
484                                 ("token %p is not initialized", tok));
485
486                         if (td->td_indefinite.type == 0) {
487                                 indefinite_init(&td->td_indefinite,
488                                                 tok->t_desc, 1, 't');
489                         } else {
490                                 indefinite_check(&td->td_indefinite);
491                         }
492                         if (lwkt_sched_debug > 0) {
493                                 --lwkt_sched_debug;
494                                 kprintf("toka %p %s %s\n",
495                                         tok, tok->t_desc, td->td_comm);
496                         }
497                         td->td_wmesg = tok->t_desc;
498                         ++tok->t_collisions;
499                         while (--scan >= &td->td_toks_base)
500                                 _lwkt_reltokref(scan, td);
501                         return(FALSE);
502                 }
503         }
504         return (TRUE);
505 }
506
507 /*
508  * Release all tokens owned by the specified thread on the current cpu.
509  *
510  * This code is really simple.  Even in cases where we own all the tokens
511  * note that t_ref may not match the scan for recursively held tokens which
512  * are held deeper in the stack, or for the case where a lwkt_getalltokens()
513  * failed.
514  *
515  * Tokens are released in reverse order to reduce chasing race failures.
516  * 
517  * Called from a critical section.
518  */
519 void
520 lwkt_relalltokens(thread_t td)
521 {
522         lwkt_tokref_t scan;
523
524         /*
525          * Weird order is to try to avoid a panic loop
526          */
527         if (td->td_toks_have) {
528                 scan = td->td_toks_have;
529                 td->td_toks_have = NULL;
530         } else {
531                 scan = td->td_toks_stop;
532         }
533         while (--scan >= &td->td_toks_base)
534                 _lwkt_reltokref(scan, td);
535 }
536
537 /*
538  * This is the decontention version of lwkt_getalltokens().  The tokens are
539  * acquired in address-sorted order to deal with any deadlocks.  Ultimately
540  * token failures will spin into the scheduler and get here.
541  *
542  * Called from critical section
543  */
544 static
545 int
546 _lwkt_getalltokens_sorted(thread_t td)
547 {
548         lwkt_tokref_t sort_array[LWKT_MAXTOKENS];
549         lwkt_tokref_t scan;
550         lwkt_token_t tok;
551         int i;
552         int j;
553         int n;
554
555         /*
556          * Sort the token array.  Yah yah, I know this isn't fun.
557          *
558          * NOTE: Recursively acquired tokens are ordered the same as in the
559          *       td_toks_array so we can always get the earliest one first.
560          */
561         i = 0;
562         scan = &td->td_toks_base;
563         while (scan < td->td_toks_stop) {
564                 for (j = 0; j < i; ++j) {
565                         if (scan->tr_tok < sort_array[j]->tr_tok)
566                                 break;
567                 }
568                 if (j != i) {
569                         bcopy(sort_array + j, sort_array + j + 1,
570                               (i - j) * sizeof(lwkt_tokref_t));
571                 }
572                 sort_array[j] = scan;
573                 ++scan;
574                 ++i;
575         }
576         n = i;
577
578         /*
579          * Acquire tokens in forward order, assign or validate tok->t_ref.
580          */
581         for (i = 0; i < n; ++i) {
582                 scan = sort_array[i];
583                 tok = scan->tr_tok;
584                 for (;;) {
585                         /*
586                          * Only try really hard on the last token
587                          */
588                         if (scan == td->td_toks_stop - 1) {
589                             if (_lwkt_trytokref_spin(scan, td, scan->tr_count))
590                                     break;
591                         } else {
592                             if (_lwkt_trytokref(scan, td, scan->tr_count))
593                                     break;
594                         }
595
596                         /*
597                          * Otherwise we failed to acquire all the tokens.
598                          * Release whatever we did get.
599                          */
600                         if (td->td_indefinite.type == 0) {
601                                 indefinite_init(&td->td_indefinite,
602                                                 tok->t_desc, 1, 't');
603                         } else {
604                                 indefinite_check(&td->td_indefinite);
605                         }
606                         if (lwkt_sched_debug > 0) {
607                                 --lwkt_sched_debug;
608                                 kprintf("tokb %p %s %s\n",
609                                         tok, tok->t_desc, td->td_comm);
610                         }
611                         td->td_wmesg = tok->t_desc;
612                         ++tok->t_collisions;
613                         while (--i >= 0) {
614                                 scan = sort_array[i];
615                                 _lwkt_reltokref(scan, td);
616                         }
617                         return(FALSE);
618                 }
619         }
620
621         /*
622          * We were successful, there is no need for another core to signal
623          * us.
624          */
625         return (TRUE);
626 }
627
628 /*
629  * Get a serializing token.  This routine can block.
630  */
631 void
632 lwkt_gettoken(lwkt_token_t tok)
633 {
634         thread_t td = curthread;
635         lwkt_tokref_t ref;
636
637         ref = td->td_toks_stop;
638         KKASSERT(ref < &td->td_toks_end);
639         ++td->td_toks_stop;
640         cpu_ccfence();
641         _lwkt_tokref_init(ref, tok, td, TOK_EXCLUSIVE|TOK_EXCLREQ);
642
643 #ifdef DEBUG_LOCKS
644         /*
645          * Taking an exclusive token after holding it shared will
646          * livelock. Scan for that case and assert.
647          */
648         lwkt_tokref_t tk;
649         int found = 0;
650         for (tk = &td->td_toks_base; tk < ref; tk++) {
651                 if (tk->tr_tok != tok)
652                         continue;
653                 
654                 found++;
655                 if (tk->tr_count & TOK_EXCLUSIVE) 
656                         goto good;
657         }
658         /* We found only shared instances of this token if found >0 here */
659         KASSERT((found == 0), ("Token %p s/x livelock", tok));
660 good:
661 #endif
662
663         if (_lwkt_trytokref_spin(ref, td, TOK_EXCLUSIVE|TOK_EXCLREQ))
664                 return;
665
666         /*
667          * Give up running if we can't acquire the token right now.
668          *
669          * Since the tokref is already active the scheduler now
670          * takes care of acquisition, so we need only call
671          * lwkt_switch().
672          *
673          * Since we failed this was not a recursive token so upon
674          * return tr_tok->t_ref should be assigned to this specific
675          * ref.
676          */
677         td->td_wmesg = tok->t_desc;
678         ++tok->t_collisions;
679         logtoken(fail, ref);
680         td->td_toks_have = td->td_toks_stop - 1;
681
682         if (tokens_debug_output > 0) {
683                 --tokens_debug_output;
684                 spin_lock(&tok_debug_spin);
685                 kprintf("Excl Token thread %p %s %s\n",
686                         td, tok->t_desc, td->td_comm);
687                 print_backtrace(6);
688                 kprintf("\n");
689                 spin_unlock(&tok_debug_spin);
690         }
691
692         lwkt_switch();
693         logtoken(succ, ref);
694         KKASSERT(tok->t_ref == ref);
695 }
696
697 /*
698  * Similar to gettoken but we acquire a shared token instead of an exclusive
699  * token.
700  */
701 void
702 lwkt_gettoken_shared(lwkt_token_t tok)
703 {
704         thread_t td = curthread;
705         lwkt_tokref_t ref;
706
707         ref = td->td_toks_stop;
708         KKASSERT(ref < &td->td_toks_end);
709         ++td->td_toks_stop;
710         cpu_ccfence();
711         _lwkt_tokref_init(ref, tok, td, TOK_EXCLREQ);
712
713 #ifdef DEBUG_LOCKS
714         /*
715          * Taking a pool token in shared mode is a bad idea; other
716          * addresses deeper in the call stack may hash to the same pool
717          * token and you may end up with an exclusive-shared livelock.
718          * Warn in this condition.
719          */
720         if ((tok >= &pool_tokens[0].token) &&
721             (tok < &pool_tokens[LWKT_NUM_POOL_TOKENS].token))
722                 kprintf("Warning! Taking pool token %p in shared mode\n", tok);
723 #endif
724
725
726         if (_lwkt_trytokref_spin(ref, td, TOK_EXCLREQ))
727                 return;
728
729         /*
730          * Give up running if we can't acquire the token right now.
731          *
732          * Since the tokref is already active the scheduler now
733          * takes care of acquisition, so we need only call
734          * lwkt_switch().
735          *
736          * Since we failed this was not a recursive token so upon
737          * return tr_tok->t_ref should be assigned to this specific
738          * ref.
739          */
740         td->td_wmesg = tok->t_desc;
741         ++tok->t_collisions;
742         logtoken(fail, ref);
743         td->td_toks_have = td->td_toks_stop - 1;
744
745         if (tokens_debug_output > 0) {
746                 --tokens_debug_output;
747                 spin_lock(&tok_debug_spin);
748                 kprintf("Shar Token thread %p %s %s\n",
749                         td, tok->t_desc, td->td_comm);
750                 print_backtrace(6);
751                 kprintf("\n");
752                 spin_unlock(&tok_debug_spin);
753         }
754
755         lwkt_switch();
756         logtoken(succ, ref);
757 }
758
759 /*
760  * Attempt to acquire a token, return TRUE on success, FALSE on failure.
761  *
762  * We setup the tokref in case we actually get the token (if we switch later
763  * it becomes mandatory so we set TOK_EXCLREQ), but we call trytokref without
764  * TOK_EXCLREQ in case we fail.
765  */
766 int
767 lwkt_trytoken(lwkt_token_t tok)
768 {
769         thread_t td = curthread;
770         lwkt_tokref_t ref;
771
772         ref = td->td_toks_stop;
773         KKASSERT(ref < &td->td_toks_end);
774         ++td->td_toks_stop;
775         cpu_ccfence();
776         _lwkt_tokref_init(ref, tok, td, TOK_EXCLUSIVE|TOK_EXCLREQ);
777
778         if (_lwkt_trytokref(ref, td, TOK_EXCLUSIVE))
779                 return TRUE;
780
781         /*
782          * Failed, unpend the request
783          */
784         cpu_ccfence();
785         --td->td_toks_stop;
786         ++tok->t_collisions;
787         return FALSE;
788 }
789
790 lwkt_token_t
791 lwkt_getpooltoken(void *ptr)
792 {
793         lwkt_token_t tok;
794
795         tok = _lwkt_token_pool_lookup(ptr);
796         lwkt_gettoken(tok);
797         return (tok);
798 }
799
800 /*
801  * Release a serializing token.
802  *
803  * WARNING!  All tokens must be released in reverse order.  This will be
804  *           asserted.
805  */
806 void
807 lwkt_reltoken(lwkt_token_t tok)
808 {
809         thread_t td = curthread;
810         lwkt_tokref_t ref;
811
812         /*
813          * Remove ref from thread token list and assert that it matches
814          * the token passed in.  Tokens must be released in reverse order.
815          */
816         ref = td->td_toks_stop - 1;
817         KKASSERT(ref >= &td->td_toks_base && ref->tr_tok == tok);
818         _lwkt_reltokref(ref, td);
819         cpu_sfence();
820         td->td_toks_stop = ref;
821 }
822
823 /*
824  * It is faster for users of lwkt_getpooltoken() to use the returned
825  * token and just call lwkt_reltoken(), but for convenience we provide
826  * this function which looks the token up based on the ident.
827  */
828 void
829 lwkt_relpooltoken(void *ptr)
830 {
831         lwkt_token_t tok = _lwkt_token_pool_lookup(ptr);
832         lwkt_reltoken(tok);
833 }
834
835 /*
836  * Return a count of the number of token refs the thread has to the
837  * specified token, whether it currently owns the token or not.
838  */
839 int
840 lwkt_cnttoken(lwkt_token_t tok, thread_t td)
841 {
842         lwkt_tokref_t scan;
843         int count = 0;
844
845         for (scan = &td->td_toks_base; scan < td->td_toks_stop; ++scan) {
846                 if (scan->tr_tok == tok)
847                         ++count;
848         }
849         return(count);
850 }
851
852 /*
853  * Pool tokens are used to provide a type-stable serializing token
854  * pointer that does not race against disappearing data structures.
855  *
856  * This routine is called in early boot just after we setup the BSP's
857  * globaldata structure.
858  */
859 void
860 lwkt_token_pool_init(void)
861 {
862         int i;
863
864         for (i = 0; i < LWKT_NUM_POOL_TOKENS; ++i)
865                 lwkt_token_init(&pool_tokens[i].token, "pool");
866 }
867
868 lwkt_token_t
869 lwkt_token_pool_lookup(void *ptr)
870 {
871         return (_lwkt_token_pool_lookup(ptr));
872 }
873
874 /*
875  * Initialize a token.  
876  */
877 void
878 lwkt_token_init(lwkt_token_t tok, const char *desc)
879 {
880         tok->t_count = 0;
881         tok->t_ref = NULL;
882         tok->t_collisions = 0;
883         tok->t_desc = desc;
884 }
885
886 void
887 lwkt_token_uninit(lwkt_token_t tok)
888 {
889         /* empty */
890 }
891
892 /*
893  * Exchange the two most recent tokens on the tokref stack.  This allows
894  * you to release a token out of order.
895  *
896  * We have to be careful about the case where the top two tokens are
897  * the same token.  In this case tok->t_ref will point to the deeper
898  * ref and must remain pointing to the deeper ref.  If we were to swap
899  * it the first release would clear the token even though a second
900  * ref is still present.
901  *
902  * Only exclusively held tokens contain a reference to the tokref which
903  * has to be flipped along with the swap.
904  */
905 void
906 lwkt_token_swap(void)
907 {
908         lwkt_tokref_t ref1, ref2;
909         lwkt_token_t tok1, tok2;
910         long count1, count2;
911         thread_t td = curthread;
912
913         crit_enter();
914
915         ref1 = td->td_toks_stop - 1;
916         ref2 = td->td_toks_stop - 2;
917         KKASSERT(ref1 >= &td->td_toks_base);
918         KKASSERT(ref2 >= &td->td_toks_base);
919
920         tok1 = ref1->tr_tok;
921         tok2 = ref2->tr_tok;
922         count1 = ref1->tr_count;
923         count2 = ref2->tr_count;
924
925         if (tok1 != tok2) {
926                 ref1->tr_tok = tok2;
927                 ref1->tr_count = count2;
928                 ref2->tr_tok = tok1;
929                 ref2->tr_count = count1;
930                 if (tok1->t_ref == ref1)
931                         tok1->t_ref = ref2;
932                 if (tok2->t_ref == ref2)
933                         tok2->t_ref = ref1;
934         }
935
936         crit_exit();
937 }
938
939 #ifdef DDB
940 DB_SHOW_COMMAND(tokens, db_tok_all)
941 {
942         struct lwkt_token *tok, **ptr;
943         struct lwkt_token *toklist[16] = {
944                 &mp_token,
945                 &pmap_token,
946                 &dev_token,
947                 &vm_token,
948                 &vmspace_token,
949                 &kvm_token,
950                 &sigio_token,
951                 &tty_token,
952                 &vnode_token,
953                 NULL
954         };
955
956         ptr = toklist;
957         for (tok = *ptr; tok; tok = *(++ptr)) {
958                 db_printf("tok=%p tr_owner=%p t_colissions=%ld t_desc=%s\n", tok,
959                     (tok->t_ref ? tok->t_ref->tr_owner : NULL),
960                     tok->t_collisions, tok->t_desc);
961         }
962 }
963 #endif /* DDB */