1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
.\"
.\" The contents of this file are subject to the terms of the
.\" Common Development and Distribution License (the "License").
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
.\" or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
.\" When distributing Covered Code, include this CDDL HEADER in each
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
.\" If applicable, add the following below this CDDL HEADER, with the
.\" fields enclosed by brackets "[]" replaced with your own identifying
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.\"
.\"
.\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved
.\" Copyright 2018 Nexenta Systems, Inc.
.\"
.Dd July 30, 2018
.Dt SEMAPHORE 9F
.Os
.Sh NAME
.Nm semaphore ,
.Nm sema_init ,
.Nm sema_destroy ,
.Nm sema_p ,
.Nm sema_p_sig ,
.Nm sema_v ,
.Nm sema_tryp
.Nd semaphore functions
.Sh SYNOPSIS
.In sys/ksynch.h
.Ft void
.Fo sema_init
.Fa "ksema_t *sp"
.Fa "uint_t val"
.Fa "char *name"
.Fa "ksema_type_t type"
.Fa "void *arg"
.Fc
.Ft void
.Fo sema_destroy
.Fa "ksema_t *sp"
.Fc
.Ft void
.Fo sema_p
.Fa "ksema_t *sp"
.Fc
.Ft void
.Fo sema_v
.Fa "ksema_t *sp"
.Fc
.Ft int
.Fo sema_p_sig
.Fa "ksema_t *sp"
.Fc
.Ft int
.Fo sema_tryp
.Fa "ksema_t *sp"
.Fc
.Sh INTERFACE LEVEL
illumos DDI specific (illumos DDI).
.Sh PARAMETERS
.Bl -tag -width Ds
.It Fa sp
A pointer to a semaphore, type
.Vt ksema_t .
.It Fa val
Initial value for semaphore.
.It Fa name
Descriptive string.
This is obsolete and should be
.Dv NULL .
.Po Non- Ns
.Dv NULL
strings are legal, but they are a waste of kernel memory.
.Pc
.It Fa type
Variant type of the semaphore.
Currently, only
.Dv SEMA_DRIVER
is supported.
.It Fa arg
Type-specific argument; should be
.Dv NULL .
.El
.Sh DESCRIPTION
These functions implement counting semaphores as described by Dijkstra.
A semaphore has a value which is atomically decremented by
.Fn sema_p
and atomically incremented by
.Fn sema_v .
The value must always be greater than or equal to zero.
If
.Fn sema_p
is called and the value is zero, the calling thread is blocked until another
thread performs a
.Fn sema_v
operation on the semaphore.
.Pp
Semaphores are initialized by calling
.Fn sema_init .
The argument,
.Fa val ,
gives the initial value for the semaphore.
The semaphore storage is provided by the caller but more may be dynamically
allocated, if necessary, by
.Fn sema_init .
For this reason,
.Fn sema_destroy
should be called before deallocating the storage containing the semaphore.
.Pp
The
.Fn sema_p_sig
function decrements the semaphore, as does
.Fn sema_p .
However, if the semaphore value is zero,
.Fn sema_p_sig
will return without decrementing the value if a signal
.Po that is, from
.Xr kill 2
.Pc
is pending for the thread.
.Pp
The
.Fn sema_tryp
function will decrement the semaphore value only if it is greater than zero, and
will not block.
.Sh CONTEXT
These functions can be called from user, interrupt, or kernel context, except
for
.Fn sema_init
and
.Fn sema_destroy ,
which can be called from user or kernel context only.
None of these functions can be called from a high-level interrupt context.
In most cases,
.Fn sema_v
and
.Fn sema_p
should not be called from any interrupt context.
.Pp
If
.Fn sema_p
is used from interrupt context, lower-priority interrupts will not be serviced
during the wait.
This means that if the thread that will eventually perform the
.Fn sema_v
becomes blocked on anything that requires the lower-priority interrupt, the
system will hang.
.Pp
For example, the thread that will perform the
.Fn sema_v
may need to first allocate memory.
This memory allocation may require waiting for paging I/O to complete, which may
require a lower-priority disk or network interrupt to be serviced.
In general, situations like this are hard to predict, so it is advisable to
avoid waiting on semaphores or condition variables in an interrupt context.
.Pp
Similar to many other synchronization mechanisms, semaphores should not be used
in any code path that requires synchronization while handling system panic, at
which time many of the semaphore operations become no-ops.
.Sh RETURN VALUES
.Bl -tag -width Ds
.It Li 0
.Fn sema_tryp
could not decrement the semaphore value because it was zero.
.It Li 1
.Fn sema_p_sig
was not able to decrement the semaphore value and detected a pending signal.
.El
.Sh SEE ALSO
.Xr kill 2 ,
.Xr condvar 9F ,
.Xr mutex 9F
.Pp
.Em Writing Device Drivers
|