source: flair-src/trunk/lib/FlairCore/src/SharedMem_impl.cpp@ 439

Last change on this file since 439 was 238, checked in by Bayard Gildas, 6 years ago

correction sémaphore. bloquant tout ça...

File size: 4.4 KB
RevLine 
[2]1// %flair:license{
[15]2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
[2]4// %flair:license}
5// created: 2014/02/10
6// filename: SharedMem_impl.cpp
7//
8// author: Guillaume Sanahuja
9// Copyright Heudiasyc UMR UTC/CNRS 7253
10//
11// version: $Id: $
12//
13// purpose: Class defining a shared memory
14//
15//
16/*********************************************************************/
17
18#include "SharedMem_impl.h"
19#include "SharedMem.h"
20#include <fcntl.h>
21#include <unistd.h>
22#include <sys/mman.h>
23#include <string.h>
24
25using std::string;
26using namespace flair::core;
27
[238]28SharedMem_impl::SharedMem_impl(const SharedMem *self, string name, size_t size, SharedMem::Type &type):self(self),type(type),size(size) {
[2]29#ifdef __XENO__
[15]30 heap_binded = false;
31 int status = rt_heap_create(&heap, name.c_str(), size,
32 H_SHARED | H_FIFO | H_NONCACHED);
33 if (status == -EEXIST) {
34 heap_binded = true;
35 status = rt_heap_bind(&heap, name.c_str(), TM_INFINITE);
36 }
37 if (status != 0) {
[213]38 char errorMsg[256];
[133]39 self->Err("rt_heap_create error (%s)\n", strerror_r(-status, errorMsg, sizeof(errorMsg)));
[15]40 return;
41 }
[2]42
[15]43 void *ptr;
44 status = rt_heap_alloc(&heap, 0, TM_NONBLOCK, &ptr);
45 if (status != 0) {
[213]46 char errorMsg[256];
[133]47 self->Err("rt_heap_alloc error (%s)\n", strerror_r(-status, errorMsg, sizeof(errorMsg)));
[15]48 }
49 mem_segment = (char *)ptr;
[2]50
51#else
[238]52 if (type==SharedMem::Type::mutex) {
53 sem = new Semaphore(self,1,"/" + name + "_mutex",Semaphore::Type::named);
54 } else { //producerConsumer
55 sem_producer=new Semaphore(self,0,"/" + name + "_producer", Semaphore::Type::named);
56 sem_consumer=new Semaphore(self,0,"/" + name + "_consumer", Semaphore::Type::named);
57 }
[15]58 shm_name = "/" + name;
59 fd = shm_open(shm_name.c_str(), O_RDWR | O_CREAT, 0666);
60 if (fd == -1) {
61 self->Err("Error creating shared memory\n");
62 }
63 ftruncate(fd, size);
[2]64
[203]65 mem_segment = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
[15]66 if (mem_segment == MAP_FAILED) {
67 self->Err("Failed to map memory\n");
68 }
[2]69#endif
70}
71
[15]72SharedMem_impl::~SharedMem_impl() {
73 int status;
[133]74
[2]75#ifdef __XENO__
76
[15]77 if (heap_binded == false) {
78 status = rt_heap_delete(&heap);
79 if (status != 0) {
[213]80 char errorMsg[256];
[133]81 self->Err("rt_heap_delete error (%s)\n", strerror_r(-status, errorMsg, sizeof(errorMsg)));
[2]82 }
[15]83 }
[2]84
85#else
[15]86 status = munmap(mem_segment, size);
87 if (status != 0) {
[213]88 char errorMsg[256];
[133]89 self->Err("Failed to unmap memory (%s)\n", strerror_r(-status, errorMsg, sizeof(errorMsg)));
[15]90 }
[2]91
[15]92 status = close(fd);
93 if (status != 0) {
[213]94 char errorMsg[256];
[133]95 self->Err("Failed to close file (%s)\n", strerror_r(-status, errorMsg, sizeof(errorMsg)));
[15]96 }
[2]97
[149]98 // do not check errors as it can be done by another process
[15]99 status = shm_unlink(shm_name.c_str()); /*
100 if(status!=0)
101 {
[213]102 char errorMsg[256];
[133]103 self->Err("Failed to unlink memory (%s)\n",strerror_r(-status, errorMsg, sizeof(errorMsg)));
[15]104 }
[2]105*/
[238]106 if (type==SharedMem::Type::mutex) {
107 delete sem;
108 } else {
109 delete sem_producer;
110 delete sem_consumer;
111 }
[2]112#endif
113}
114
[149]115void SharedMem_impl::ReaderReady() {
[238]116 if (type==SharedMem::Type::producerConsumer) {
117 sem_consumer->ReleaseSemaphore();
118 } else {
119 self->Warn("Called on a non producerConsumer type of shared memory! (this is seriously wrong)");
120 }
[149]121}
122
[15]123void SharedMem_impl::Write(const char *buf, size_t size) {
[149]124 if (type==SharedMem::Type::mutex) {
[238]125 sem->GetSemaphore();
[149]126 memcpy(mem_segment, buf, size);
[238]127 sem->ReleaseSemaphore();
[149]128 } else if (type==SharedMem::Type::producerConsumer) {
[238]129 //wait until consumer took the data away before writing a new one
[149]130 //but should not block if nobody's there to read
[238]131 if (sem_consumer->TryGetSemaphore()) {
[149]132 memcpy(mem_segment, buf, size);
[238]133 sem_producer->ReleaseSemaphore();
[149]134 }
135 }
[2]136}
137
[203]138bool SharedMem_impl::Read(char *buf, size_t size, Time nsTimeout) {
[149]139 if (type==SharedMem::Type::mutex) {
[238]140 if (sem->GetSemaphore()) { //may block for ever
[203]141 memcpy(buf, mem_segment, size);
[238]142 sem->ReleaseSemaphore();
[203]143 return true;
144 }
[149]145 } else if (type==SharedMem::Type::producerConsumer) {
[238]146 if (sem_producer->GetSemaphore(nsTimeout)) { //if nobody ever writes we need to exit this after a while
[206]147 memcpy(buf, mem_segment, size);
[238]148 sem_consumer->ReleaseSemaphore();
[203]149 return true;
[238]150 };
[149]151 }
[203]152 return false;
[2]153}
Note: See TracBrowser for help on using the repository browser.