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