1 #include "splat-internal.h"
3 #define SPLAT_SUBSYSTEM_THREAD 0x0600
4 #define SPLAT_THREAD_NAME "thread"
5 #define SPLAT_THREAD_DESC "Kernel Thread Tests"
7 #define SPLAT_THREAD_TEST1_ID 0x0601
8 #define SPLAT_THREAD_TEST1_NAME "create"
9 #define SPLAT_THREAD_TEST1_DESC "Validate thread creation"
11 #define SPLAT_THREAD_TEST2_ID 0x0602
12 #define SPLAT_THREAD_TEST2_NAME "exit"
13 #define SPLAT_THREAD_TEST2_DESC "Validate thread exit"
15 #define SPLAT_THREAD_TEST_MAGIC 0x4488CC00UL
17 typedef struct thread_priv
{
18 unsigned long tp_magic
;
21 wait_queue_head_t tp_waitq
;
26 splat_thread_rc(thread_priv_t
*tp
, int rc
)
30 spin_lock(&tp
->tp_lock
);
31 ret
= (tp
->tp_rc
== rc
);
32 spin_unlock(&tp
->tp_lock
);
38 splat_thread_work1(void *priv
)
40 thread_priv_t
*tp
= (thread_priv_t
*)priv
;
42 spin_lock(&tp
->tp_lock
);
43 ASSERT(tp
->tp_magic
== SPLAT_THREAD_TEST_MAGIC
);
45 spin_unlock(&tp
->tp_lock
);
47 wake_up(&tp
->tp_waitq
);
52 splat_thread_test1(struct file
*file
, void *arg
)
58 tp
.tp_magic
= SPLAT_THREAD_TEST_MAGIC
;
60 spin_lock_init(&tp
.tp_lock
);
61 init_waitqueue_head(&tp
.tp_waitq
);
64 thr
= (kthread_t
*)thread_create(NULL
, 0, splat_thread_work1
, &tp
, 0,
65 &p0
, TS_RUN
, minclsyspri
);
66 /* Must never fail under Solaris, but we check anyway since this
67 * can happen in the linux SPL, we may want to change this behavior */
71 /* Sleep until the thread sets tp.tp_rc == 1 */
72 wait_event(tp
.tp_waitq
, splat_thread_rc(&tp
, 1));
74 splat_vprint(file
, SPLAT_THREAD_TEST1_NAME
, "%s",
75 "Thread successfully started properly\n");
80 splat_thread_work2(void *priv
)
82 thread_priv_t
*tp
= (thread_priv_t
*)priv
;
84 spin_lock(&tp
->tp_lock
);
85 ASSERT(tp
->tp_magic
== SPLAT_THREAD_TEST_MAGIC
);
87 spin_unlock(&tp
->tp_lock
);
89 wake_up(&tp
->tp_waitq
);
92 /* The following code is unreachable when thread_exit() is
93 * working properly, which is exactly what we're testing */
94 spin_lock(&tp
->tp_lock
);
96 spin_unlock(&tp
->tp_lock
);
98 wake_up(&tp
->tp_waitq
);
102 splat_thread_test2(struct file
*file
, void *arg
)
109 tp
.tp_magic
= SPLAT_THREAD_TEST_MAGIC
;
111 spin_lock_init(&tp
.tp_lock
);
112 init_waitqueue_head(&tp
.tp_waitq
);
115 thr
= (kthread_t
*)thread_create(NULL
, 0, splat_thread_work2
, &tp
, 0,
116 &p0
, TS_RUN
, minclsyspri
);
117 /* Must never fail under Solaris, but we check anyway since this
118 * can happen in the linux SPL, we may want to change this behavior */
122 /* Sleep until the thread sets tp.tp_rc == 1 */
123 wait_event(tp
.tp_waitq
, splat_thread_rc(&tp
, 1));
125 /* Sleep until the thread sets tp.tp_rc == 2, or until we hit
126 * the timeout. If thread exit is working properly we should
127 * hit the timeout and never see to.tp_rc == 2. */
128 rc
= wait_event_timeout(tp
.tp_waitq
, splat_thread_rc(&tp
, 2), HZ
/ 10);
131 splat_vprint(file
, SPLAT_THREAD_TEST2_NAME
, "%s",
132 "Thread did not exit properly at thread_exit()\n");
134 splat_vprint(file
, SPLAT_THREAD_TEST2_NAME
, "%s",
135 "Thread successfully exited at thread_exit()\n");
142 splat_thread_init(void)
144 splat_subsystem_t
*sub
;
146 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
150 memset(sub
, 0, sizeof(*sub
));
151 strncpy(sub
->desc
.name
, SPLAT_THREAD_NAME
, SPLAT_NAME_SIZE
);
152 strncpy(sub
->desc
.desc
, SPLAT_THREAD_DESC
, SPLAT_DESC_SIZE
);
153 INIT_LIST_HEAD(&sub
->subsystem_list
);
154 INIT_LIST_HEAD(&sub
->test_list
);
155 spin_lock_init(&sub
->test_lock
);
156 sub
->desc
.id
= SPLAT_SUBSYSTEM_THREAD
;
158 SPLAT_TEST_INIT(sub
, SPLAT_THREAD_TEST1_NAME
, SPLAT_THREAD_TEST1_DESC
,
159 SPLAT_THREAD_TEST1_ID
, splat_thread_test1
);
160 SPLAT_TEST_INIT(sub
, SPLAT_THREAD_TEST2_NAME
, SPLAT_THREAD_TEST2_DESC
,
161 SPLAT_THREAD_TEST2_ID
, splat_thread_test2
);
167 splat_thread_fini(splat_subsystem_t
*sub
)
170 SPLAT_TEST_FINI(sub
, SPLAT_THREAD_TEST2_ID
);
171 SPLAT_TEST_FINI(sub
, SPLAT_THREAD_TEST1_ID
);
177 splat_thread_id(void) {
178 return SPLAT_SUBSYSTEM_THREAD
;