1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24*8e0c8248SAndrew Stormont  *
25*8e0c8248SAndrew Stormont  * Copyright 2019 RackTop Systems.
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte #include "Lockable.h"
30fcf3ce44SJohn Forte #include <iostream>
31fcf3ce44SJohn Forte #include <cstdio>
32fcf3ce44SJohn Forte #include <cerrno>
33fcf3ce44SJohn Forte #include <unistd.h>
34f3aaec0aSRichard Lowe #include <cstring>
35fcf3ce44SJohn Forte 
36fcf3ce44SJohn Forte using namespace std;
37fcf3ce44SJohn Forte 
38fcf3ce44SJohn Forte #define	    DEADLOCK_WARNING 10
39fcf3ce44SJohn Forte #define	    LOCK_SLEEP 1
40fcf3ce44SJohn Forte 
41fcf3ce44SJohn Forte /**
42fcf3ce44SJohn Forte  * @memo	    Create a lockable instance and initialize internal locks
43fcf3ce44SJohn Forte  */
Lockable()44fcf3ce44SJohn Forte Lockable::Lockable() {
45fcf3ce44SJohn Forte 	if (pthread_mutex_init(&mutex, NULL)) {
46fcf3ce44SJohn Forte 	}
47fcf3ce44SJohn Forte }
48fcf3ce44SJohn Forte 
49fcf3ce44SJohn Forte /**
50fcf3ce44SJohn Forte  * @memo	    Free up a lockable instance
51fcf3ce44SJohn Forte  */
~Lockable()52fcf3ce44SJohn Forte Lockable::~Lockable() {
53fcf3ce44SJohn Forte 	if (pthread_mutex_destroy(&mutex)) {
54fcf3ce44SJohn Forte 	}
55fcf3ce44SJohn Forte }
56fcf3ce44SJohn Forte 
57fcf3ce44SJohn Forte /**
58fcf3ce44SJohn Forte  * @memo	    Unlock the instance
59fcf3ce44SJohn Forte  * @precondition    This thread must have locked the instance
60fcf3ce44SJohn Forte  * @postcondition   The instance will be unlocked
61fcf3ce44SJohn Forte  */
unlock()62fcf3ce44SJohn Forte void Lockable::unlock() {
63fcf3ce44SJohn Forte 	unlock(&mutex);
64fcf3ce44SJohn Forte }
65fcf3ce44SJohn Forte 
66fcf3ce44SJohn Forte /**
67fcf3ce44SJohn Forte  * @memo	    Unlock a given mutex lock
68fcf3ce44SJohn Forte  * @precondition    The lock must be held by this thread
69fcf3ce44SJohn Forte  * @postcondition   The lock will be released
70fcf3ce44SJohn Forte  * @param	    myMutex The lock to unlock
71fcf3ce44SJohn Forte  */
unlock(pthread_mutex_t * myMutex)72fcf3ce44SJohn Forte void Lockable::unlock(pthread_mutex_t *myMutex) {
73fcf3ce44SJohn Forte 	pthread_mutex_unlock(myMutex);
74fcf3ce44SJohn Forte }
75fcf3ce44SJohn Forte 
76fcf3ce44SJohn Forte /**
77fcf3ce44SJohn Forte  * @memo	    Lock the instance
78fcf3ce44SJohn Forte  * @postcondition   The lock will be held by this thread.
79fcf3ce44SJohn Forte  */
lock()80fcf3ce44SJohn Forte void Lockable::lock() {
81fcf3ce44SJohn Forte 	lock(&mutex);
82fcf3ce44SJohn Forte }
83fcf3ce44SJohn Forte 
84fcf3ce44SJohn Forte /**
85fcf3ce44SJohn Forte  * @memo	    Lock the given mutex lock
86fcf3ce44SJohn Forte  * @postcondition   The lock will be held by this thread
87fcf3ce44SJohn Forte  * @param	    myMutex The mutex lock to take
88fcf3ce44SJohn Forte  */
lock(pthread_mutex_t * myMutex)89fcf3ce44SJohn Forte void Lockable::lock(pthread_mutex_t *myMutex) {
90fcf3ce44SJohn Forte 	int status;
91fcf3ce44SJohn Forte 	int loop = 0;
92fcf3ce44SJohn Forte 	do {
93fcf3ce44SJohn Forte 	    loop++;
94fcf3ce44SJohn Forte 	    status = pthread_mutex_trylock(myMutex);
95fcf3ce44SJohn Forte 	    if (status) {
96fcf3ce44SJohn Forte 		switch (pthread_mutex_trylock(myMutex)) {
97fcf3ce44SJohn Forte 		case EFAULT:
98fcf3ce44SJohn Forte 		    cerr << "Lock failed: Fault" << endl;
99fcf3ce44SJohn Forte 		    break;
100fcf3ce44SJohn Forte 		case EINVAL:
101fcf3ce44SJohn Forte 		    cerr << "Lock failed: Invalid" << endl;
102fcf3ce44SJohn Forte 		    break;
103fcf3ce44SJohn Forte 		case EBUSY:
104fcf3ce44SJohn Forte 		    if (loop > DEADLOCK_WARNING) {
105fcf3ce44SJohn Forte 			cerr << "Lock failed: Deadlock" << endl;
106fcf3ce44SJohn Forte 		    }
107fcf3ce44SJohn Forte 		    break;
108fcf3ce44SJohn Forte 		case EOWNERDEAD:
109fcf3ce44SJohn Forte 		    cerr << "Lock failed: Owner died" << endl;
110fcf3ce44SJohn Forte 		    break;
111fcf3ce44SJohn Forte 		case ELOCKUNMAPPED:
112fcf3ce44SJohn Forte 		    cerr << "Lock failed: Unmapped" << endl;
113fcf3ce44SJohn Forte 		    break;
114fcf3ce44SJohn Forte 		case ENOTRECOVERABLE:
115fcf3ce44SJohn Forte 		    cerr << "Lock failed: not recoverable" << endl;
116*8e0c8248SAndrew Stormont 		    /* FALLTHROUGH */
117fcf3ce44SJohn Forte 		default:
118fcf3ce44SJohn Forte 		    if (loop > DEADLOCK_WARNING) {
119fcf3ce44SJohn Forte 			cerr << "Lock failed: " <<strerror(status) << endl;
120fcf3ce44SJohn Forte 			break;
121fcf3ce44SJohn Forte 		    }
122fcf3ce44SJohn Forte 		}
123fcf3ce44SJohn Forte 	    } else {
124fcf3ce44SJohn Forte 		break; // Lock taken succesfully
125fcf3ce44SJohn Forte 	    }
126fcf3ce44SJohn Forte 	    sleep(LOCK_SLEEP);
127fcf3ce44SJohn Forte 	} while (status);
128fcf3ce44SJohn Forte }
129