xref: /illumos-gate/usr/src/lib/sun_fc/common/Lockable.cc (revision 1f5207b7604fb44407eb4342aff613f7c4508508)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 #include "Lockable.h"
28 #include <iostream>
29 #include <cstdio>
30 #include <cerrno>
31 #include <unistd.h>
32 #include <cstring>
33 
34 using namespace std;
35 
36 #define	    DEADLOCK_WARNING 10
37 #define	    LOCK_SLEEP 1
38 
39 /**
40  * @memo	    Create a lockable instance and initialize internal locks
41  */
42 Lockable::Lockable() {
43 	if (pthread_mutex_init(&mutex, NULL)) {
44 	}
45 }
46 
47 /**
48  * @memo	    Free up a lockable instance
49  */
50 Lockable::~Lockable() {
51 	if (pthread_mutex_destroy(&mutex)) {
52 	}
53 }
54 
55 /**
56  * @memo	    Unlock the instance
57  * @precondition    This thread must have locked the instance
58  * @postcondition   The instance will be unlocked
59  */
60 void Lockable::unlock() {
61 	unlock(&mutex);
62 }
63 
64 /**
65  * @memo	    Unlock a given mutex lock
66  * @precondition    The lock must be held by this thread
67  * @postcondition   The lock will be released
68  * @param	    myMutex The lock to unlock
69  */
70 void Lockable::unlock(pthread_mutex_t *myMutex) {
71 	pthread_mutex_unlock(myMutex);
72 }
73 
74 /**
75  * @memo	    Lock the instance
76  * @postcondition   The lock will be held by this thread.
77  */
78 void Lockable::lock() {
79 	lock(&mutex);
80 }
81 
82 /**
83  * @memo	    Lock the given mutex lock
84  * @postcondition   The lock will be held by this thread
85  * @param	    myMutex The mutex lock to take
86  */
87 void Lockable::lock(pthread_mutex_t *myMutex) {
88 	int status;
89 	int loop = 0;
90 	do {
91 	    loop++;
92 	    status = pthread_mutex_trylock(myMutex);
93 	    if (status) {
94 		switch (pthread_mutex_trylock(myMutex)) {
95 		case EFAULT:
96 		    cerr << "Lock failed: Fault" << endl;
97 		    break;
98 		case EINVAL:
99 		    cerr << "Lock failed: Invalid" << endl;
100 		    break;
101 		case EBUSY:
102 		    if (loop > DEADLOCK_WARNING) {
103 			cerr << "Lock failed: Deadlock" << endl;
104 		    }
105 		    break;
106 		case EOWNERDEAD:
107 		    cerr << "Lock failed: Owner died" << endl;
108 		    break;
109 		case ELOCKUNMAPPED:
110 		    cerr << "Lock failed: Unmapped" << endl;
111 		    break;
112 		case ENOTRECOVERABLE:
113 		    cerr << "Lock failed: not recoverable" << endl;
114 		default:
115 		    if (loop > DEADLOCK_WARNING) {
116 			cerr << "Lock failed: " <<strerror(status) << endl;
117 			break;
118 		    }
119 		}
120 	    } else {
121 		break; // Lock taken succesfully
122 	    }
123 	    sleep(LOCK_SLEEP);
124 	} while (status);
125 }
126