forked from niftich/magenta
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[magenta][locks] Add spin_lock_t helper classes.
Add simple helper classes for spinlocks which allow C++ to use common auto initialization and AutoLock patterns. Change-Id: I32d1c3e3a119d62357a74cb5dd796bfd20db8fcd
- Loading branch information
Showing
6 changed files
with
244 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ MODULE_DEPS := \ | |
lib/libc \ | ||
lib/debug \ | ||
lib/heap \ | ||
lib/mxtl \ | ||
|
||
|
||
MODULE_SRCS := \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#pragma once | ||
#ifdef __cplusplus | ||
|
||
#include <mxtl/mutex.h> | ||
|
||
// Introduce preprocessor definitions for the underlying mutex data type and the | ||
// lock/unlock operations based on whether this code is being used in the kernel | ||
// or in user-mode. Also, if this is the user-mode AutoLock implementation, | ||
// introduce it into the mxtl namespace. Otherwise, add it to the global | ||
// namespace, and create an alias in mxtl. | ||
#ifdef _KERNEL | ||
#define mxtl_mutex_t mutex_t | ||
#define mxtl_mutex_acquire mutex_acquire | ||
#define mxtl_mutex_release mutex_release | ||
#else | ||
namespace mxtl { | ||
#define mxtl_mutex_t mtx_t | ||
#define mxtl_mutex_acquire mtx_lock | ||
#define mxtl_mutex_release mtx_unlock | ||
#endif | ||
|
||
class AutoLock { | ||
public: | ||
explicit AutoLock(mxtl_mutex_t* mutex) | ||
: mutex_(mutex) { | ||
mxtl_mutex_acquire(mutex_); | ||
} | ||
|
||
explicit AutoLock(mxtl_mutex_t& mutex) | ||
: AutoLock(&mutex) {} | ||
|
||
explicit AutoLock(Mutex& mutex) | ||
: AutoLock(mutex.GetInternal()) {} | ||
|
||
explicit AutoLock(Mutex* mutex) | ||
: AutoLock(mutex->GetInternal()) {} | ||
|
||
~AutoLock() { | ||
release(); | ||
} | ||
|
||
// early release the mutex before the object goes out of scope | ||
void release() { | ||
if (mutex_) { | ||
mxtl_mutex_release(mutex_); | ||
mutex_ = nullptr; | ||
} | ||
} | ||
|
||
// suppress default constructors | ||
AutoLock(const AutoLock& am) = delete; | ||
AutoLock& operator=(const AutoLock& am) = delete; | ||
AutoLock(AutoLock&& c) = delete; | ||
AutoLock& operator=(AutoLock&& c) = delete; | ||
|
||
private: | ||
mxtl_mutex_t* mutex_; | ||
}; | ||
|
||
#if _KERNEL | ||
namespace mxtl { using AutoLock = ::AutoLock; } | ||
#else | ||
} // namespace mxtl | ||
#endif | ||
|
||
// Remove the underlying mutex preprocessor definitions. Do not let them leak | ||
// out into the world at large. | ||
#undef mxtl_mutex_t | ||
#undef mxtl_mutex_acquire | ||
#undef mxtl_mutex_release | ||
|
||
#endif // #ifdef __cplusplus |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#pragma once | ||
|
||
#ifdef __cplusplus | ||
|
||
// Notes about class Mutex | ||
// | ||
// Mutex is a C++ helper class intended to wrap a mutex-style synchronization | ||
// primative and provide a common interface for library code which is intended | ||
// to be shared between user-mode and kernel code. It is also responsible for | ||
// automatically initializing and destroying the internal mutex object. | ||
// | ||
// For user-mode code, Mutex is defined in the mxtl namespace. For kernel mode | ||
// code, to maintain compatibility with existing code, Mutex is introduced into | ||
// the global namespace, and a using alias is introduced in the mxtl namespace. | ||
// The implication of this is that shared code should always use mxtl::Mutex | ||
// instead of the global Mutex | ||
#if _KERNEL | ||
#include <kernel/mutex.h> | ||
#include <sys/types.h> | ||
|
||
class Mutex { | ||
public: | ||
constexpr Mutex() : mutex_(MUTEX_INITIAL_VALUE(mutex_)) { } | ||
~Mutex() { mutex_destroy(&mutex_); } | ||
void Acquire() { mutex_acquire(&mutex_); } | ||
void Release() { mutex_release(&mutex_); } | ||
|
||
status_t AcquireTimeout(lk_time_t timeout) { | ||
return mutex_acquire_timeout(&mutex_, timeout); | ||
} | ||
|
||
bool IsHeld() const { | ||
return is_mutex_held(&mutex_); | ||
} | ||
|
||
mutex_t* GetInternal() { | ||
return &mutex_; | ||
} | ||
|
||
// suppress default constructors | ||
Mutex(const Mutex& am) = delete; | ||
Mutex& operator=(const Mutex& am) = delete; | ||
Mutex(Mutex&& c) = delete; | ||
Mutex& operator=(Mutex&& c) = delete; | ||
private: | ||
mutex_t mutex_; | ||
}; | ||
|
||
namespace mxtl { using Mutex = ::Mutex; } | ||
|
||
#else // if _KERNEL | ||
|
||
#include <magenta/types.h> | ||
#include <threads.h> | ||
|
||
namespace mxtl { | ||
|
||
class Mutex { | ||
public: | ||
constexpr Mutex() : mutex_(MTX_INIT) { } | ||
~Mutex() { mtx_destroy(&mutex_); } | ||
void Acquire() { mtx_lock(&mutex_); } | ||
void Release() { mtx_unlock(&mutex_); } | ||
|
||
/* AcquireTimeout is not supported by the Mutex wrapper in user-mode. | ||
* Implementation would require creation of a C11 mtx_timed mutex, a | ||
* decision normally made at construction time. */ | ||
|
||
/* IsHeld is not supported by the Mutex wrapper in user-mode as C11 mtx_t | ||
* instances do not support a direct IsHeld style check. A possible | ||
* implementation could be built out of mtx_trylock, but would require | ||
* either relaxing away the const constraint on the method signature, or | ||
* flagging the mutex_ member as mutable */ | ||
|
||
mtx_t* GetInternal() { | ||
return &mutex_; | ||
} | ||
|
||
// suppress default constructors | ||
Mutex(const Mutex& am) = delete; | ||
Mutex& operator=(const Mutex& am) = delete; | ||
Mutex(Mutex&& c) = delete; | ||
Mutex& operator=(Mutex&& c) = delete; | ||
private: | ||
mtx_t mutex_; | ||
}; | ||
|
||
} | ||
|
||
#endif // if _KERNEL | ||
#endif // ifdef __cplusplus |