Index: chrome/common/transport_dib_linux.cc |
diff --git a/chrome/common/transport_dib_linux.cc b/chrome/common/transport_dib_linux.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..adecf1d9862d658cf4d563b81a79109455aa3a4e |
--- /dev/null |
+++ b/chrome/common/transport_dib_linux.cc |
@@ -0,0 +1,85 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <errno.h> |
+#include <stdlib.h> |
+#include <sys/ipc.h> |
+#include <sys/shm.h> |
+ |
+#include "base/logging.h" |
+#include "chrome/common/transport_dib.h" |
+ |
+// The shmat system call uses this as it's invalid return address |
+static void *const kInvalidAddress = (void*) -1; |
+ |
+TransportDIB::TransportDIB() |
+ : key_(-1), |
+ address_(kInvalidAddress), |
+ size_(0) { |
+} |
+ |
+TransportDIB::~TransportDIB() { |
+ if (address_ != kInvalidAddress) { |
+ shmdt(address_); |
+ address_ = kInvalidAddress; |
+ } |
+} |
+ |
+// static |
+TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) { |
+ // We use a mode of 0666 since the X server won't attach to memory which is |
+ // 0600 since it can't know if it (as a root process) is being asked to map |
+ // someone else's private shared memory region. |
+ const int shmkey = shmget(IPC_PRIVATE, size, 0666); |
+ if (shmkey == -1) { |
+ DLOG(ERROR) << "Failed to create SysV shared memory region" |
+ << " errno:" << errno; |
+ return false; |
+ } |
+ |
+ void* address = shmat(shmkey, NULL /* desired address */, 0 /* flags */); |
+ // Here we mark the shared memory for deletion. Since we attached it in the |
+ // line above, it doesn't actually get deleted but, if we crash, this means |
+ // that the kernel will automatically clean it up for us. |
+ shmctl(shmkey, IPC_RMID, 0); |
+ if (address == kInvalidAddress) |
+ return false; |
+ |
+ TransportDIB* dib = new TransportDIB; |
+ |
+ dib->key_ = shmkey; |
+ dib->address_ = address; |
+ dib->size_ = size; |
+ return dib; |
+} |
+ |
+TransportDIB* TransportDIB::Map(Handle shmkey) { |
+ struct shmid_ds shmst; |
+ if (shmctl(shmkey, IPC_STAT, &shmst) == -1) |
+ return NULL; |
+ |
+ void* address = shmat(shmkey, NULL /* desired address */, 0 /* flags */); |
+ if (address == kInvalidAddress) |
+ return NULL; |
+ |
+ TransportDIB* dib = new TransportDIB; |
+ |
+ dib->address_ = address; |
+ dib->size_ = shmst.shm_segsz; |
+ dib->key_ = shmkey; |
+ return dib; |
+} |
+ |
+void* TransportDIB::memory() const { |
+ DCHECK_NE(address_, kInvalidAddress); |
+ return address_; |
+} |
+ |
+TransportDIB::Id TransportDIB::id() const { |
+ return key_; |
+} |
+ |
+TransportDIB::Handle TransportDIB::handle() const { |
+ return key_; |
+} |