4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 #include "metaGlobal.h"
31 * The list and the list lock are global for two external uses:
32 * 1) C_CloseAllSessions need to close the head (repeatedly,
33 * until no more sessions exist).
34 * 2) meta_object_find_by_handle needs to walk all sessions,
35 * searching each session object list for matching objects.
37 pthread_rwlock_t meta_sessionlist_lock
;
38 meta_session_t
*meta_sessionlist_head
;
41 * The following 2 variables are used for tracking the number of
42 * sessions and number of rw sessios that are currently open
44 * They are being manipulated in the metaSession.c file, and being
45 * referenced in the metaSlotToken.c file
47 CK_ULONG num_meta_sessions
;
48 CK_ULONG num_rw_meta_sessions
;
52 static pthread_rwlock_t meta_sessionclose_lock
;
56 * meta_sessionManager_initialize
58 * Called from meta_Initialize. Initializes all the variables used
59 * by the session manager.
62 meta_sessionManager_initialize()
65 if (pthread_rwlock_init(&meta_sessionlist_lock
, NULL
) != 0) {
66 return (CKR_FUNCTION_FAILED
);
69 if (pthread_rwlock_init(&meta_sessionclose_lock
, NULL
) != 0) {
70 (void) pthread_rwlock_destroy(&meta_sessionlist_lock
);
71 return (CKR_FUNCTION_FAILED
);
74 meta_sessionlist_head
= NULL
;
75 num_meta_sessions
= 0;
76 num_rw_meta_sessions
= 0;
82 * meta_sessionManager_finalize
84 * Close all sessions, and destroy all the locks
87 meta_sessionManager_finalize()
90 * Close any remaining metasessions, can just simply call
91 * meta_CloseAllSessions. The METASLOT_SLOTID argument is
92 * not used, but need to be passed in.
94 (void) meta_CloseAllSessions(METASLOT_SLOTID
);
96 (void) pthread_rwlock_destroy(&meta_sessionclose_lock
);
98 (void) pthread_rwlock_destroy(&meta_sessionlist_lock
);
102 * meta_handle2session
104 * Convert a CK_SESSION_HANDLE to the corresponding metasession. If
105 * successful, a write-lock on the session will be held to indicate
106 * that it's in use. Call REFRELEASE() when finished.
110 meta_handle2session(CK_SESSION_HANDLE hSession
, meta_session_t
**session
)
112 meta_session_t
*tmp_session
= (meta_session_t
*)(hSession
);
114 /* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */
115 if (tmp_session
== NULL
||
116 tmp_session
->magic_marker
!= METASLOT_SESSION_MAGIC
) {
117 return (CKR_SESSION_HANDLE_INVALID
);
121 * sessions can only be used by a single thread at a time.
122 * So, we need to get a write-lock.
124 (void) pthread_rwlock_wrlock(&tmp_session
->session_lock
);
126 /* Make sure this session is not in the process of being deleted */
127 (void) pthread_mutex_lock(&tmp_session
->isClosingSession_lock
);
128 if (tmp_session
->isClosingSession
) {
129 (void) pthread_mutex_unlock(
130 &tmp_session
->isClosingSession_lock
);
131 (void) pthread_rwlock_unlock(&tmp_session
->session_lock
);
132 return (CKR_SESSION_HANDLE_INVALID
);
134 (void) pthread_mutex_unlock(&tmp_session
->isClosingSession_lock
);
136 *session
= tmp_session
;
145 meta_session_alloc(meta_session_t
**session
)
147 meta_session_t
*new_session
;
149 /* Allocate memory for the session. */
150 new_session
= calloc(1, sizeof (meta_session_t
));
151 if (new_session
== NULL
)
152 return (CKR_HOST_MEMORY
);
154 (new_session
->mech_support_info
).supporting_slots
155 = malloc(meta_slotManager_get_slotcount() * sizeof (mechinfo_t
*));
156 if ((new_session
->mech_support_info
).supporting_slots
== NULL
) {
158 return (CKR_HOST_MEMORY
);
160 (new_session
->mech_support_info
).num_supporting_slots
= 0;
162 new_session
->magic_marker
= METASLOT_SESSION_MAGIC
;
163 (void) pthread_rwlock_init(&new_session
->session_lock
, NULL
);
164 (void) pthread_mutex_init(&new_session
->isClosingSession_lock
, NULL
);
165 (void) pthread_rwlock_init(&new_session
->object_list_lock
, NULL
);
167 *session
= new_session
;
173 * meta_session_activate
175 * Create and add a session to the list of active meta sessions.
178 meta_session_activate(meta_session_t
*session
)
182 /* Add session to the list of sessions. */
183 (void) pthread_rwlock_wrlock(&meta_sessionlist_lock
);
184 INSERT_INTO_LIST(meta_sessionlist_head
, session
);
185 (void) pthread_rwlock_unlock(&meta_sessionlist_lock
);
191 * meta_session_deactivate
196 meta_session_deactivate(meta_session_t
*session
,
197 boolean_t have_sessionlist_lock
)
199 boolean_t isLastSession
= B_FALSE
;
200 meta_object_t
*object
;
202 /* Safely resolve attempts of concurrent-close */
203 (void) pthread_mutex_lock(&session
->isClosingSession_lock
);
204 if (session
->isClosingSession
) {
205 /* Lost a delete race. */
206 (void) pthread_mutex_unlock(&session
->isClosingSession_lock
);
208 return (CKR_SESSION_HANDLE_INVALID
);
210 session
->isClosingSession
= B_TRUE
;
211 session
->magic_marker
= METASLOT_SESSION_BADMAGIC
;
212 (void) pthread_mutex_unlock(&session
->isClosingSession_lock
);
215 * Remove session from the session list. Once removed, it will not
216 * be possible for another thread to begin using the session.
218 (void) pthread_rwlock_wrlock(&meta_sessionclose_lock
);
219 if (!have_sessionlist_lock
) {
220 (void) pthread_rwlock_wrlock(&meta_sessionlist_lock
);
223 REMOVE_FROM_LIST(meta_sessionlist_head
, session
);
224 if (meta_sessionlist_head
== NULL
) {
225 isLastSession
= B_TRUE
;
227 if (!have_sessionlist_lock
) {
228 (void) pthread_rwlock_unlock(&meta_sessionlist_lock
);
230 (void) pthread_rwlock_unlock(&meta_sessionclose_lock
);
232 (void) pthread_rwlock_unlock(&session
->session_lock
);
234 /* Cleanup any in-progress operations. */
235 if (session
->op1
.type
!= 0) {
236 meta_operation_cleanup(session
, session
->op1
.type
, FALSE
);
239 if (session
->op1
.session
!= NULL
) {
240 meta_release_slot_session(session
->op1
.session
);
241 session
->op1
.session
= NULL
;
244 /* Remove all the session metaobjects created in this session. */
245 /* Basically, emulate C_DestroyObject, including safety h2s */
246 while ((object
= session
->object_list_head
) != NULL
) {
249 rv
= meta_handle2object((CK_OBJECT_HANDLE
)object
, &object
);
251 /* Can only happen if someone else just closed it. */
255 rv
= meta_object_deactivate(object
, B_FALSE
, B_TRUE
);
260 rv
= meta_object_dealloc(NULL
, object
, B_FALSE
);
267 if ((isLastSession
) && (metaslot_logged_in())) {
268 slot_session_t
*slotsessp
;
271 rv
= meta_get_slot_session(get_keystore_slotnum(), &slotsessp
,
272 session
->session_flags
);
275 rv
= FUNCLIST(slotsessp
->fw_st_id
)->C_Logout(
276 slotsessp
->hSession
);
278 meta_release_slot_session(slotsessp
);
280 /* if C_Logout fails, just ignore the error */
281 metaslot_set_logged_in_flag(B_FALSE
);
286 /* need to deactivate all the PRIVATE token objects */
287 rv
= meta_token_object_deactivate(PRIVATE_TOKEN
);
298 * meta_session_dealloc
300 * Release the resources held by a metasession. If the session has been
301 * activated, it must be deactivated first.
304 meta_session_dealloc(meta_session_t
*session
)
306 if ((session
->find_objs_info
).matched_objs
) {
307 free((session
->find_objs_info
).matched_objs
);
310 free((session
->mech_support_info
).supporting_slots
);
313 * If there were active operations, cleanup the slot session so that
314 * it can be reused (otherwise provider might complain that an
315 * operation is active).
317 if (session
->op1
.type
!= 0)
318 meta_operation_cleanup(session
, session
->op1
.type
, FALSE
);
320 /* Final object cleanup. */
321 (void) pthread_rwlock_destroy(&session
->session_lock
);
322 (void) pthread_mutex_destroy(&session
->isClosingSession_lock
);
323 (void) pthread_rwlock_destroy(&session
->object_list_lock
);
325 meta_session_delay_free(session
);
329 * This function adds the to-be-freed meta session to a linked list.
330 * When the number of sessions queued in the linked list reaches the
331 * maximum threshold MAX_SESSION_TO_BE_FREED, it will free the first
332 * session (FIFO) in the list.
335 meta_session_delay_free(meta_session_t
*sp
)
339 (void) pthread_mutex_lock(&ses_delay_freed
.ses_to_be_free_mutex
);
341 /* Add the newly deleted session at the end of the list */
343 if (ses_delay_freed
.first
== NULL
) {
344 ses_delay_freed
.last
= sp
;
345 ses_delay_freed
.first
= sp
;
347 ses_delay_freed
.last
->next
= sp
;
348 ses_delay_freed
.last
= sp
;
351 if (++ses_delay_freed
.count
>= MAX_SESSION_TO_BE_FREED
) {
353 * Free the first session in the list only if
354 * the total count reaches maximum threshold.
356 ses_delay_freed
.count
--;
357 tmp
= ses_delay_freed
.first
->next
;
358 free(ses_delay_freed
.first
);
359 ses_delay_freed
.first
= tmp
;
361 (void) pthread_mutex_unlock(&ses_delay_freed
.ses_to_be_free_mutex
);