kernel - MPSAFE work - add vmspace_token
[dragonfly.git] / sys / sys / thread.h
index 946cca7..7c65bc4 100644 (file)
@@ -98,60 +98,47 @@ struct intrframe;
  * Tokens are managed through a helper reference structure, lwkt_tokref,
  * which is typically declared on the caller's stack.  Multiple tokref's
  * may reference the same token.
- *
- * It is possible to detect that your token was temporarily lost via
- * lwkt_token_is_stale(), which uses the t_lastowner field.  This field
- * does NOT necessarily represent the current owner and can become stale
- * (not point to a valid structure).  It is used solely to detect
- * whether the token was temporarily lost to another thread.  The lost
- * state is cleared by the function.
  */
 
 typedef struct lwkt_token {
-#ifdef SMP
-    struct spinlock    t_spinlock;     /* Controls access */
-#else
-    struct spinlock    t_unused01;
-#endif
-    struct thread      *t_owner;       /* The current owner of the token */
-    int                        t_count;        /* Per-thread count */
-    struct thread       *t_lastowner;  /* Last owner that acquired token */ 
+    struct lwkt_tokref *t_ref;         /* Owning ref or NULL */
+    intptr_t           t_flags;        /* MP lock required */
+    long               t_collisions;   /* Collision counter */
 } lwkt_token;
 
-#ifdef SMP
-#define LWKT_TOKEN_INITIALIZER(head) \
-{ \
-       .t_spinlock = SPINLOCK_INITIALIZER(head.t_spinlock), \
-       .t_owner = NULL, \
-       .t_lastowner = NULL, \
-       .t_count = 0 \
+#define LWKT_TOKEN_MPSAFE      0x0001
+
+/*
+ * Static initialization for a lwkt_token.
+ *     UP - Not MPSAFE (full MP lock will also be acquired)
+ *     MP - Is MPSAFE  (only the token will be acquired)
+ */
+#define LWKT_TOKEN_UP_INITIALIZER      \
+{                                      \
+       .t_ref = NULL,                  \
+       .t_flags = 0,                   \
+       .t_collisions = 0               \
 }
-#else
-#define LWKT_TOKEN_INITIALIZER(head) \
-{ \
-       .t_owner = NULL, \
-       .t_lastowner = NULL, \
-       .t_count = 0 \
+
+#define LWKT_TOKEN_MP_INITIALIZER      \
+{                                      \
+       .t_ref = NULL,                  \
+       .t_flags = LWKT_TOKEN_MPSAFE,   \
+       .t_collisions = 0               \
 }
-#endif
 
-#define ASSERT_LWKT_TOKEN_HELD(token) \
-       KKASSERT((token)->t_owner == curthread)
+#define ASSERT_LWKT_TOKEN_HELD(tok) \
+       KKASSERT((tok)->t_ref->tr_owner == curthread)
 
-typedef struct lwkt_tokref {
+struct lwkt_tokref {
     lwkt_token_t       tr_tok;         /* token in question */
-    lwkt_tokref_t      tr_next;        /* linked list */
-    int                        tr_state;       /* 0 = don't have, 1 = have */
-} lwkt_tokref;
-
-#define LWKT_TOKREF_INIT(tok)          \
-                       { tok, NULL, 0 }
-#define LWKT_TOKREF_DECLARE(name, tok) \
-                       lwkt_tokref name = LWKT_TOKREF_INIT(tok)
+    struct thread      *tr_owner;      /* me */
+    intptr_t           tr_flags;       /* copy of t_flags */
+};
 
 #define MAXCPUFIFO      16     /* power of 2 */
 #define MAXCPUFIFO_MASK        (MAXCPUFIFO - 1)
-#define LWKT_MAXTOKENS 16      /* max tokens beneficially held by thread */
+#define LWKT_MAXTOKENS 32      /* max tokens beneficially held by thread */
 
 /*
  * Always cast to ipifunc_t when registering an ipi.  The actual ipi function
@@ -230,7 +217,7 @@ struct thread {
     struct pcb *td_pcb;        /* points to pcb and top of kstack */
     struct globaldata *td_gd;  /* associated with this cpu */
     const char *td_wmesg;      /* string name for blockage */
-    void       *td_wchan;      /* waiting on channel */
+    const volatile void        *td_wchan;      /* waiting on channel */
     int                td_pri;         /* 0-31, 31=highest priority (note 1) */
     int                td_flags;       /* TDF flags */
     int                td_wdomain;     /* domain for wchan address (typ 0) */
@@ -245,6 +232,7 @@ struct thread {
     __uint64_t td_iticks;      /* Statclock hits processing intr (uS) */
     int                td_locks;       /* lockmgr lock debugging */
     int                td_unused01;
+    void       *td_dsched_priv1;       /* priv data for I/O schedulers */
     int                td_refs;        /* hold position in gd_tdallq / hold free */
     int                td_nest_count;  /* prevent splz nesting */
 #ifdef SMP
@@ -260,7 +248,8 @@ struct thread {
     struct thread *td_preempted; /* we preempted this thread */
     struct ucred *td_ucred;            /* synchronized from p_ucred */
     struct caps_kinfo *td_caps;        /* list of client and server registrations */
-    lwkt_tokref_t td_toks;     /* tokens beneficially held */
+    lwkt_tokref_t td_toks_stop;
+    struct lwkt_tokref td_toks_array[LWKT_MAXTOKENS];
 #ifdef DEBUG_CRIT_SECTIONS
 #define CRIT_DEBUG_ARRAY_SIZE   32
 #define CRIT_DEBUG_ARRAY_MASK   (CRIT_DEBUG_ARRAY_SIZE - 1)
@@ -271,6 +260,12 @@ struct thread {
     struct md_thread td_mach;
 };
 
+#define td_toks_base   td_toks_array[0]
+#define td_toks_end    td_toks_array[LWKT_MAXTOKENS]
+
+#define TD_TOKS_HELD(td)       ((td)->td_toks_stop != &(td)->td_toks_base)
+#define TD_TOKS_NOT_HELD(td)   ((td)->td_toks_stop == &(td)->td_toks_base)
+
 /*
  * Thread flags.  Note that TDF_RUNNING is cleared on the old thread after
  * we switch to the new one, which is necessary because LWKTs don't need
@@ -326,6 +321,7 @@ struct thread {
  * rollup flag will be set in mycpu->gd_reqflags.
  */
 #define TDPRI_IDLE_THREAD      0       /* the idle thread */
+#define TDPRI_IDLE_WORK                1       /* idle work (page zero, etc) */
 #define TDPRI_USER_SCHEDULER   2       /* user scheduler helper */
 #define TDPRI_USER_IDLE                4       /* user scheduler idle */
 #define TDPRI_USER_NORM                6       /* user scheduler normal */
@@ -345,19 +341,34 @@ struct thread {
 #define TDPRI_MASK             31
 #define TDPRI_CRIT             32      /* high bits of td_pri used for crit */
 
-#ifdef _KERNEL
 #define LWKT_THREAD_STACK      (UPAGES * PAGE_SIZE)
-#endif
 
 #define CACHE_NTHREADS         6
 
 #define IN_CRITICAL_SECT(td)   ((td)->td_pri >= TDPRI_CRIT)
 
+#ifdef _KERNEL
+
+/*
+ * Global tokens
+ */
+extern struct lwkt_token pmap_token;
+extern struct lwkt_token dev_token;
+extern struct lwkt_token vm_token;
+extern struct lwkt_token vmspace_token;
+extern struct lwkt_token kvm_token;
+extern struct lwkt_token proc_token;
+extern struct lwkt_token tty_token;
+extern struct lwkt_token vnode_token;
+
+/*
+ * Procedures
+ */
 extern void lwkt_init(void);
 extern struct thread *lwkt_alloc_thread(struct thread *, int, int, int);
 extern void lwkt_init_thread(struct thread *, void *, int, int,
                             struct globaldata *);
-extern void lwkt_set_comm(thread_t, const char *, ...);
+extern void lwkt_set_comm(thread_t, const char *, ...) __printflike(2, 3);
 extern void lwkt_wait_free(struct thread *);
 extern void lwkt_free_thread(struct thread *);
 extern void lwkt_gdinit(struct globaldata *);
@@ -375,20 +386,18 @@ extern void lwkt_hold(thread_t);
 extern void lwkt_rele(thread_t);
 extern void lwkt_passive_release(thread_t);
 
-extern void lwkt_gettoken(lwkt_tokref_t, lwkt_token_t);
-extern int lwkt_trytoken(lwkt_tokref_t, lwkt_token_t);
-extern void lwkt_gettokref(lwkt_tokref_t);
-extern int  lwkt_trytokref(lwkt_tokref_t);
-extern void lwkt_reltoken(lwkt_tokref_t);
+extern void lwkt_gettoken(lwkt_token_t);
+extern int  lwkt_trytoken(lwkt_token_t);
+extern void lwkt_reltoken(lwkt_token_t);
 extern int  lwkt_getalltokens(thread_t);
 extern void lwkt_relalltokens(thread_t);
 extern void lwkt_drain_token_requests(void);
-extern void lwkt_token_init(lwkt_token_t);
+extern void lwkt_token_init(lwkt_token_t, int);
 extern void lwkt_token_uninit(lwkt_token_t);
-extern int  lwkt_token_is_stale(lwkt_tokref_t);
 
 extern void lwkt_token_pool_init(void);
-extern lwkt_token_t lwkt_token_pool_get(void *);
+extern lwkt_token_t lwkt_token_pool_lookup(void *);
+extern lwkt_token_t lwkt_getpooltoken(void *);
 
 extern void lwkt_setpri(thread_t, int);
 extern void lwkt_setpri_initial(thread_t, int);
@@ -411,9 +420,7 @@ extern int  lwkt_send_ipiq3_mask(cpumask_t, ipifunc3_t, void *, int);
 extern void lwkt_wait_ipiq(struct globaldata *, int);
 extern int  lwkt_seq_ipiq(struct globaldata *);
 extern void lwkt_process_ipiq(void);
-#ifdef _KERNEL
 extern void lwkt_process_ipiq_frame(struct intrframe *);
-#endif
 extern void lwkt_smp_stopped(void);
 extern void lwkt_synchronize_ipiqs(const char *);
 
@@ -429,9 +436,12 @@ extern void crit_panic(void);
 extern struct lwp *lwkt_preempted_proc(void);
 
 extern int  lwkt_create (void (*func)(void *), void *, struct thread **,
-                        struct thread *, int, int, const char *, ...);
+               struct thread *, int, int,
+               const char *, ...) __printflike(7, 8);
 extern void lwkt_exit (void) __dead2;
 extern void lwkt_remove_tdallq (struct thread *);
 
 #endif
 
+#endif
+