Skip to content

Fix #8639 - Concurrency problem in remote profiler communication mechanism using boost/interprocess #8645

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/common/classes/Spinlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2025 Adriano dos Santos Fernandes <adrianosf@gmail.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/

#ifndef CLASSES_SPINLOCK_H
#define CLASSES_SPINLOCK_H

#include <atomic>
#include <thread>

namespace Firebird {


// Spinlock implementation that can be used in shared memory.
// Based in example found in https://en.cppreference.com/w/cpp/atomic/atomic_flag.html
// Compatible with std::lock_guard, std::scoped_lock and std::unique_lock.
class SpinLock
{
std::atomic_flag atomicFlag = ATOMIC_FLAG_INIT;

public:
void lock() noexcept
{
while (atomicFlag.test_and_set(std::memory_order_acquire))
{
#if defined(__cpp_lib_atomic_wait) && __cpp_lib_atomic_wait >= 201907L
// Since C++20, locks can be acquired only after notification in the unlock,
// avoiding any unnecessary spinning.
// Note that even though wait guarantees it returns only after the value has
// changed, the lock is acquired after the next condition check.
atomicFlag.wait(true, std::memory_order_relaxed);
#else
std::this_thread::yield();
#endif
}
}

bool try_lock() noexcept
{
return !atomicFlag.test_and_set(std::memory_order_acquire);
}

void unlock() noexcept
{
atomicFlag.clear(std::memory_order_release);
#if defined(__cpp_lib_atomic_wait) && __cpp_lib_atomic_wait >= 201907L
atomicFlag.notify_one();
#endif
}
};


} // namespace Firebird

#endif // CLASSES_SPINLOCK_H
9 changes: 1 addition & 8 deletions src/common/classes/locks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,7 @@

namespace Firebird {

#if defined(WIN_NT)

void Spinlock::init()
{
SetCriticalSectionSpinCount(&spinlock, 4000);
}

#else //posix mutex
#if !defined(WIN_NT)

pthread_mutexattr_t Mutex::attr;

Expand Down
65 changes: 1 addition & 64 deletions src/common/classes/locks.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ class Exception; // Needed for catch

#ifdef WIN_NT

// Generic process-local mutex and spinlock. The latter
// is used to manage memory heaps in a threaded environment.
// Generic process-local mutex.

// Windows version of the class

Expand Down Expand Up @@ -151,23 +150,6 @@ class Mutex : public Reasons
Mutex& operator=(const Mutex&);
};

class Spinlock : public Mutex
{
private:
void init();

public:
Spinlock()
{
init();
}

explicit Spinlock(MemoryPool&)
{
init();
}
};

#else //WIN_NT

// Pthreads version of the class
Expand Down Expand Up @@ -272,51 +254,6 @@ friend class Condition;
Mutex& operator=(const Mutex&);
};

#ifdef NOT_USED_OR_REPLACED // we do not use spinlocks currently
class Spinlock
{
private:
pthread_spinlock_t spinlock;
public:
Spinlock()
{
if (pthread_spin_init(&spinlock, false))
system_call_failed::raise("pthread_spin_init");
}

explicit Spinlock(MemoryPool&)
{
if (pthread_spin_init(&spinlock, false))
system_call_failed::raise("pthread_spin_init");
}

~Spinlock()
{
if (pthread_spin_destroy(&spinlock))
system_call_failed::raise("pthread_spin_destroy");
}

void enter()
{
if (pthread_spin_lock(&spinlock))
system_call_failed::raise("pthread_spin_lock");
}

void leave()
{
if (pthread_spin_unlock(&spinlock))
system_call_failed::raise("pthread_spin_unlock");
}

private:
// Forbid copying
Spinlock(const Spinlock&);
Spinlock& operator=(const Spinlock&);
};
#else
typedef Mutex Spinlock;
#endif

#endif //WIN_NT


Expand Down
Loading
Loading