* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ashmem.h"
#include <base/logging.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/ashmem.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "graphic_adapter.h"
#define ASHMEM_DEVICE "/dev/ashmem"
static pthread_once_t s_ashmem_dev_once = PTHREAD_ONCE_INIT;
static dev_t s_ashmem_dev;
static void get_ashmem_dev() {
struct stat st;
if (stat(ASHMEM_DEVICE, &st) == 0 && S_ISCHR(st.st_mode)) {
s_ashmem_dev = st.st_dev;
LOG(INFO) << "get_ashmem_dev execute success";
return;
}
LOG_IF(FATAL, 1) << "get_ashmem_dev execute failed";
}
static int ashmem_dev_fd_check(int fd) {
pthread_once(&s_ashmem_dev_once, get_ashmem_dev);
struct stat st;
if (fstat(fd, &st) == 0 &&
S_ISCHR(st.st_mode) &&
st.st_dev != 0 &&
st.st_dev == s_ashmem_dev) {
return 1;
}
LOG_IF(FATAL, 1) << "ashmem_dev_fd_check failed";
return 0;
}
static int ashmem_check_failure(int fd, int result)
{
if (result == -1 && errno == ENOTTY) {
return ashmem_dev_fd_check(fd);
}
return result;
}
int ashmem_device_is_supported(void) {
return 1;
}
int ashmem_create_region(const char* name, size_t size) {
return OHOS::NWeb::AshmemAdapter::AshmemCreate(name, size);
}
int ashmem_set_prot_region(int fd, int prot) {
return ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)));
}
int ashmem_get_prot_region(int fd) {
return ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_PROT_MASK)));
}
int ashmem_pin_region(int fd, size_t offset, size_t len) {
LOG(INFO) << "ashmem_pin_region";
struct ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
return ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)));
}
int ashmem_unpin_region(int fd, size_t offset, size_t len) {
LOG(DEBUG) << "ashmem_unpin_region";
struct ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
return ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)));
}
int ashmem_get_size_region(int fd) {
return ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
}