Lockable.cc revision f3aaec0a97c3584095582719a0149d5e94c06ea2
6a67d144095c31bbafed93cec1619590157335eajvergara/*
6a67d144095c31bbafed93cec1619590157335eajvergara * CDDL HEADER START
6a67d144095c31bbafed93cec1619590157335eajvergara *
6a67d144095c31bbafed93cec1619590157335eajvergara * The contents of this file are subject to the terms of the
6a67d144095c31bbafed93cec1619590157335eajvergara * Common Development and Distribution License (the "License").
6a67d144095c31bbafed93cec1619590157335eajvergara * You may not use this file except in compliance with the License.
6a67d144095c31bbafed93cec1619590157335eajvergara *
6a67d144095c31bbafed93cec1619590157335eajvergara * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6a67d144095c31bbafed93cec1619590157335eajvergara * or http://www.opensolaris.org/os/licensing.
6a67d144095c31bbafed93cec1619590157335eajvergara * See the License for the specific language governing permissions
6a67d144095c31bbafed93cec1619590157335eajvergara * and limitations under the License.
6a67d144095c31bbafed93cec1619590157335eajvergara *
6a67d144095c31bbafed93cec1619590157335eajvergara * When distributing Covered Code, include this CDDL HEADER in each
6a67d144095c31bbafed93cec1619590157335eajvergara * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6a67d144095c31bbafed93cec1619590157335eajvergara * If applicable, add the following below this CDDL HEADER, with the
6a67d144095c31bbafed93cec1619590157335eajvergara * fields enclosed by brackets "[]" replaced with your own identifying
6a67d144095c31bbafed93cec1619590157335eajvergara * information: Portions Copyright [yyyy] [name of copyright owner]
6a67d144095c31bbafed93cec1619590157335eajvergara *
6a67d144095c31bbafed93cec1619590157335eajvergara * CDDL HEADER END
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergara/*
6a67d144095c31bbafed93cec1619590157335eajvergara * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
6a67d144095c31bbafed93cec1619590157335eajvergara * Use is subject to license terms.
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara#include "Lockable.h"
6a67d144095c31bbafed93cec1619590157335eajvergara#include <iostream>
6a67d144095c31bbafed93cec1619590157335eajvergara#include <cstdio>
6a67d144095c31bbafed93cec1619590157335eajvergara#include <cerrno>
6a67d144095c31bbafed93cec1619590157335eajvergara#include <unistd.h>
6a67d144095c31bbafed93cec1619590157335eajvergara#include <cstring>
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergarausing namespace std;
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara#define DEADLOCK_WARNING 10
6a67d144095c31bbafed93cec1619590157335eajvergara#define LOCK_SLEEP 1
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara/**
6a67d144095c31bbafed93cec1619590157335eajvergara * @memo Create a lockable instance and initialize internal locks
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergaraLockable::Lockable() {
6a67d144095c31bbafed93cec1619590157335eajvergara if (pthread_mutex_init(&mutex, NULL)) {
6a67d144095c31bbafed93cec1619590157335eajvergara }
6a67d144095c31bbafed93cec1619590157335eajvergara}
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara/**
6a67d144095c31bbafed93cec1619590157335eajvergara * @memo Free up a lockable instance
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergaraLockable::~Lockable() {
6a67d144095c31bbafed93cec1619590157335eajvergara if (pthread_mutex_destroy(&mutex)) {
6a67d144095c31bbafed93cec1619590157335eajvergara }
6a67d144095c31bbafed93cec1619590157335eajvergara}
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara/**
6a67d144095c31bbafed93cec1619590157335eajvergara * @memo Unlock the instance
6a67d144095c31bbafed93cec1619590157335eajvergara * @precondition This thread must have locked the instance
6a67d144095c31bbafed93cec1619590157335eajvergara * @postcondition The instance will be unlocked
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergaravoid Lockable::unlock() {
6a67d144095c31bbafed93cec1619590157335eajvergara unlock(&mutex);
6a67d144095c31bbafed93cec1619590157335eajvergara}
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara/**
6a67d144095c31bbafed93cec1619590157335eajvergara * @memo Unlock a given mutex lock
6a67d144095c31bbafed93cec1619590157335eajvergara * @precondition The lock must be held by this thread
6a67d144095c31bbafed93cec1619590157335eajvergara * @postcondition The lock will be released
6a67d144095c31bbafed93cec1619590157335eajvergara * @param myMutex The lock to unlock
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergaravoid Lockable::unlock(pthread_mutex_t *myMutex) {
6a67d144095c31bbafed93cec1619590157335eajvergara pthread_mutex_unlock(myMutex);
6a67d144095c31bbafed93cec1619590157335eajvergara}
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara/**
6a67d144095c31bbafed93cec1619590157335eajvergara * @memo Lock the instance
6a67d144095c31bbafed93cec1619590157335eajvergara * @postcondition The lock will be held by this thread.
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergaravoid Lockable::lock() {
6a67d144095c31bbafed93cec1619590157335eajvergara lock(&mutex);
6a67d144095c31bbafed93cec1619590157335eajvergara}
6a67d144095c31bbafed93cec1619590157335eajvergara
6a67d144095c31bbafed93cec1619590157335eajvergara/**
6a67d144095c31bbafed93cec1619590157335eajvergara * @memo Lock the given mutex lock
6a67d144095c31bbafed93cec1619590157335eajvergara * @postcondition The lock will be held by this thread
6a67d144095c31bbafed93cec1619590157335eajvergara * @param myMutex The mutex lock to take
6a67d144095c31bbafed93cec1619590157335eajvergara */
6a67d144095c31bbafed93cec1619590157335eajvergaravoid Lockable::lock(pthread_mutex_t *myMutex) {
6a67d144095c31bbafed93cec1619590157335eajvergara int status;
6a67d144095c31bbafed93cec1619590157335eajvergara int loop = 0;
6a67d144095c31bbafed93cec1619590157335eajvergara do {
6a67d144095c31bbafed93cec1619590157335eajvergara loop++;
6a67d144095c31bbafed93cec1619590157335eajvergara status = pthread_mutex_trylock(myMutex);
6a67d144095c31bbafed93cec1619590157335eajvergara if (status) {
6a67d144095c31bbafed93cec1619590157335eajvergara switch (pthread_mutex_trylock(myMutex)) {
6a67d144095c31bbafed93cec1619590157335eajvergara case EFAULT:
6a67d144095c31bbafed93cec1619590157335eajvergara cerr << "Lock failed: Fault" << endl;
6a67d144095c31bbafed93cec1619590157335eajvergara break;
6a67d144095c31bbafed93cec1619590157335eajvergara case EINVAL:
6a67d144095c31bbafed93cec1619590157335eajvergara cerr << "Lock failed: Invalid" << endl;
6a67d144095c31bbafed93cec1619590157335eajvergara break;
6a67d144095c31bbafed93cec1619590157335eajvergara case EBUSY:
6a67d144095c31bbafed93cec1619590157335eajvergara if (loop > DEADLOCK_WARNING) {
6a67d144095c31bbafed93cec1619590157335eajvergara cerr << "Lock failed: Deadlock" << endl;
6a67d144095c31bbafed93cec1619590157335eajvergara }
6a67d144095c31bbafed93cec1619590157335eajvergara break;
6a67d144095c31bbafed93cec1619590157335eajvergara case EOWNERDEAD:
6a67d144095c31bbafed93cec1619590157335eajvergara cerr << "Lock failed: Owner died" << endl;
6a67d144095c31bbafed93cec1619590157335eajvergara break;
6a67d144095c31bbafed93cec1619590157335eajvergara case ELOCKUNMAPPED:
6a67d144095c31bbafed93cec1619590157335eajvergara cerr << "Lock failed: Unmapped" << endl;
6a67d144095c31bbafed93cec1619590157335eajvergara break;
6a67d144095c31bbafed93cec1619590157335eajvergara case ENOTRECOVERABLE:
6a67d144095c31bbafed93cec1619590157335eajvergara cerr << "Lock failed: not recoverable" << endl;
6a67d144095c31bbafed93cec1619590157335eajvergara default:
6a67d144095c31bbafed93cec1619590157335eajvergara if (loop > DEADLOCK_WARNING) {
6a67d144095c31bbafed93cec1619590157335eajvergara cerr << "Lock failed: " <<strerror(status) << endl;
6a67d144095c31bbafed93cec1619590157335eajvergara break;
6a67d144095c31bbafed93cec1619590157335eajvergara }
6a67d144095c31bbafed93cec1619590157335eajvergara }
6a67d144095c31bbafed93cec1619590157335eajvergara } else {
6a67d144095c31bbafed93cec1619590157335eajvergara break; // Lock taken succesfully
6a67d144095c31bbafed93cec1619590157335eajvergara }
6a67d144095c31bbafed93cec1619590157335eajvergara sleep(LOCK_SLEEP);
6a67d144095c31bbafed93cec1619590157335eajvergara } while (status);
6a67d144095c31bbafed93cec1619590157335eajvergara}
6a67d144095c31bbafed93cec1619590157335eajvergara