library/src/SharedMemoryAccess.cpp

111 lines
3.2 KiB
C++
Raw Normal View History

2019-11-12 14:07:02 +01:00
#include <cstdio>
#include <cstring>
2019-11-06 11:05:11 +01:00
#include <sys/ipc.h>
2019-11-12 14:07:02 +01:00
#include <sys/sem.h>
2019-11-06 11:05:11 +01:00
#include <sys/shm.h>
#include <sys/stat.h>
2019-11-12 14:07:02 +01:00
#include <sys/types.h>
#include "SharedMemoryAccess.hpp"
#include "internal.hpp"
#include "log.hpp"
2019-11-06 11:05:11 +01:00
namespace vkvm {
constexpr int PERMISSION = 0666;
constexpr int LOCK = -1;
constexpr int UNLOCK = 1;
constexpr int SEM_KEY = 123458L;
2019-11-07 12:05:06 +01:00
int semId;
struct sembuf semaphore;
2019-11-07 12:05:06 +01:00
std::vector<char> localSharedMemory;
auto initSemaphore() -> int {
/* Testen, ob das Semaphor bereits existiert */
semId = semget(SEM_KEY, 0, IPC_PRIVATE);
2019-11-06 11:05:11 +01:00
if (semId < 0) {
/* ... existiert noch nicht, also anlegen */
/* Alle Zugriffsrechte der Dateikreierungsmaske */
/* erlauben */
umask(0);
semId = semget(SEM_KEY, 1, IPC_CREAT | IPC_EXCL | PERMISSION);
if (semId < 0) {
return -1;
}
/* Semaphor mit 1 initialisieren */
2019-11-13 15:42:04 +01:00
if (semctl(semId, 0, SETVAL, 1) == -1) {
return -1;
}
2019-11-06 11:05:11 +01:00
}
return 1;
}
auto semaphoreOperation(int op) -> int {
semaphore.sem_op = static_cast<int16_t>(op);
semaphore.sem_flg = SEM_UNDO;
if (semop(semId, &semaphore, 1) == -1) {
perror(" semop ");
log(LogLevel::CRITICAL, "could not operate on semaphore, exiting");
2019-11-06 11:05:11 +01:00
return -1;
2019-11-12 14:07:02 +01:00
}
return 1;
2019-11-06 11:05:11 +01:00
}
auto writeSharedMemory(char *data, int size, int offset) -> void {
lockSharedMemory();
memcpy(getSharedMemory() + offset, data, size);
unlockSharedMemory();
2019-11-06 11:05:11 +01:00
}
2019-11-21 13:03:53 +01:00
char *getLocalMemory(){
static bool givenWarning {false};
if(!givenWarning && impl.localMemoryWarn){
givenWarning = true;
log(LogLevel::WARNING, "no shared memory found, using local memory instead!");
}
2019-11-21 13:03:53 +01:00
if (localSharedMemory.empty()) {
constexpr int kilo = 1024;
localSharedMemory.resize(impl.sharedMemorySize * kilo);
2019-11-21 13:03:53 +01:00
}
return &localSharedMemory[0];
}
auto getSharedMemory() -> char * {
2019-11-27 11:40:54 +01:00
if(impl.sharedMemory != nullptr){
return impl.sharedMemory;
}
2019-11-13 15:42:04 +01:00
int shmId = shmget(impl.sharedMemoryKey, 0, 0);
if (shmId < 0) {
//using a local buffer for shared memory testing
2019-11-21 13:03:53 +01:00
return getLocalMemory();
}
char *ptr = static_cast<char *>(shmat(shmId, nullptr, 0));
2019-11-27 13:39:16 +01:00
if(reinterpret_cast<size_t>(ptr) == static_cast<size_t>(-1)){
2019-11-27 11:40:54 +01:00
log(LogLevel::WARNING, strerror(errno));
2019-11-21 13:03:53 +01:00
}else{
2019-11-27 11:40:54 +01:00
impl.sharedMemory = ptr;
2019-11-21 13:03:53 +01:00
return ptr;
}
2019-11-27 13:39:16 +01:00
return getLocalMemory();
}
auto getSharedMemory(char *address, int size, int offset) -> void {
lockSharedMemory();
memcpy(address, getSharedMemory() + offset, size);
unlockSharedMemory();
}
auto getSharedMemorySize() -> int {
return impl.sharedMemorySize;
}
auto lockSharedMemory() -> void {
semaphoreOperation(LOCK);
}
auto unlockSharedMemory() -> void {
semaphoreOperation(UNLOCK);
}
}