1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5 * Author: Isaac Huang <isaac@clusterfs.com>
8 #define DEBUG_SUBSYSTEM S_LNET
13 struct smoketest_workitem {
14 struct list_head wi_runq; /* concurrent workitems */
15 struct list_head wi_serial_runq; /* serialised workitems */
16 cfs_waitq_t wi_waitq; /* where schedulers sleep */
17 cfs_waitq_t wi_serial_waitq; /* where serial scheduler sleep */
18 spinlock_t wi_lock; /* serialize */
24 swi_sched_cansleep (struct list_head *q)
28 spin_lock(&swi_data.wi_lock);
30 rc = !swi_data.wi_shuttingdown && list_empty(q);
32 spin_unlock(&swi_data.wi_lock);
37 * 0. it only works when called from wi->wi_action.
38 * 1. when it returns no one shall try to schedule the workitem.
41 swi_kill_workitem (swi_workitem_t *wi)
43 LASSERT (!in_interrupt()); /* because we use plain spinlock */
44 LASSERT (!swi_data.wi_shuttingdown);
46 spin_lock(&swi_data.wi_lock);
49 LASSERT (wi->wi_running);
52 if (wi->wi_scheduled) { /* cancel pending schedules */
53 LASSERT (!list_empty(&wi->wi_list));
54 list_del_init(&wi->wi_list);
57 LASSERT (list_empty(&wi->wi_list));
58 wi->wi_scheduled = 1; /* LBUG future schedule attempts */
60 spin_unlock(&swi_data.wi_lock);
65 swi_schedule_workitem (swi_workitem_t *wi)
67 LASSERT (!in_interrupt()); /* because we use plain spinlock */
68 LASSERT (!swi_data.wi_shuttingdown);
70 spin_lock(&swi_data.wi_lock);
72 if (!wi->wi_scheduled) {
73 LASSERT (list_empty(&wi->wi_list));
76 list_add_tail(&wi->wi_list, &swi_data.wi_runq);
77 cfs_waitq_signal(&swi_data.wi_waitq);
80 LASSERT (!list_empty(&wi->wi_list));
81 spin_unlock(&swi_data.wi_lock);
86 * Workitem scheduled by this function is strictly serialised not only with
87 * itself, but also with others scheduled this way.
89 * Now there's only one static serialised queue, but in the future more might
90 * be added, and even dynamic creation of serialised queues might be supported.
93 swi_schedule_serial_workitem (swi_workitem_t *wi)
95 LASSERT (!in_interrupt()); /* because we use plain spinlock */
96 LASSERT (!swi_data.wi_shuttingdown);
98 spin_lock(&swi_data.wi_lock);
100 if (!wi->wi_scheduled) {
101 LASSERT (list_empty(&wi->wi_list));
103 wi->wi_scheduled = 1;
104 list_add_tail(&wi->wi_list, &swi_data.wi_serial_runq);
105 cfs_waitq_signal(&swi_data.wi_serial_waitq);
108 LASSERT (!list_empty(&wi->wi_list));
109 spin_unlock(&swi_data.wi_lock);
116 swi_scheduler_main (void *arg)
121 snprintf(name, sizeof(name), "swi_sd%03d", id);
125 spin_lock(&swi_data.wi_lock);
127 while (!swi_data.wi_shuttingdown) {
132 while (!list_empty(&swi_data.wi_runq) &&
133 nloops < SWI_RESCHED) {
134 wi = list_entry(swi_data.wi_runq.next,
135 swi_workitem_t, wi_list);
136 list_del_init(&wi->wi_list);
138 LASSERT (wi->wi_scheduled);
141 if (wi->wi_running) {
142 list_add_tail(&wi->wi_list, &swi_data.wi_runq);
147 wi->wi_scheduled = 0;
148 spin_unlock(&swi_data.wi_lock);
150 rc = (*wi->wi_action) (wi);
152 spin_lock(&swi_data.wi_lock);
153 if (rc == 0) /* wi still active */
157 spin_unlock(&swi_data.wi_lock);
159 if (nloops < SWI_RESCHED)
160 wait_event_interruptible_exclusive(
162 !swi_sched_cansleep(&swi_data.wi_runq));
166 spin_lock(&swi_data.wi_lock);
169 swi_data.wi_nthreads--;
170 spin_unlock(&swi_data.wi_lock);
175 swi_serial_scheduler_main (void *arg)
179 cfs_daemonize("swi_serial_sd");
182 spin_lock(&swi_data.wi_lock);
184 while (!swi_data.wi_shuttingdown) {
189 while (!list_empty(&swi_data.wi_serial_runq) &&
190 nloops < SWI_RESCHED) {
191 wi = list_entry(swi_data.wi_serial_runq.next,
192 swi_workitem_t, wi_list);
193 list_del_init(&wi->wi_list);
195 LASSERT (!wi->wi_running);
196 LASSERT (wi->wi_scheduled);
200 wi->wi_scheduled = 0;
201 spin_unlock(&swi_data.wi_lock);
203 rc = (*wi->wi_action) (wi);
205 spin_lock(&swi_data.wi_lock);
206 if (rc == 0) /* wi still active */
210 spin_unlock(&swi_data.wi_lock);
212 if (nloops < SWI_RESCHED)
213 wait_event_interruptible_exclusive(
214 swi_data.wi_serial_waitq,
215 !swi_sched_cansleep(&swi_data.wi_serial_runq));
219 spin_lock(&swi_data.wi_lock);
222 swi_data.wi_nthreads--;
223 spin_unlock(&swi_data.wi_lock);
228 swi_start_thread (int (*func) (void*), void *arg)
232 LASSERT (!swi_data.wi_shuttingdown);
234 pid = cfs_kernel_thread(func, arg, 0);
238 spin_lock(&swi_data.wi_lock);
239 swi_data.wi_nthreads++;
240 spin_unlock(&swi_data.wi_lock);
244 #else /* __KERNEL__ */
247 swi_check_events (void)
253 spin_lock(&swi_data.wi_lock);
256 if (!list_empty(&swi_data.wi_serial_runq))
257 q = &swi_data.wi_serial_runq;
258 else if (!list_empty(&swi_data.wi_runq))
259 q = &swi_data.wi_runq;
263 wi = list_entry(q->next, swi_workitem_t, wi_list);
264 list_del_init(&wi->wi_list);
266 LASSERT (wi->wi_scheduled);
267 wi->wi_scheduled = 0;
268 spin_unlock(&swi_data.wi_lock);
271 (*wi->wi_action) (wi);
273 spin_lock(&swi_data.wi_lock);
276 spin_unlock(&swi_data.wi_lock);
288 swi_data.wi_nthreads = 0;
289 swi_data.wi_shuttingdown = 0;
290 spin_lock_init(&swi_data.wi_lock);
291 cfs_waitq_init(&swi_data.wi_waitq);
292 cfs_waitq_init(&swi_data.wi_serial_waitq);
293 CFS_INIT_LIST_HEAD(&swi_data.wi_runq);
294 CFS_INIT_LIST_HEAD(&swi_data.wi_serial_runq);
297 rc = swi_start_thread(swi_serial_scheduler_main, NULL);
299 LASSERT (swi_data.wi_nthreads == 0);
300 CERROR ("Can't spawn serial workitem scheduler: %d\n", rc);
304 for (i = 0; i < num_online_cpus(); i++) {
305 rc = swi_start_thread(swi_scheduler_main, (void *) (long) i);
307 CERROR ("Can't spawn workitem scheduler: %d\n", rc);
323 spin_lock(&swi_data.wi_lock);
325 LASSERT (list_empty(&swi_data.wi_runq));
326 LASSERT (list_empty(&swi_data.wi_serial_runq));
328 swi_data.wi_shuttingdown = 1;
331 cfs_waitq_broadcast(&swi_data.wi_waitq);
332 cfs_waitq_broadcast(&swi_data.wi_serial_waitq);
333 lst_wait_until(swi_data.wi_nthreads == 0, swi_data.wi_lock,
334 "waiting for %d threads to terminate\n",
335 swi_data.wi_nthreads);
338 spin_unlock(&swi_data.wi_lock);