dsched - Implement priorities and other improvements
[dragonfly.git] / sys / dsched / fq / dsched_fq_procops.c
1 /*
2  * Copyright (c) 2009, 2010 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Alex Hornung <ahornung@gmail.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 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/proc.h>
38 #include <sys/sysctl.h>
39 #include <sys/buf.h>
40 #include <sys/conf.h>
41 #include <sys/diskslice.h>
42 #include <sys/disk.h>
43 #include <machine/atomic.h>
44 #include <sys/malloc.h>
45 #include <sys/thread.h>
46 #include <sys/thread2.h>
47 #include <sys/sysctl.h>
48 #include <sys/spinlock2.h>
49 #include <machine/md_var.h>
50 #include <sys/ctype.h>
51 #include <sys/syslog.h>
52 #include <sys/device.h>
53 #include <sys/msgport.h>
54 #include <sys/msgport2.h>
55 #include <sys/buf2.h>
56 #include <sys/dsched.h>
57 #include <machine/varargs.h>
58 #include <machine/param.h>
59
60 #include <dsched/fq/dsched_fq.h>
61
62 MALLOC_DECLARE(M_DSCHEDFQ);
63
64 dsched_new_buf_t        fq_new_buf;
65 dsched_new_proc_t       fq_new_proc;
66 dsched_new_thread_t     fq_new_thread;
67 dsched_exit_buf_t       fq_exit_buf;
68 dsched_exit_proc_t      fq_exit_proc;
69 dsched_exit_thread_t    fq_exit_thread;
70
71 extern struct dsched_fq_stats   fq_stats;
72
73 void
74 fq_new_buf(struct buf *bp)
75 {
76         struct dsched_fq_mpriv  *fqmp = NULL;
77
78         if (curproc != NULL /* XXX: is it -1 or is it 0? */) {
79                 fqmp = dsched_get_proc_priv(curproc);
80         } else {
81                 /* This is a kernel thread, so no proc info is available */
82                 fqmp = dsched_get_thread_priv(curthread);
83         }
84
85 #if 0
86         /*
87          * XXX: hack. we don't want this assert because we aren't catching all
88          *      threads. mi_startup() is still getting away without an fqmp.
89          */
90
91         /* by now we should have an fqmp. if not, something bad is going on */
92         KKASSERT(fqmp != NULL);
93 #endif
94
95         if (fqmp) {
96                 atomic_add_int(&fq_stats.nbufs, 1);
97                 fq_reference_mpriv(fqmp);
98         }
99         dsched_set_buf_priv(bp, fqmp);
100         
101 }
102
103 void
104 fq_exit_buf(struct buf *bp)
105 {
106         struct dsched_fq_mpriv  *fqmp;
107
108         fqmp = dsched_get_buf_priv(bp);
109         if (fqmp != NULL) {
110                 dsched_clr_buf_priv(bp);
111                 fq_dereference_mpriv(fqmp);
112                 atomic_subtract_int(&fq_stats.nbufs, 1);
113         }
114 }
115
116 void
117 fq_new_proc(struct proc *p)
118 {
119         struct dsched_fq_mpriv  *fqmp;
120
121         KKASSERT(p != NULL);
122
123         fqmp = fq_alloc_mpriv(p);
124         fq_reference_mpriv(fqmp);
125         dsched_set_proc_priv(p, fqmp);
126         atomic_add_int(&fq_stats.nprocs, 1);
127         fqmp->p = p;
128 }
129
130 void
131 fq_new_thread(struct thread *td)
132 {
133         struct dsched_fq_mpriv  *fqmp;
134
135         KKASSERT(td != NULL);
136
137         fqmp = fq_alloc_mpriv(NULL);
138         fq_reference_mpriv(fqmp);
139         dsched_set_thread_priv(td, fqmp);
140         atomic_add_int(&fq_stats.nthreads, 1);
141         fqmp->td = td;
142 }
143
144 void
145 fq_exit_proc(struct proc *p)
146 {
147         struct dsched_fq_mpriv  *fqmp;
148
149         KKASSERT(p != NULL);
150
151         fqmp = dsched_get_proc_priv(p);
152         KKASSERT(fqmp != NULL);
153 #if 0
154         kprintf("exit_proc: fqmp = %p\n", fqmp);
155 #endif
156         fqmp->dead = 0x1337;
157         dsched_set_proc_priv(p, 0);
158         fq_dereference_mpriv(fqmp); /* one for alloc, */
159         fq_dereference_mpriv(fqmp); /* one for ref */
160         atomic_subtract_int(&fq_stats.nprocs, 1);
161 }
162
163 void
164 fq_exit_thread(struct thread *td)
165 {
166         struct dsched_fq_mpriv  *fqmp;
167
168         KKASSERT(td != NULL);
169
170         fqmp = dsched_get_thread_priv(td);
171         KKASSERT(fqmp != NULL);
172 #if 0
173         kprintf("exit_thread: fqmp = %p\n", fqmp);
174 #endif
175         fqmp->dead = 0x1337;
176         dsched_set_thread_priv(td, 0);
177         fq_dereference_mpriv(fqmp); /* one for alloc, */
178         fq_dereference_mpriv(fqmp); /* one for ref */
179         atomic_subtract_int(&fq_stats.nthreads, 1);
180 }