#ifndef RTAPI_MUTEX_H #define RTAPI_MUTEX_H // Copyright 2004-2015 Jeff Epler, John Kasunich, Paul Corner, and other // authors // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. /*********************************************************************** * LIGHTWEIGHT MUTEX FUNCTIONS * ************************************************************************/ #if defined(__KERNEL__) #include /* for blocking when needed */ #else #include /* for blocking when needed */ #endif #include "rtapi_bitops.h" /* atomic bit ops for lightweight mutex */ typedef unsigned long rtapi_mutex_t; /** These three functions provide a very simple way to do mutual exclusion around shared resources. They do _not_ replace semaphores, and can result in significant slowdowns if contention is severe. However, unlike semaphores they can be used from both user and kernel space. The 'try' and 'give' functions are non- blocking, and can be used anywhere. The 'get' function blocks if the mutex is already taken, and can only be used in user space or the init code of a realtime module, _not_ in realtime code. */ /** 'rtapi_mutex_give()' releases the mutex pointed to by 'mutex'. The release is unconditional, even if the caller doesn't have the mutex, it will be released. */ static __inline__ void rtapi_mutex_give(unsigned long *mutex) { test_and_clear_bit(0, mutex); } /** 'rtapi_mutex_try()' makes a non-blocking attempt to get the mutex pointed to by 'mutex'. If the mutex was available, it returns 0 and the mutex is no longer available, since the caller now has it. If the mutex is not available, it returns a non-zero value to indicate that someone else has the mutex. The programer is responsible for "doing the right thing" when it returns non-zero. "Doing the right thing" almost certainly means doing something that will yield the CPU, so that whatever other process has the mutex gets a chance to release it. */ static __inline__ int rtapi_mutex_try(unsigned long *mutex) { return test_and_set_bit(0, mutex); } /** 'rtapi_mutex_get()' gets the mutex pointed to by 'mutex', blocking if the mutex is not available. Because of this, calling it from a realtime task is a "very bad" thing to do. */ static __inline__ void rtapi_mutex_get(unsigned long *mutex) { while (test_and_set_bit(0, mutex)) { #if defined(__KERNEL__) schedule(); #else sched_yield(); #endif } } #endif