--- net/instaweb/util/pthread_shared_mem.cc.org 2012-03-31 16:29:02.678813000 +0900 +++ net/instaweb/util/pthread_shared_mem.cc 2012-03-31 16:59:45.750779463 +0900 @@ -24,6 +24,9 @@ #include #include #include +#if defined(__FreeBSD__) +#include +#endif #include "net/instaweb/util/public/abstract_shared_mem.h" #include "net/instaweb/util/public/abstract_mutex.h" #include "net/instaweb/util/public/basictypes.h" @@ -70,13 +73,45 @@ DISALLOW_COPY_AND_ASSIGN(PthreadSharedMemMutex); }; +#if defined(__FreeBSD__) +// Some OSs does not support PTHREAD_PROCESS_SHARED attribute. (ex. FreeBSD < 9R, MacOS) +// FreeBSD lacks PTHREAD_PROCESS_SHARED support before 9.0R, so we use a semaphore +// instead. But nested locking is not supported. +class SemSharedMemMutex : public AbstractMutex { + public: + explicit SemSharedMemMutex(sem_t* sem) + : sem_(sem) {} + + virtual void Lock() { + sem_wait(sem_); + } + + virtual void Unlock() { + sem_post(sem_); + } + +private: + sem_t* sem_; + DISALLOW_COPY_AND_ASSIGN(SemSharedMemMutex); +}; +#endif + class PthreadSharedMemSegment : public AbstractSharedMemSegment { public: // We will be representing memory mapped in the [base, base + size) range. +#if defined(__FreeBSD__) + PthreadSharedMemSegment(char* base, size_t size, MessageHandler* handler, const char* name) + : base_(base), + size_(size), + sem_(NULL) { + std::sprintf(name_, "/%s_sem", name); + } +#else PthreadSharedMemSegment(char* base, size_t size, MessageHandler* handler) : base_(base), size_(size) { } +#endif virtual ~PthreadSharedMemSegment() { } @@ -86,10 +121,18 @@ } virtual size_t SharedMutexSize() const { +#if defined(__FreeBSD__) + return 0; +#else return sizeof(pthread_mutex_t); +#endif } virtual bool InitializeSharedMutex(size_t offset, MessageHandler* handler) { +#if defined(__FreeBSD__) + sem_ = sem_open(name_, O_CREAT, 0755, 1); + return sem_ ? true : false; +#else pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr) != 0) { handler->Message(kError, "pthread_mutexattr_init failed with errno:%d", @@ -113,19 +156,32 @@ pthread_mutexattr_destroy(&attr); return true; +#endif } virtual AbstractMutex* AttachToSharedMutex(size_t offset) { +#if defined(__FreeBSD__) + sem_ = sem_open(name_, O_EXCL); + return new SemSharedMemMutex(sem_); +#else return new PthreadSharedMemMutex(MutexPtr(offset)); +#endif } private: +#if defined(__FreeBSD__) +#else pthread_mutex_t* MutexPtr(size_t offset) { return reinterpret_cast(base_ + offset); } +#endif char* const base_; const size_t size_; +#if defined(__FreeBSD__) + char name_[256]; + sem_t* sem_; +#endif DISALLOW_COPY_AND_ASSIGN(PthreadSharedMemSegment); }; @@ -143,7 +199,11 @@ } size_t PthreadSharedMem::SharedMutexSize() const { +#if defined(__FreeBSD__) + return 0; +#else return sizeof(pthread_mutex_t); +#endif } AbstractSharedMemSegment* PthreadSharedMem::CreateSegment( @@ -167,7 +227,11 @@ SegmentBaseMap* bases = AcquireSegmentBases(); (*bases)[name] = base; UnlockSegmentBases(); +#if defined(__FreeBSD__) + return new PthreadSharedMemSegment(base, size, handler, name.c_str()); +#else return new PthreadSharedMemSegment(base, size, handler); +#endif } AbstractSharedMemSegment* PthreadSharedMem::AttachToSegment( @@ -182,7 +246,11 @@ } char* base = i->second; UnlockSegmentBases(); +#if defined(__FreeBSD__) + return new PthreadSharedMemSegment(base, size, handler, name.c_str()); +#else return new PthreadSharedMemSegment(base, size, handler); +#endif } void PthreadSharedMem::DestroySegment(const GoogleString& name,