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