Line data Source code
1 : /*
2 : * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #if defined(_MSC_VER)
12 : #include <windows.h>
13 : #endif
14 :
15 : #include "single_rw_fifo.h"
16 :
17 : #include <assert.h>
18 :
19 0 : static int UpdatePos(int pos, int capacity) {
20 0 : return (pos + 1) % capacity;
21 : }
22 :
23 : namespace webrtc {
24 :
25 : namespace subtle {
26 :
27 : // Start with compiler support, then processor-specific hacks
28 : #if defined(__GNUC__) || defined(__clang__)
29 : // Available on GCC and clang - others?
30 0 : inline void MemoryBarrier() {
31 0 : __sync_synchronize();
32 0 : }
33 :
34 : #elif defined(_MSC_VER)
35 : inline void MemoryBarrier() {
36 : ::MemoryBarrier();
37 : }
38 :
39 : #elif defined(__aarch64__)
40 : // From http://http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_arm64_gcc.h
41 : inline void MemoryBarrier() {
42 : __asm__ __volatile__ ("dmb ish" ::: "memory");
43 : }
44 :
45 : #elif defined(__ARMEL__)
46 : // From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_arm_gcc.h
47 : inline void MemoryBarrier() {
48 : // Note: This is a function call, which is also an implicit compiler barrier.
49 : typedef void (*KernelMemoryBarrierFunc)();
50 : ((KernelMemoryBarrierFunc)0xffff0fa0)();
51 : }
52 :
53 : #elif defined(__x86_64__) || defined (__i386__)
54 : // From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_x86_gcc.h
55 : // mfence exists on x64 and x86 platforms containing SSE2.
56 : // x86 platforms that don't have SSE2 will crash with SIGILL.
57 : // If this code needs to run on such platforms in the future,
58 : // add runtime CPU detection here.
59 : inline void MemoryBarrier() {
60 : __asm__ __volatile__("mfence" : : : "memory");
61 : }
62 :
63 : #elif defined(__MIPSEL__)
64 : // From http://src.chromium.org/viewvc/chrome/trunk/src/base/atomicops_internals_mips_gcc.h
65 : inline void MemoryBarrier() {
66 : __asm__ __volatile__("sync" : : : "memory");
67 : }
68 :
69 : #else
70 : #error Add an implementation of MemoryBarrier() for this platform!
71 : #endif
72 :
73 : } // namespace subtle
74 :
75 0 : SingleRwFifo::SingleRwFifo(int capacity)
76 0 : : queue_(new int8_t*[capacity]),
77 : capacity_(capacity),
78 : size_(0),
79 : read_pos_(0),
80 0 : write_pos_(0)
81 : {
82 0 : }
83 :
84 0 : SingleRwFifo::~SingleRwFifo() {
85 0 : }
86 :
87 0 : void SingleRwFifo::Push(int8_t* mem) {
88 0 : assert(mem);
89 :
90 : // Ensure that there is space for the new data in the FIFO.
91 : // Note there is only one writer meaning that the other thread is guaranteed
92 : // only to decrease the size.
93 0 : const int free_slots = capacity() - size();
94 0 : if (free_slots <= 0) {
95 : // Size can be queried outside of the Push function. The caller is assumed
96 : // to ensure that Push will be successful before calling it.
97 0 : assert(false);
98 : return;
99 : }
100 0 : queue_.get()[write_pos_] = mem;
101 : // Memory barrier ensures that |size_| is updated after the size has changed.
102 0 : subtle::MemoryBarrier();
103 0 : ++size_;
104 0 : write_pos_ = UpdatePos(write_pos_, capacity());
105 : }
106 :
107 0 : int8_t* SingleRwFifo::Pop() {
108 0 : int8_t* ret_val = NULL;
109 0 : if (size() <= 0) {
110 : // Size can be queried outside of the Pop function. The caller is assumed
111 : // to ensure that Pop will be successfull before calling it.
112 0 : assert(false);
113 : return ret_val;
114 : }
115 0 : ret_val = queue_.get()[read_pos_];
116 : // Memory barrier ensures that |size_| is updated after the size has changed.
117 0 : subtle::MemoryBarrier();
118 0 : --size_;
119 0 : read_pos_ = UpdatePos(read_pos_, capacity());
120 0 : return ret_val;
121 : }
122 :
123 : } // namespace webrtc
|