1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
14 * Copyright 2018 RackTop Systems.
15 */
16
17 #include <sys/cmn_err.h>
18 #include <sys/thread.h>
19 #include <sys/zone.h>
20 #include <sys/proc.h>
21 #include <sys/atomic.h>
22
23 #define _SYNCH_H /* keep out <synch.h> */
24 #include <thread.h>
25
26 /*
27 * Get the current kthread_t pointer.
28 */
29 kthread_t *
_curthread(void)30 _curthread(void)
31 {
32 thread_t tid;
33
34 tid = thr_self();
35 return ((kthread_t *)(uintptr_t)tid);
36 }
37
38 /*
39 * Create a thread.
40 *
41 * thread_create() blocks for memory if necessary. It never fails.
42 */
43 /* ARGSUSED */
44 kthread_t *
thread_create(caddr_t stk,size_t stksize,void (* func)(),void * arg,size_t len,struct proc * pp,int state,pri_t pri)45 thread_create(
46 caddr_t stk,
47 size_t stksize,
48 void (*func)(),
49 void *arg,
50 size_t len,
51 struct proc *pp,
52 int state,
53 pri_t pri)
54 {
55 void * (*thr_func)(void *);
56 thread_t newtid;
57 int thr_flags = 0;
58 int rc;
59
60 thr_flags = THR_BOUND;
61
62 switch (state) {
63 case TS_RUN:
64 case TS_ONPROC:
65 break;
66 case TS_STOPPED:
67 thr_flags |= THR_SUSPENDED;
68 break;
69 default:
70 cmn_err(CE_PANIC, "thread_create: invalid state");
71 break;
72 }
73
74 thr_func = (void *(*)(void *))(uintptr_t)func;
75 rc = thr_create(NULL, 0, thr_func, arg, thr_flags, &newtid);
76 if (rc != 0)
77 cmn_err(CE_PANIC, "thread_create failed, rc=%d", rc);
78
79 return ((void *)(uintptr_t)newtid);
80 }
81
82 void
thread_exit(void)83 thread_exit(void)
84 {
85 static thread_t reap_tid;
86 thread_t prev;
87
88 /* reap previous thread exit */
89 prev = atomic_swap_uint(&reap_tid, thr_self());
90 if (prev != 0)
91 (void) thr_join(prev, NULL, NULL); /* joinable thread */
92
93 thr_exit(NULL);
94 }
95
96 void
thread_join(kt_did_t id)97 thread_join(kt_did_t id)
98 {
99 thread_t thr_id;
100
101 thr_id = (thread_t)id;
102 (void) thr_join(thr_id, NULL, NULL);
103 }
104
105 void
tsignal(kthread_t * kt,int sig)106 tsignal(kthread_t *kt, int sig)
107 {
108 thread_t tid = (thread_t)(uintptr_t)kt;
109
110 (void) thr_kill(tid, sig);
111 }
112
113
114 /*ARGSUSED*/
115 kthread_t *
zthread_create(caddr_t stk,size_t stksize,void (* func)(),void * arg,size_t len,pri_t pri)116 zthread_create(
117 caddr_t stk,
118 size_t stksize,
119 void (*func)(),
120 void *arg,
121 size_t len,
122 pri_t pri)
123 {
124 kthread_t *t;
125
126 t = thread_create(stk, stksize, func, arg, len, NULL, TS_RUN, pri);
127
128 return (t);
129 }
130
131 void
zthread_exit(void)132 zthread_exit(void)
133 {
134 thread_exit();
135 /* NOTREACHED */
136 }
137
138 void
tsd_create(uint_t * keyp,void (* destructor)(void *))139 tsd_create(uint_t *keyp, void (*destructor)(void *))
140 {
141 VERIFY0(thr_keycreate(keyp, destructor));
142 }
143
144 /*ARGSUSED*/
145 void
tsd_destroy(uint_t * keyp)146 tsd_destroy(uint_t *keyp)
147 {}
148
149 void *
tsd_get(uint_t key)150 tsd_get(uint_t key)
151 {
152 void *value;
153
154 return (thr_getspecific(key, &value) ? NULL : value);
155 }
156
157 int
tsd_set(uint_t key,void * value)158 tsd_set(uint_t key, void *value)
159 {
160 return (thr_setspecific(key, value));
161 }
162