mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-16 07:50:28 +02:00
The libretro-common submodule pinned the standalone repository at 76a3d54. It is replaced by an in-tree copy of RetroArch master (b655a20) holding only what the core uses: the VFS, file, string, encoding, compat and time sources it already built, the headers they and the core include, the threading set - rthreads, retro_atomic, retro_spsc and retro_waitable_spsc, mpsc_stack, retro_triple_buffer, retro_eventcount, retro_asym_eventcount, retro_procbarrier and tpool, with features_cpu and rstrtod, which they need - and the codecs that replace the bundled zlib, zstd, libchdr, libzip and libpng: rinflate and rdeflate, rzstd, rchd with its LZMA and FLAC decoders, rzip_archive, rpng and crc32. stdstring.c, which nothing calls, is no longer built. The threading sources are always built, by both the static Makefile and CMake; the VFS set stays behind HAVE_LIBRETRO_VFS as before. The codecs are built by the change that switches the core over to them.
145 lines
4.6 KiB
C
145 lines
4.6 KiB
C
/* Copyright (C) 2010-2026 The RetroArch team
|
|
*
|
|
* ---------------------------------------------------------------------
|
|
* The following license statement only applies to this file (mpsc_stack.h).
|
|
* ---------------------------------------------------------------------
|
|
*
|
|
* Permission is hereby granted, free of charge,
|
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation the rights to
|
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#ifndef __LIBRETRO_SDK_MPSC_STACK_H__
|
|
#define __LIBRETRO_SDK_MPSC_STACK_H__
|
|
|
|
/* A many-producer, single-consumer intrusive stack: any thread pushes,
|
|
* one thread takes everything at once. The shape a worker-to-main
|
|
* handoff wants - deferred messages, retire lists - where the consumer
|
|
* drains on its own cadence and order within the batch is recovered by
|
|
* reversing, since a push stacks newest-first.
|
|
*
|
|
* Producers never wait and never touch a lock; the consumer's drain is
|
|
* one exchange. There is no ABA hazard in this shape: nodes are only
|
|
* pushed, and the consumer takes the whole chain, so a producer's
|
|
* compare-exchange retries against a moved head and nothing else.
|
|
*
|
|
* The node's link field belongs to the stack from push until the
|
|
* consumer has taken the chain; everything else in the node is
|
|
* published by the push and safe for the consumer to read after
|
|
* mpsc_stack_drain() returned it.
|
|
*/
|
|
|
|
#include <boolean.h>
|
|
#include <retro_atomic.h>
|
|
#include <retro_inline.h>
|
|
|
|
RETRO_BEGIN_DECLS
|
|
|
|
typedef struct mpsc_stack_node
|
|
{
|
|
struct mpsc_stack_node *next;
|
|
} mpsc_stack_node_t;
|
|
|
|
#if defined(RETRO_ATOMIC_HAS_PTR)
|
|
|
|
typedef struct mpsc_stack
|
|
{
|
|
retro_atomic_ptr_t head;
|
|
} mpsc_stack_t;
|
|
|
|
static INLINE void mpsc_stack_init(mpsc_stack_t *stack)
|
|
{
|
|
retro_atomic_ptr_init(&stack->head, NULL);
|
|
}
|
|
|
|
/* Any thread. The node's payload must be written before the push;
|
|
* the compare-exchange publishes it. */
|
|
static INLINE void mpsc_stack_push(mpsc_stack_t *stack,
|
|
mpsc_stack_node_t *node)
|
|
{
|
|
do
|
|
{
|
|
node->next = (mpsc_stack_node_t *)
|
|
retro_atomic_load_acquire_ptr(&stack->head);
|
|
} while (!retro_atomic_cas_ptr(&stack->head, node->next, node));
|
|
}
|
|
|
|
/* True when a drain would return nothing: the consumer's cheap
|
|
* per-iteration probe. */
|
|
static INLINE bool mpsc_stack_empty(mpsc_stack_t *stack)
|
|
{
|
|
return !retro_atomic_load_acquire_ptr(&stack->head);
|
|
}
|
|
|
|
/* The consumer. Takes the whole chain, newest-first; the caller walks
|
|
* or reverses it. */
|
|
static INLINE mpsc_stack_node_t *mpsc_stack_drain(mpsc_stack_t *stack)
|
|
{
|
|
return (mpsc_stack_node_t *)
|
|
retro_atomic_exchange_ptr(&stack->head, NULL);
|
|
}
|
|
|
|
#else
|
|
|
|
/* The volatile fallback backend offers no pointer atomics by design:
|
|
* it serves single-context targets where plain access is all the
|
|
* platform has. The stack keeps its shape with plain operations, and
|
|
* its guarantees follow the backend's - none beyond what the target
|
|
* itself provides, exactly as with every retro_atomic op there. */
|
|
typedef struct mpsc_stack
|
|
{
|
|
mpsc_stack_node_t * volatile head;
|
|
} mpsc_stack_t;
|
|
|
|
static INLINE void mpsc_stack_init(mpsc_stack_t *stack)
|
|
{
|
|
stack->head = NULL;
|
|
}
|
|
|
|
static INLINE void mpsc_stack_push(mpsc_stack_t *stack,
|
|
mpsc_stack_node_t *node)
|
|
{
|
|
node->next = stack->head;
|
|
stack->head = node;
|
|
}
|
|
|
|
static INLINE bool mpsc_stack_empty(mpsc_stack_t *stack)
|
|
{
|
|
return !stack->head;
|
|
}
|
|
|
|
static INLINE mpsc_stack_node_t *mpsc_stack_drain(mpsc_stack_t *stack)
|
|
{
|
|
mpsc_stack_node_t *node = stack->head;
|
|
stack->head = NULL;
|
|
return node;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* The drained chain, oldest-first. */
|
|
static INLINE mpsc_stack_node_t *mpsc_stack_reverse(mpsc_stack_node_t *node)
|
|
{
|
|
mpsc_stack_node_t *chain = NULL;
|
|
while (node)
|
|
{
|
|
mpsc_stack_node_t *next = node->next;
|
|
node->next = chain;
|
|
chain = node;
|
|
node = next;
|
|
}
|
|
return chain;
|
|
}
|
|
|
|
RETRO_END_DECLS
|
|
|
|
#endif
|