thread/primitive: add platform wrappers for pause/yield instructions

This commit is contained in:
Danny Robson 2019-02-02 14:55:13 +11:00
parent 8c934fbd2c
commit 1f6caaa242
5 changed files with 40 additions and 13 deletions

View File

@ -157,8 +157,9 @@ endif ()
############################################################################### ###############################################################################
list (APPEND UTIL_FILES list (APPEND UTIL_FILES
thread/event.hpp thread/event.hpp
thread/semaphore.hpp
thread/flag.hpp thread/flag.hpp
thread/primitive.hpp
thread/semaphore.hpp
) )
if (LINUX) if (LINUX)

View File

@ -3,13 +3,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2018 Danny Robson <danny@nerdcruft.net> * Copyright 2018-2019 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef CRUFT_UTIL_PARALLEL_QUEUE_HPP #pragma once
#define CRUFT_UTIL_PARALLEL_QUEUE_HPP
#include "../maths.hpp" #include "../maths.hpp"
#include "../thread/primitive.hpp"
#include <atomic> #include <atomic>
#include <type_traits> #include <type_traits>
@ -78,7 +78,7 @@ namespace cruft::parallel {
// try to bump the write cursor to claim that slot // try to bump the write cursor to claim that slot
if (uint32_t orig = curr; !m_write.compare_exchange_weak (orig, next)) { if (uint32_t orig = curr; !m_write.compare_exchange_weak (orig, next)) {
asm volatile ("pause;"); pause ();
continue; continue;
} }
@ -92,7 +92,7 @@ namespace cruft::parallel {
uint32_t orig = curr; uint32_t orig = curr;
if (m_read.hi.compare_exchange_weak (orig, next)) if (m_read.hi.compare_exchange_weak (orig, next))
break; break;
asm volatile ("pause;"); pause ();
} while (1); } while (1);
return true; return true;
@ -132,7 +132,7 @@ namespace cruft::parallel {
if (uint32_t orig = curr; m_read.lo.compare_exchange_weak (orig, next)) if (uint32_t orig = curr; m_read.lo.compare_exchange_weak (orig, next))
return true; return true;
asm volatile ("pause;"); pause ();
} while (1); } while (1);
} }
@ -156,5 +156,3 @@ namespace cruft::parallel {
} m_read; } m_read;
}; };
} }
#endif

25
thread/primitive.hpp Normal file
View File

@ -0,0 +1,25 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include "../platform.hpp"
namespace cruft {
inline void pause [[gnu::always_inline]] (void)
{
#ifdef PROCESSOR_AMD64
asm volatile ("pause");
#elif PROCESSOR_ARM
asm volatile ("yield");
#else
#error "Unhandled processor type"
#endif
}
}

View File

@ -3,11 +3,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2018 Danny Robson <danny@nerdcruft.net> * Copyright 2018-2019 Danny Robson <danny@nerdcruft.net>
*/ */
#include "spinlock.hpp" #include "spinlock.hpp"
#include "primitive.hpp"
#include "../debug.hpp" #include "../debug.hpp"
using cruft::thread::spinlock; using cruft::thread::spinlock;
@ -35,7 +37,7 @@ spinlock::lock (void)
return; return;
while (held) while (held)
__asm__ volatile ("pause"); pause ();
} while (true); } while (true);
} }

View File

@ -3,10 +3,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2018 Danny Robson <danny@nerdcruft.net> * Copyright 2018-2019 Danny Robson <danny@nerdcruft.net>
*/ */
#include "ticketlock.hpp" #include "ticketlock.hpp"
#include "primitive.hpp"
using cruft::thread::ticketlock; using cruft::thread::ticketlock;
@ -25,7 +26,7 @@ ticketlock::lock (void)
auto self = next++; auto self = next++;
while (current != self) while (current != self)
__asm__ volatile ("pause"); pause ();
} }