Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / ports / SkPurgeableMemoryBlock_android.cpp
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkPurgeableMemoryBlock.h"
9
10 #include "android/ashmem.h"
11 #include <sys/mman.h>
12 #include <unistd.h>
13
14 bool SkPurgeableMemoryBlock::IsSupported() {
15     return true;
16 }
17
18 #ifdef SK_DEBUG
19 bool SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks() {
20     return false;
21 }
22
23 bool SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks() {
24     return false;
25 }
26
27 bool SkPurgeableMemoryBlock::purge() {
28     SkASSERT(!fPinned);
29     if (-1 != fFD) {
30         ashmem_purge_all_caches(fFD);
31         return true;
32     } else {
33         return false;
34     }
35 }
36 #endif
37
38 // ashmem likes lengths on page boundaries.
39 static size_t round_to_page_size(size_t size) {
40     const size_t mask = getpagesize() - 1;
41     size_t newSize = (size + mask) & ~mask;
42     return newSize;
43 }
44
45 SkPurgeableMemoryBlock::SkPurgeableMemoryBlock(size_t size)
46     : fAddr(NULL)
47     , fSize(round_to_page_size(size))
48     , fPinned(false)
49     , fFD(-1) {
50 }
51
52 SkPurgeableMemoryBlock::~SkPurgeableMemoryBlock() {
53     if (-1 != fFD) {
54         munmap(fAddr, fSize);
55         close(fFD);
56     }
57 }
58
59 void* SkPurgeableMemoryBlock::pin(SkPurgeableMemoryBlock::PinResult* pinResult) {
60     SkASSERT(!fPinned);
61     if (-1 == fFD) {
62         int fd = ashmem_create_region(NULL, fSize);
63         if (-1 == fd) {
64             SkDebugf("ashmem_create_region failed\n");
65             return NULL;
66         }
67
68         int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
69         if (err != 0) {
70             SkDebugf("ashmem_set_prot_region failed\n");
71             close(fd);
72             return NULL;
73         }
74
75         void* addr = mmap(NULL, fSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
76         if (-1 == (long) addr) {
77             SkDebugf("mmap failed\n");
78             close(fd);
79             return NULL;
80         }
81         fAddr = addr;
82         fFD = fd;
83         (void) ashmem_pin_region(fd, 0, 0);
84         *pinResult = kUninitialized_PinResult;
85         fPinned = true;
86     } else {
87         int pin = ashmem_pin_region(fFD, 0, 0);
88         if (ASHMEM_NOT_PURGED == pin) {
89             fPinned = true;
90             *pinResult = kRetained_PinResult;
91         } else if (ASHMEM_WAS_PURGED == pin) {
92             fPinned = true;
93             *pinResult = kUninitialized_PinResult;
94         } else {
95             // Failed.
96             munmap(fAddr, fSize);
97             close(fFD);
98             fFD = -1;
99             fAddr = NULL;
100         }
101     }
102     return fAddr;
103 }
104
105 void SkPurgeableMemoryBlock::unpin() {
106     if (-1 != fFD) {
107         ashmem_unpin_region(fFD, 0, 0);
108         fPinned = false;
109     }
110 }