• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2005 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #include <stdlib.h>
18  #include <string.h>
19  
20  #include <log/log.h>
21  
22  #include "SharedBuffer.h"
23  
24  // ---------------------------------------------------------------------------
25  
26  namespace android {
27  
alloc(size_t size)28  SharedBuffer* SharedBuffer::alloc(size_t size)
29  {
30      // Don't overflow if the combined size of the buffer / header is larger than
31      // size_max.
32      LOG_ALWAYS_FATAL_IF((size >= (SIZE_MAX - sizeof(SharedBuffer))),
33                          "Invalid buffer size %zu", size);
34  
35      SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
36      if (sb) {
37          // Should be std::atomic_init(&sb->mRefs, 1);
38          // But that generates a warning with some compilers.
39          // The following is OK on Android-supported platforms.
40          sb->mRefs.store(1, std::memory_order_relaxed);
41          sb->mSize = size;
42      }
43      return sb;
44  }
45  
46  
dealloc(const SharedBuffer * released)47  void SharedBuffer::dealloc(const SharedBuffer* released)
48  {
49      free(const_cast<SharedBuffer*>(released));
50  }
51  
edit() const52  SharedBuffer* SharedBuffer::edit() const
53  {
54      if (onlyOwner()) {
55          return const_cast<SharedBuffer*>(this);
56      }
57      SharedBuffer* sb = alloc(mSize);
58      if (sb) {
59          memcpy(sb->data(), data(), size());
60          release();
61      }
62      return sb;
63  }
64  
editResize(size_t newSize) const65  SharedBuffer* SharedBuffer::editResize(size_t newSize) const
66  {
67      if (onlyOwner()) {
68          SharedBuffer* buf = const_cast<SharedBuffer*>(this);
69          if (buf->mSize == newSize) return buf;
70          // Don't overflow if the combined size of the new buffer / header is larger than
71          // size_max.
72          LOG_ALWAYS_FATAL_IF((newSize >= (SIZE_MAX - sizeof(SharedBuffer))),
73                              "Invalid buffer size %zu", newSize);
74  
75          buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
76          if (buf != NULL) {
77              buf->mSize = newSize;
78              return buf;
79          }
80      }
81      SharedBuffer* sb = alloc(newSize);
82      if (sb) {
83          const size_t mySize = mSize;
84          memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize);
85          release();
86      }
87      return sb;
88  }
89  
attemptEdit() const90  SharedBuffer* SharedBuffer::attemptEdit() const
91  {
92      if (onlyOwner()) {
93          return const_cast<SharedBuffer*>(this);
94      }
95      return 0;
96  }
97  
reset(size_t new_size) const98  SharedBuffer* SharedBuffer::reset(size_t new_size) const
99  {
100      // cheap-o-reset.
101      SharedBuffer* sb = alloc(new_size);
102      if (sb) {
103          release();
104      }
105      return sb;
106  }
107  
acquire() const108  void SharedBuffer::acquire() const {
109      mRefs.fetch_add(1, std::memory_order_relaxed);
110  }
111  
release(uint32_t flags) const112  int32_t SharedBuffer::release(uint32_t flags) const
113  {
114      int32_t prev = 1;
115      if (onlyOwner() || ((prev = mRefs.fetch_sub(1, std::memory_order_release) == 1)
116              && (atomic_thread_fence(std::memory_order_acquire), true))) {
117          mRefs.store(0, std::memory_order_relaxed);
118          if ((flags & eKeepStorage) == 0) {
119              free(const_cast<SharedBuffer*>(this));
120          }
121      }
122      return prev;
123  }
124  
125  
126  }; // namespace android
127