Rind преди 8 години
родител
ревизия
4422e27921

BIN
build/Toolchain/arm/libgfaipc.so.1.0.0


BIN
build/Toolchain/arm/libgfaipc.so.1.1.0


BIN
build/Toolchain/arm/libgfaipcd.so.1.0.0


BIN
build/Toolchain/arm/libgfaipcd.so.1.1.0


+ 8 - 0
build/Toolchain/gfaipc.h

@@ -4,6 +4,8 @@
 #if !defined(AGD_GFAIPC_H__6126047E_C1B1_4ACE_BD49_8780C7E5E068__INCLUDED_)
 #define AGD_GFAIPC_H__6126047E_C1B1_4ACE_BD49_8780C7E5E068__INCLUDED_
 
+#include <stdlib.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif	//	__cplusplus
@@ -21,6 +23,12 @@ void	GfaIpcLockSHM		(HSHM hShm);
 void	GfaIpcUnlockSHM		(HSHM hShm);
 void	GfaIpcDumpSHMROT	(void);
 
+long	GfaIpcInterlockedIncrement(HSHM hShm, volatile long *pl);
+long	GfaIpcInterlockedDecrement(HSHM hShm, volatile long *pl);
+long	GfaIpcInterlockedCompare(HSHM hShm, volatile long *pl, long comparand);
+long	GfaIpcInterlockedSet(HSHM hShm, volatile long *pl, long val);
+long	GfaIpcInterlockedClear(HSHM hShm, volatile long *pl);
+
 /////////////////////////////////////////////////////////////////////////////
 #ifdef __cplusplus
 }

+ 10 - 10
build/Toolchain/install.sh

@@ -9,10 +9,10 @@ REMUSR="root@192.168.0.125"
 TOOLCHAIN_SYSROOT="/opt/GfA/T_C49xL448RT_Qt57x/usr/arm-buildroot-linux-gnueabihf/sysroot"
 LIBBASENAMEREL="gfaipc"
 LIBBASENAMEDBG="gfaipcd"
-LIBDBGx86_64SRC="x86_64/lib$LIBBASENAMEDBG.so.1.0.0"
-LIBRELx86_64SRC="x86_64/lib$LIBBASENAMEREL.so.1.0.0"
-LIBDBGARMSRC="arm/lib$LIBBASENAMEDBG.so.1.0.0"
-LIBRELARMSRC="arm/lib$LIBBASENAMEREL.so.1.0.0"
+LIBDBGx86_64SRC="x86_64/lib$LIBBASENAMEDBG.so.1.1.0"
+LIBRELx86_64SRC="x86_64/lib$LIBBASENAMEREL.so.1.1.0"
+LIBDBGARMSRC="arm/lib$LIBBASENAMEDBG.so.1.1.0"
+LIBRELARMSRC="arm/lib$LIBBASENAMEREL.so.1.1.0"
 INCSRC="$LIBBASENAMEREL.h"
 
 LIBDBGx86_64DST="/usr/lib/"
@@ -27,26 +27,26 @@ sudo cp $LIBDBGx86_64SRC $LIBDBGx86_64DST
 sudo cp $LIBRELx86_64SRC $LIBRELx86_64DST
 sudo cp $INCSRC $INCDSTx86_64DST
 
-sudo ln -sfnr /usr/lib/lib$LIBBASENAMEDBG.so.1.0.0 /usr/lib/lib$LIBBASENAMEDBG.so.1
+sudo ln -sfnr /usr/lib/lib$LIBBASENAMEDBG.so.1.1.0 /usr/lib/lib$LIBBASENAMEDBG.so.1
 sudo ln -sfnr /usr/lib/lib$LIBBASENAMEDBG.so.1 /usr/lib/lib$LIBBASENAMEDBG.so
-sudo ln -sfnr /usr/lib/lib$LIBBASENAMEREL.so.1.0.0 /usr/lib/lib$LIBBASENAMEREL.so.1
+sudo ln -sfnr /usr/lib/lib$LIBBASENAMEREL.so.1.1.0 /usr/lib/lib$LIBBASENAMEREL.so.1
 sudo ln -sfnr /usr/lib/lib$LIBBASENAMEREL.so.1 /usr/lib/lib$LIBBASENAMEREL.so
 
 cp $LIBDBGARMSRC $LIBDBGARMDST_LOC
 cp $LIBRELARMSRC $LIBRELARMDST_LOC
 cp $INCSRC $INCDSTARM_LOC
 
-ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1.0.0 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1
+ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1.1.0 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1
 ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so
-ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1.0.0 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1
+ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1.1.0 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1
 ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so
 
 pscp -pw $REMPWD $LIBDBGARMSRC $REMUSR:/usr/lib/ > /dev/null
 pscp -pw $REMPWD $LIBRELARMSRC $REMUSR:/usr/lib/ > /dev/null
 
-plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEDBG.so.1.0.0 /usr/lib/lib$LIBBASENAMEDBG.so.1
+plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEDBG.so.1.1.0 /usr/lib/lib$LIBBASENAMEDBG.so.1
 plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEDBG.so.1 /usr/lib/lib$LIBBASENAMEDBG.so
-plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEREL.so.1.0.0 /usr/lib/lib$LIBBASENAMEREL.so.1
+plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEREL.so.1.1.0 /usr/lib/lib$LIBBASENAMEREL.so.1
 plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEREL.so.1 /usr/lib/lib$LIBBASENAMEREL.so
 
 echo Done.

BIN
build/Toolchain/x86_64/libgfaipc.so.1.0.0


BIN
build/Toolchain/x86_64/libgfaipc.so.1.1.0


BIN
build/Toolchain/x86_64/libgfaipcd.so.1.0.0


BIN
build/Toolchain/x86_64/libgfaipcd.so.1.1.0


+ 4 - 10
build/arm/builddbg.sh

@@ -4,20 +4,14 @@ set -o pipefail
 
 SYSROOT="/opt/GfA/T_C49xL448RT_Qt57x/usr/arm-buildroot-linux-gnueabihf/sysroot"
 CC="/opt/GfA/T_C49xL448RT_Qt57x/usr/bin/arm-buildroot-linux-gnueabihf-c++"
-CCOPTS="-g -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer -D_DEBUG"
+CCOPTS="-g -fPIC -pthread -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer -D_DEBUG"
 
 LIBBASENAME="gfaipcd"
-LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LIBFILENAME="lib$LIBBASENAME.so.1.1.0"
 LINKNAME="lib$LIBBASENAME.so"
 
-$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
-$CC -g -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o shm.o shmrot.o ipcshm.o -lc
+$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/locmtx.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
+$CC -g -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o locmtx.o shm.o shmrot.o ipcshm.o -lc -pthread
 rm -f *.o
 mv $LIBFILENAME ../Toolchain/arm
 
-#sudo mv $LIBFILENAME $SYSROOT/usr/lib/
-#sudo ln -sfn $SYSROOT/usr/lib/$LIBFILENAME $SYSROOT/usr/lib/$LINKNAME
-
-#CCOPTS="-Wall -Wextra -Wformat -Wconversion -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -fabi-version=2 -fno-omit-frame-pointer"
-#$CC -D_DEBUG -g $CCOPTS -L. -o testd.bin ../main.c -l$LIBBASENAME -lconfig -lpthread -lz -lm -lrt -ldl
-

+ 4 - 10
build/arm/buildrel.sh

@@ -4,20 +4,14 @@ set -o pipefail
 
 SYSROOT="/opt/GfA/T_C49xL448RT_Qt57x/usr/arm-buildroot-linux-gnueabihf/sysroot"
 CC="/opt/GfA/T_C49xL448RT_Qt57x/usr/bin/arm-buildroot-linux-gnueabihf-c++"
-CCOPTS="-O3 -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer"
+CCOPTS="-O3 -pthread -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer"
 
 LIBBASENAME="gfaipc"
-LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LIBFILENAME="lib$LIBBASENAME.so.1.1.0"
 LINKNAME="lib$LIBBASENAME.so"
 
-$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
-$CC -O3 -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o shm.o shmrot.o ipcshm.o -lc
+$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/locmtx.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
+$CC -O3 -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o locmtx.o shm.o shmrot.o ipcshm.o -lc -pthread
 rm -f *.o
 mv $LIBFILENAME ../Toolchain/arm
 
-#sudo mv $LIBFILENAME $SYSROOT/usr/lib/
-#sudo ln -sfn $SYSROOT/usr/lib/$LIBFILENAME $SYSROOT/usr/lib/$LINKNAME
-
-#CCOPTS="-Wall -Wextra -Wformat -Wconversion -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -fabi-version=2 -fno-omit-frame-pointer"
-#$CC -O3 $CCOPTS -L. -o testr.bin ../main.c -l$LIBBASENAME -lconfig -lpthread -lz -lm -lrt -ldl
-

+ 3 - 0
build/build.sh

@@ -10,4 +10,7 @@ cd ../arm
 ./builddbg.sh
 ./buildrel.sh
 
+cd ..
+cp "../src/gfaipc.h" "Toolchain/"
+
 echo done

+ 4 - 10
build/x86_64/builddbg.sh

@@ -3,20 +3,14 @@ set -e
 set -o pipefail
 
 CC=c++
-CCOPTS="-g -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer -D_DEBUG"
+CCOPTS="-g -pthread -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer -D_DEBUG"
 
 LIBBASENAME="gfaipcd"
-LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LIBFILENAME="lib$LIBBASENAME.so.1.1.0"
 LINKNAME="lib$LIBBASENAME.so"
 
-$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
-$CC -g -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o shm.o shmrot.o ipcshm.o -lc
+$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/locmtx.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
+$CC -g -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o locmtx.o shm.o shmrot.o ipcshm.o -lc -pthread
 rm -f *.o
 mv $LIBFILENAME ../Toolchain/x86_64
 
-#sudo mv $LIBFILENAME /usr/lib/
-#sudo ln -sfn /usr/lib/$LIBFILENAME /usr/lib/$LINKNAME
-
-#CCOPTS="-Wall -Wextra -Wformat -Wconversion -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -fabi-version=2 -fno-omit-frame-pointer"
-#$CC -D_DEBUG -g $CCOPTS -L. -o test.bin ../main.c -l$LIBBASENAME -lconfig -lpthread -lz -lm -lrt -ldl
-

+ 4 - 10
build/x86_64/buildrel.sh

@@ -3,20 +3,14 @@ set -e
 set -o pipefail
 
 CC=c++
-CCOPTS="-O3 -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer"
+CCOPTS="-O3 -pthread -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer"
 
 LIBBASENAME="gfaipc"
-LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LIBFILENAME="lib$LIBBASENAME.so.1.1.0"
 LINKNAME="lib$LIBBASENAME.so"
 
-$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
-$CC -O3 -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o shm.o shmrot.o ipcshm.o -lc -pthread
+$CC $CCOPTS -c ../../src/uuid.c ../../src/sema.cpp ../../src/mutex.cpp ../../src/locmtx.cpp ../../src/shm.cpp ../../src/shmrot.cpp ../../src/ipcshm.cpp
+$CC -O3 -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME uuid.o sema.o mutex.o locmtx.o shm.o shmrot.o ipcshm.o -lc -pthread
 rm -f *.o
 mv $LIBFILENAME ../Toolchain/x86_64
 
-#sudo mv $LIBFILENAME /usr/lib/
-#sudo ln -sfn /usr/lib/$LIBFILENAME /usr/lib/$LINKNAME
-
-#CCOPTS="-Wall -Wextra -Wformat -Wconversion -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -fabi-version=2 -fno-omit-frame-pointer"
-#$CC -O3 $CCOPTS -L. -o test.bin ../main.c -l$LIBBASENAME -lconfig -lpthread -lz -lm -lrt -ldl
-

+ 18 - 3
main.c

@@ -8,6 +8,11 @@
 #endif	//	_WIN32
 
 #include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+#include <fcntl.h>
 #include "src/defines.h"
 #include "src/gfaipc.h"
 
@@ -40,13 +45,21 @@ int main(int argc, char *argv[])
 	_UNUSED(argc);
 	_UNUSED(argv);
 
-	GfaIpcDumpSHMROT();
+//	GfaIpcDumpSHMROT();
 
 	hShm1 = GfaIpcAcquireSHM(_UUID_TESTSTRUCT1, sizeof(TESTSTRUCT1), 1, "Teststruct 1");
-	GfaIpcDumpSHMROT();
-	hShm2 = GfaIpcAcquireSHM(_UUID_TESTSTRUCT1, sizeof(TESTSTRUCT1), 1, "Teststruct 1");
+	TRACE("Acquired SHM.\n");
+	p1 = (LPTESTSTRUCT1)GfaIpcAcquirePointer(hShm1);
+	TRACE("Acquired Pointer.\n");
+//	GfaIpcDumpSHMROT();
+	GfaIpcLockSHM(hShm1);
+	GfaIpcLockSHM(hShm1);
+	TRACE("Acquired Lock.\n");
+	sleep(10);
+//	hShm2 = GfaIpcAcquireSHM(_UUID_TESTSTRUCT1, sizeof(TESTSTRUCT1), 1, "Teststruct 1");
 //	GfaIpcDumpSHMROT();
 
+#if 0
 	if(hShm1 && hShm2)
 	{
 		p1 = (LPTESTSTRUCT1)GfaIpcAcquirePointer(hShm1);
@@ -77,10 +90,12 @@ int main(int argc, char *argv[])
 		GfaIpcReleaseSHM(hShm1);
 		GfaIpcReleaseSHM(hShm2);
 	}
+#endif
 
 	//uuid_t uuid;
 	//_uuid_parse("8c2e723a-5556-4d90-b5ed-bba8575b6f28", &uuid);
 
+	TRACE("Exit.\n");
 	return 0;
 }
 

+ 8 - 0
src/gfaipc.h

@@ -4,6 +4,8 @@
 #if !defined(AGD_GFAIPC_H__6126047E_C1B1_4ACE_BD49_8780C7E5E068__INCLUDED_)
 #define AGD_GFAIPC_H__6126047E_C1B1_4ACE_BD49_8780C7E5E068__INCLUDED_
 
+#include <stdlib.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif	//	__cplusplus
@@ -21,6 +23,12 @@ void	GfaIpcLockSHM		(HSHM hShm);
 void	GfaIpcUnlockSHM		(HSHM hShm);
 void	GfaIpcDumpSHMROT	(void);
 
+long	GfaIpcInterlockedIncrement(HSHM hShm, volatile long *pl);
+long	GfaIpcInterlockedDecrement(HSHM hShm, volatile long *pl);
+long	GfaIpcInterlockedCompare(HSHM hShm, volatile long *pl, long comparand);
+long	GfaIpcInterlockedSet(HSHM hShm, volatile long *pl, long val);
+long	GfaIpcInterlockedClear(HSHM hShm, volatile long *pl);
+
 /////////////////////////////////////////////////////////////////////////////
 #ifdef __cplusplus
 }

+ 139 - 33
src/ipcshm.cpp

@@ -11,48 +11,22 @@
 #include "defines.h"
 #include "uuid.h"
 #include "shmrot.h"
-#include "gfaipc.h"
 
 /////////////////////////////////////////////////////////////////////////////
 
-typedef struct _SHM_HANDLE
-{
-	CShm *pShm;
-}SHM_HANDLE, *LPSHM_HANDLE;
-typedef const SHM_HANDLE *LPCSHM_HANDLE;
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define _IPCSHM_MAX_HANDLES			32
-
-class CShmHandle
-{
-public:
-	CShmHandle(void);
-	~CShmHandle(void);
-
-	HSHM AcquireHandle(CShm *pShm);
-	void ReleaseHandle(HSHM hShm);
-
-private:
-	SHM_HANDLE m_handles[_IPCSHM_MAX_HANDLES];
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-CShmHandle::CShmHandle(void)
+CShmHandleMap::CShmHandleMap(void)
 {
 	memset(m_handles, 0, sizeof(m_handles));
 }
 
-CShmHandle::~CShmHandle(void)
+CShmHandleMap::~CShmHandleMap(void)
 {
 	for(size_t i = 0; i < _IPCSHM_MAX_HANDLES; i++)
 	{
 	}
 }
 
-HSHM CShmHandle::AcquireHandle(CShm *pShm)
+HSHM CShmHandleMap::AcquireHandle(CShm *pShm)
 {
 	HSHM hShm = NULL;
 
@@ -69,7 +43,7 @@ HSHM CShmHandle::AcquireHandle(CShm *pShm)
 	return hShm;
 }
 
-void CShmHandle::ReleaseHandle(HSHM hShm)
+void CShmHandleMap::ReleaseHandle(HSHM hShm)
 {
 	for(int i = 0; i < _IPCSHM_MAX_HANDLES; i++)
 	{
@@ -81,10 +55,26 @@ void CShmHandle::ReleaseHandle(HSHM hShm)
 	}
 }
 
+CShm* CShmHandleMap::LookupShm(const uuid_t &uuid)
+{
+	for(int i = 0; i < _IPCSHM_MAX_HANDLES; i++)
+	{
+		if(m_handles[i].pShm)
+		{
+			const uuid_t &uuid2 = m_handles[i].pShm->Uuid();
+
+			if(!_uuid_compare(&uuid, &uuid2))
+				return m_handles[i].pShm;
+		}
+	}
+
+	return NULL;
+}
+
 /////////////////////////////////////////////////////////////////////////////
 
 static CShmROT g_shmRot;
-static CShmHandle g_shmHandleMap;
+static CShmHandleMap g_shmHandleMap;
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -116,10 +106,11 @@ HSHM GfaIpcAcquireSHM(const char *pszUuid, size_t nSizeElement, size_t nCntEleme
 	}
 
 	g_shmRot.Unlock();
-
 	return hShm;
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 void GfaIpcReleaseSHM(HSHM hShm)
 {
 	if(hShm)
@@ -137,6 +128,8 @@ void GfaIpcReleaseSHM(HSHM hShm)
 	}
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 void* GfaIpcAcquirePointer(HSHM hShm)
 {
 	if(hShm)
@@ -155,6 +148,8 @@ void* GfaIpcAcquirePointer(HSHM hShm)
 	return NULL;
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 void GfaIpcReleasePointer(HSHM hShm, const void *p)
 {
 	if(!hShm)
@@ -174,6 +169,8 @@ void GfaIpcReleasePointer(HSHM hShm, const void *p)
 	ph->pShm->Detach(p);
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 void GfaIpcLockSHM(HSHM hShm)
 {
 	if(!hShm)
@@ -193,6 +190,8 @@ void GfaIpcLockSHM(HSHM hShm)
 	ph->pShm->Lock();
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 void GfaIpcUnlockSHM(HSHM hShm)
 {
 	if(!hShm)
@@ -212,6 +211,8 @@ void GfaIpcUnlockSHM(HSHM hShm)
 	ph->pShm->Unlock();
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 void GfaIpcDumpSHMROT(void)
 {
 	if(!g_shmRot.Created())
@@ -223,5 +224,110 @@ void GfaIpcDumpSHMROT(void)
 		}
 	}
 
-	g_shmRot.DumpEntries();
+	g_shmRot.DumpEntries(g_shmHandleMap);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+long GfaIpcInterlockedIncrement(HSHM hShm, volatile long *pl)
+{
+	if(!hShm)
+	{
+		TRACE("GfaIpcInterlockedIncrement: Invalid Handle!\n");
+		return 0;
+	}
+
+	LPSHM_HANDLE ph = (LPSHM_HANDLE)hShm;
+
+	if(!ph->pShm)
+	{
+		TRACE("GfaIpcInterlockedIncrement: Invalid Handle!\n");
+		return 0;
+	}
+
+	return ph->pShm->InterlockedIncrement(pl);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+long GfaIpcInterlockedDecrement(HSHM hShm, volatile long *pl)
+{
+	if(!hShm)
+	{
+		TRACE("GfaIpcInterlockedDecrement: Invalid Handle!\n");
+		return 0;
+	}
+
+	LPSHM_HANDLE ph = (LPSHM_HANDLE)hShm;
+
+	if(!ph->pShm)
+	{
+		TRACE("GfaIpcInterlockedDecrement: Invalid Handle!\n");
+		return 0;
+	}
+
+	return ph->pShm->InterlockedDecrement(pl);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+long GfaIpcInterlockedCompare(HSHM hShm, volatile long *pl, long comparand)
+{
+	if(!hShm)
+	{
+		TRACE("GfaIpcInterlockedCompare: Invalid Handle!\n");
+		return 0;
+	}
+
+	LPSHM_HANDLE ph = (LPSHM_HANDLE)hShm;
+
+	if(!ph->pShm)
+	{
+		TRACE("GfaIpcInterlockedCompare: Invalid Handle!\n");
+		return 0;
+	}
+
+	return ph->pShm->InterlockedCompare(pl, comparand);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+long GfaIpcInterlockedSet(HSHM hShm, volatile long *pl, long val)
+{
+	if(!hShm)
+	{
+		TRACE("GfaIpcInterlockedSet: Invalid Handle!\n");
+		return 0;
+	}
+
+	LPSHM_HANDLE ph = (LPSHM_HANDLE)hShm;
+
+	if(!ph->pShm)
+	{
+		TRACE("GfaIpcInterlockedSet: Invalid Handle!\n");
+		return 0;
+	}
+
+	return ph->pShm->InterlockedSet(pl, val);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+long GfaIpcInterlockedClear(HSHM hShm, volatile long *pl)
+{
+	if(!hShm)
+	{
+		TRACE("GfaIpcInterlockedSet: Invalid Handle!\n");
+		return 0;
+	}
+
+	LPSHM_HANDLE ph = (LPSHM_HANDLE)hShm;
+
+	if(!ph->pShm)
+	{
+		TRACE("GfaIpcInterlockedClear: Invalid Handle!\n");
+		return 0;
+	}
+
+	return ph->pShm->InterlockedClear(pl);
 }

+ 83 - 0
src/locmtx.cpp

@@ -0,0 +1,83 @@
+#ifdef _WIN32
+#define _CRT_SECURE_NO_WARNINGS
+#define _CRT_NONSTDC_NO_WARNINGS
+#include <windows.h>
+#include <io.h>
+#include "../Win32/w32def.h"
+#endif	//	_WIN32
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef __linux__
+#include <sys/file.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <linux/limits.h>
+#include <sys/shm.h>
+#endif	//	__linux__
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "defines.h"
+#include "mutex.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define _IS_VALID_SHMID(id)				((id) >= 0)
+
+/////////////////////////////////////////////////////////////////////////////
+
+CLocalMutex::CLocalMutex(void) : m_bInit(false)
+{
+	memset(&m_mutex, 0, sizeof(m_mutex));
+}
+
+CLocalMutex::~CLocalMutex(void)
+{
+	Release();
+}
+
+bool CLocalMutex::Create(void)
+{
+	if(!m_bInit)
+	{
+		if(!::pthread_mutex_init(&m_mutex, NULL))
+		{
+			TRACE("CLocalMutex::Create: Created Mutex\n");
+			m_bInit = true;
+		}
+		else
+		{
+			TRACE("CLocalMutex::Create failed!\n");
+		}
+	}
+	
+	return m_bInit;
+}
+
+void CLocalMutex::Release(void)
+{
+	if(m_bInit)
+	{
+		::pthread_mutex_destroy(&m_mutex);
+		m_bInit = false;
+		TRACE("CLocalMutex::Release: Mutex released.\n");
+	}
+}
+
+bool CLocalMutex::Lock(void)
+{
+	return !::pthread_mutex_lock(&m_mutex);
+}
+
+bool CLocalMutex::TryLock(void)
+{
+	return !::pthread_mutex_trylock(&m_mutex);
+}
+
+bool CLocalMutex::Unlock(void)
+{
+	return !::pthread_mutex_unlock(&m_mutex);
+}

+ 222 - 199
src/mutex.cpp

@@ -1,199 +1,222 @@
-#ifdef _WIN32
-#define _CRT_SECURE_NO_WARNINGS
-#define _CRT_NONSTDC_NO_WARNINGS
-#include <windows.h>
-#include <io.h>
-#include "../Win32/w32def.h"
-#endif	//	_WIN32
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#ifdef __linux__
-#include <sys/file.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
-#include <linux/limits.h>
-#include <sys/shm.h>
-#endif	//	__linux__
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "defines.h"
-#include "mutex.h"
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define _IS_VALID_SHMID(id)				((id) >= 0)
-
-/////////////////////////////////////////////////////////////////////////////
-
-CGlobalMutex::CGlobalMutex(void) :	m_nShmID(_INVALID_ID), m_pMutex(NULL)
-{
-	memset(&m_mutexAttr, 0, sizeof(m_mutexAttr));
-	::pthread_mutexattr_init(&m_mutexAttr);
-	::pthread_mutexattr_setpshared(&m_mutexAttr, PTHREAD_PROCESS_SHARED);
-	::pthread_mutexattr_settype(&m_mutexAttr, PTHREAD_MUTEX_RECURSIVE);
-}
-
-CGlobalMutex::~CGlobalMutex(void)
-{
-	Release();
-}
-
-int CGlobalMutex::Create(const uuid_t &ruuid, const char *pszDir)
-{
-	if(!pszDir)
-		pszDir = "";
-
-	size_t nLenReq = strlen(pszDir) + _UUID_STRING_LEN + 2;
-
-	if(nLenReq > PATH_MAX)
-	{
-		TRACE("CGlobalMutex::Create: directory name too long\n");
-		errno = EINVAL;
-		return -1;
-	}
-
-	int nRet = -1;
-	char szUuid[_UUID_STRING_LEN + 1];
-	char szShm[PATH_MAX];
-	_uuid_unparse(&ruuid, szUuid, sizeof(szUuid));
-	sprintf(szShm, "%s/%s.mtx", pszDir, szUuid);
-
-	int nFdShm;
-
-	if((nFdShm = ::open(szShm, O_RDWR | O_CREAT | O_TRUNC, _NUMBER_OF_THE_BEAST)) >= 0)
-	{
-		key_t shmKey;
-
-		if((shmKey = ::ftok(szShm, 'R')) >= 0)
-		{
-			if((m_nShmID = ::shmget(shmKey, sizeof(pthread_mutex_t), IPC_CREAT | _NUMBER_OF_THE_BEAST)) >= 0)
-			{
-				struct shmid_ds sds;
-				memset(&sds, 0, sizeof(sds));
-
-				if(!::shmctl(m_nShmID, IPC_STAT, (struct shmid_ds*)&sds))
-				{
-					m_pMutex = (pthread_mutex_t*)::shmat(m_nShmID, NULL, 0);
-
-					if(!sds.shm_atime)
-					{
-						if(!(nRet = ::pthread_mutex_init(m_pMutex, &m_mutexAttr)))
-						{
-							TRACE("CGlobalMutex::Create: Created new Mutex\n");
-							nRet = 1;
-						}
-						else
-						{
-							TRACE("CGlobalMutex::Create failed! Code: %d\n", nRet);
-							nRet = -1;
-						}
-					}
-					else
-					{
-						TRACE("CGlobalMutex::Create: Opened existing Mutex\n");
-						nRet = 0;
-					}
-				}
-				else
-				{
-					TRACE("CGlobalMutex::Create: IPC_STAT failed - errno: %d!\n", errno);
-				}
-			}
-			else
-			{
-				TRACE("CGlobalMutex::Create: Failed to create SHM on Key: 0x%08X - errno: %d!\n", shmKey, errno);
-			}
-		}
-		else
-		{
-			TRACE("CGlobalMutex::Create: Failed to create shmKey - errno: %d!\n", errno);
-		}
-
-		close(nFdShm);
-	}
-	else
-	{
-		TRACE("CGlobalMutex::Create: Failed to open '%s' - errno: %d!\n", szShm, errno);
-	}
-
-	return nRet;
-}
-	
-long CGlobalMutex::Release(void)
-{
-	struct shmid_ds sds;
-	sds.shm_nattch = (shmatt_t)-1;
-
-	if(_IS_VALID_SHMID(m_nShmID) && m_pMutex)
-	{
-		if(!::shmctl(m_nShmID, IPC_STAT, (struct shmid_ds*)&sds))
-		{
-			if((long)sds.shm_nattch > 1)
-			{
-				::pthread_mutexattr_destroy(&m_mutexAttr);
-				::shmdt(m_pMutex);
-				::shmctl(m_nShmID, IPC_STAT, (struct shmid_ds*)&sds);
-				TRACE("CGlobalMutex::Release: Still attached: %ld!\n", (long)(sds.shm_nattch));
-			}
-			else if((long)sds.shm_nattch == 1)
-			{
-				::pthread_mutex_destroy(m_pMutex);
-				::pthread_mutexattr_destroy(&m_mutexAttr);
-				::shmdt(m_pMutex);
-				::shmctl(m_nShmID, IPC_RMID, NULL);
-				sds.shm_nattch = 0;
-				TRACE("CGlobalMutex::Release: Mutex removed!\n");
-			}
-		}
-		else
-		{
-			sds.shm_nattch = (shmatt_t)-1;
-			TRACE("CGlobalMutex::Release: IPC_STAT failed!\n");
-		}
-
-		m_pMutex = NULL;
-		m_nShmID = _INVALID_ID;
-	}
-
-	return (long)sds.shm_nattch;
-}
-
-bool CGlobalMutex::Lock(void)
-{
-	if(m_pMutex)
-		return !::pthread_mutex_lock(m_pMutex);
-	else
-	{
-		TRACE("CGlobalMutex::Lock: Invalid Mutex: %p!\n", m_pMutex);
-		errno = EINVAL;
-		return false;
-	}
-}
-
-bool CGlobalMutex::TryLock(void)
-{
-	if(m_pMutex)
-		return !::pthread_mutex_trylock(m_pMutex);
-	else
-	{
-		TRACE("CGlobalMutex::Lock: Invalid Mutex: %p!\n", m_pMutex);
-		errno = EINVAL;
-		return false;
-	}
-}
-
-bool CGlobalMutex::Unlock(void)
-{
-	if(m_pMutex)
-		return !::pthread_mutex_unlock(m_pMutex);
-	else
-	{
-		TRACE("CGlobalMutex::Lock: Invalid Mutex: %p!\n", m_pMutex);
-		errno = EINVAL;
-		return false;
-	}
-}
+#ifdef _WIN32
+#define _CRT_SECURE_NO_WARNINGS
+#define _CRT_NONSTDC_NO_WARNINGS
+#include <windows.h>
+#include <io.h>
+#include "../Win32/w32def.h"
+#endif	//	_WIN32
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef __linux__
+#include <sys/file.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <linux/limits.h>
+#include <sys/shm.h>
+#endif	//	__linux__
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "defines.h"
+#include "mutex.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define _IS_VALID_SHMID(id)				((id) >= 0)
+
+/////////////////////////////////////////////////////////////////////////////
+
+CGlobalMutex::CGlobalMutex(void) :	m_nShmID(_INVALID_ID), m_pMutex(NULL)
+{
+	memset(&m_mutexAttr, 0, sizeof(m_mutexAttr));
+	::pthread_mutexattr_init(&m_mutexAttr);
+	::pthread_mutexattr_setpshared(&m_mutexAttr, PTHREAD_PROCESS_SHARED);
+	::pthread_mutexattr_settype(&m_mutexAttr, PTHREAD_MUTEX_RECURSIVE);
+	::pthread_mutexattr_setrobust(&m_mutexAttr, PTHREAD_MUTEX_ROBUST);
+}
+
+CGlobalMutex::~CGlobalMutex(void)
+{
+	Release();
+}
+
+int CGlobalMutex::Create(const uuid_t &ruuid, const char *pszDir)
+{
+	if(!pszDir)
+		pszDir = "";
+
+	size_t nLenReq = strlen(pszDir) + _UUID_STRING_LEN + 2;
+
+	if(nLenReq > PATH_MAX)
+	{
+		TRACE("CGlobalMutex::Create: directory name too long\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	int nRet = -1;
+	char szUuid[_UUID_STRING_LEN + 1];
+	char szShm[PATH_MAX];
+	_uuid_unparse(&ruuid, szUuid, sizeof(szUuid));
+	sprintf(szShm, "%s/%s.mtx", pszDir, szUuid);
+
+	int nFdShm;
+
+	if((nFdShm = ::open(szShm, O_RDWR | O_CREAT | O_TRUNC, _NUMBER_OF_THE_BEAST)) >= 0)
+	{
+		key_t shmKey;
+
+		if((shmKey = ::ftok(szShm, 'R')) >= 0)
+		{
+			if((m_nShmID = ::shmget(shmKey, sizeof(pthread_mutex_t), IPC_CREAT | _NUMBER_OF_THE_BEAST)) >= 0)
+			{
+				struct shmid_ds sds;
+				memset(&sds, 0, sizeof(sds));
+
+				if(!::shmctl(m_nShmID, IPC_STAT, (struct shmid_ds*)&sds))
+				{
+					m_pMutex = (pthread_mutex_t*)::shmat(m_nShmID, NULL, 0);
+
+					if(!sds.shm_atime)
+					{
+						if(!(nRet = ::pthread_mutex_init(m_pMutex, &m_mutexAttr)))
+						{
+							TRACE("CGlobalMutex::Create: Created new Mutex\n");
+							nRet = 1;
+						}
+						else
+						{
+							TRACE("CGlobalMutex::Create failed! Code: %d\n", nRet);
+							nRet = -1;
+						}
+					}
+					else
+					{
+						TRACE("CGlobalMutex::Create: Opened existing Mutex\n");
+						nRet = 0;
+					}
+				}
+				else
+				{
+					TRACE("CGlobalMutex::Create: IPC_STAT failed - errno: %d!\n", errno);
+				}
+			}
+			else
+			{
+				TRACE("CGlobalMutex::Create: Failed to create SHM on Key: 0x%08X - errno: %d!\n", shmKey, errno);
+			}
+		}
+		else
+		{
+			TRACE("CGlobalMutex::Create: Failed to create shmKey - errno: %d!\n", errno);
+		}
+
+		close(nFdShm);
+	}
+	else
+	{
+		TRACE("CGlobalMutex::Create: Failed to open '%s' - errno: %d!\n", szShm, errno);
+	}
+
+	return nRet;
+}
+	
+long CGlobalMutex::Release(void)
+{
+	struct shmid_ds sds;
+	sds.shm_nattch = (shmatt_t)-1;
+
+	if(_IS_VALID_SHMID(m_nShmID) && m_pMutex)
+	{
+		if(!::shmctl(m_nShmID, IPC_STAT, (struct shmid_ds*)&sds))
+		{
+			if((long)sds.shm_nattch > 1)
+			{
+				::pthread_mutexattr_destroy(&m_mutexAttr);
+				::shmdt(m_pMutex);
+				::shmctl(m_nShmID, IPC_STAT, (struct shmid_ds*)&sds);
+				TRACE("CGlobalMutex::Release: Still attached: %ld!\n", (long)(sds.shm_nattch));
+			}
+			else if((long)sds.shm_nattch == 1)
+			{
+				::pthread_mutex_destroy(m_pMutex);
+				::pthread_mutexattr_destroy(&m_mutexAttr);
+				::shmdt(m_pMutex);
+				::shmctl(m_nShmID, IPC_RMID, NULL);
+				sds.shm_nattch = 0;
+				TRACE("CGlobalMutex::Release: Mutex removed!\n");
+			}
+		}
+		else
+		{
+			sds.shm_nattch = (shmatt_t)-1;
+			TRACE("CGlobalMutex::Release: IPC_STAT failed!\n");
+		}
+
+		m_pMutex = NULL;
+		m_nShmID = _INVALID_ID;
+	}
+
+	return (long)sds.shm_nattch;
+}
+
+bool CGlobalMutex::Lock(void)
+{
+	if(m_pMutex)
+	{
+		int nRet = ::pthread_mutex_lock(m_pMutex);
+		if(nRet == EOWNERDEAD)
+		{
+			TRACE("CGlobalMutex::Lock: Former owner process has died - gained ownership!\n");
+			::pthread_mutex_consistent(m_pMutex);
+			nRet = 0;
+		}
+//		TRACE("CGlobalMutex::Lock: Locked: %d.\n", m_nShmID);
+		return !nRet;
+	}
+	else
+	{
+		TRACE("CGlobalMutex::Lock: Invalid Mutex: %p!\n", m_pMutex);
+		errno = EINVAL;
+		return false;
+	}
+}
+
+bool CGlobalMutex::TryLock(void)
+{
+	if(m_pMutex)
+	{
+		int nRet = ::pthread_mutex_trylock(m_pMutex);
+		if(nRet == EOWNERDEAD)
+		{
+			TRACE("CGlobalMutex::TryLock: Former owner process has died - gained ownership!\n");
+			::pthread_mutex_consistent(m_pMutex);
+			nRet = 0;
+		}
+		return !nRet;
+	}
+	else
+	{
+		TRACE("CGlobalMutex::TryLock: Invalid Mutex: %p!\n", m_pMutex);
+		errno = EINVAL;
+		return false;
+	}
+}
+
+bool CGlobalMutex::Unlock(void)
+{
+	if(m_pMutex)
+	{
+//		TRACE("CGlobalMutex::Unlock: Unlocked: %d.\n", m_nShmID);
+		return !::pthread_mutex_unlock(m_pMutex);
+	}
+	else
+	{
+		TRACE("CGlobalMutex::Unlock: Invalid Mutex: %p!\n", m_pMutex);
+		errno = EINVAL;
+		return false;
+	}
+}

+ 20 - 0
src/mutex.h

@@ -41,5 +41,25 @@ private:
 	pthread_mutex_t *m_pMutex;
 };
 
+/////////////////////////////////////////////////////////////////////////////
+
+class CLocalMutex
+{
+public:
+	CLocalMutex(void);
+	virtual ~CLocalMutex(void);
+
+	bool Create(void);
+	void Release(void);
+
+	bool Lock(void);
+	bool TryLock(void);
+	bool Unlock(void);
+
+private:
+	bool m_bInit;
+	pthread_mutex_t m_mutex;
+};
+
 /////////////////////////////////////////////////////////////////////////////
 #endif	//	!defined(AGD_MUTEX_H__307A751D_EF2D_45D6_BBA8_2EB4B79B548D__INCLUDED_)

+ 78 - 1
src/shm.cpp

@@ -85,7 +85,7 @@ int CShm::Create(const uuid_t &ruuid, size_t nCbShm, const char *pszDir)
 		return -1;
 
 	int nFdShm;
-	CShmLocker locker(m_mutex);
+//	CShmLocker locker(m_mutex);
 
 	if((nFdShm = ::open(szShm, O_RDWR | O_CREAT | O_TRUNC, _NUMBER_OF_THE_BEAST)) >= 0)
 	{
@@ -281,6 +281,83 @@ int CShm::Unlock(void)
 	return m_mutex.Unlock();
 }
 
+long CShm::InterlockedIncrement(volatile long *pl)
+{
+	if(!pl)
+	{
+		TRACE("CShm::InterlockedIncrement: Invalid Argument!\n");
+		return 0;
+	}
+
+	long l;
+	m_mutex.Lock();
+	l = ++(*pl);
+	m_mutex.Unlock();
+	return l;
+}
+
+long CShm::InterlockedDecrement(volatile long *pl)
+{
+	if(!pl)
+	{
+		TRACE("CShm::InterlockedDecrement: Invalid Argument!\n");
+		return 0;
+	}
+
+	long l;
+	m_mutex.Lock();
+	l = --(*pl);
+	m_mutex.Unlock();
+	return l;
+}
+
+long CShm::InterlockedCompare(volatile long *pl, long comparand)
+{
+	if(!pl)
+	{
+		TRACE("CShm::InterlockedCompare: Invalid Argument!\n");
+		return 0;
+	}
+
+	long l;
+	m_mutex.Lock();
+	l = *pl - comparand;
+	m_mutex.Unlock();
+	return l;
+}
+
+long CShm::InterlockedSet(volatile long *pl, long val)
+{
+	if(!pl)
+	{
+		TRACE("CShm::InterlockedSet: Invalid Argument!\n");
+		return 0;
+	}
+
+	long l;
+	m_mutex.Lock();
+	l = *pl;
+	*pl = val;
+	m_mutex.Unlock();
+	return l;
+}
+
+long CShm::InterlockedClear(volatile long *pl)
+{
+	if(!pl)
+	{
+		TRACE("CShm::InterlockedClear: Invalid Argument!\n");
+		return 0;
+	}
+
+	long l;
+	m_mutex.Lock();
+	l = *pl;
+	*pl = 0;
+	m_mutex.Unlock();
+	return l;
+}
+
 /////////////////////////////////////////////////////////////////////////////
 
 void CShm::DumpIpcPerm(struct ipc_perm *ip)

+ 6 - 1
src/shm.h

@@ -52,6 +52,12 @@ public:
 	const uuid_t& Uuid() const {
 		return m_uuid;}
 
+	long InterlockedIncrement(volatile long *pl);
+	long InterlockedDecrement(volatile long *pl);
+	long InterlockedCompare(volatile long *pl, long comparand);
+	long InterlockedSet(volatile long *pl, long val);
+	long InterlockedClear(volatile long *pl);
+
 	static void DumpIpcPerm(struct ipc_perm *ip);
 	static void DumpShmidDs(struct shmid_ds *sid);
 
@@ -59,7 +65,6 @@ private:
 
 private:
 	int m_nShmID;
-//	CShmSemaphore m_sema;
 	CGlobalMutex m_mutex;
 	uuid_t m_uuid;
 };

+ 46 - 17
src/shmrot.cpp

@@ -67,6 +67,7 @@ bool CShmROT::Create(void)
 		{
 			if(m_pTable->version != _ROT_CURRENT_VERSION)
 			{
+				// ...
 			}
 		}
 
@@ -125,12 +126,12 @@ CShm* CShmROT::AcquireShm(const char *pszUuid, size_t nSizeElement, size_t nCntE
 		}
 	}
 
-	if(nIndexFound >= 0)
+	if(nIndexFound >= 0) // found existing entry
 	{
 		SHMROT_ENTRY &re = m_pTable->rot[nIndexFound];
+		bool bMatch = (re.nSizeElement == nSizeElement) && (re.nCntElements == nCntElements);
 
-		if(	(re.nSizeElement == nSizeElement) &&
-			(re.nCntElements == nCntElements))
+		if(bMatch)
 		{
 			TRACE("CShmROT::AcquireShm: Found matching SHM entry!\n");
 
@@ -143,6 +144,10 @@ CShm* CShmROT::AcquireShm(const char *pszUuid, size_t nSizeElement, size_t nCntE
 					pShm = NULL;
 					TRACE("CShmROT::AcquireShm: Failed to create new CShm!\n");
 				}
+				else
+				{
+					re.nCntHandles++;
+				}
 			}
 			else
 			{
@@ -154,7 +159,7 @@ CShm* CShmROT::AcquireShm(const char *pszUuid, size_t nSizeElement, size_t nCntE
 			TRACE("CShmROT::AcquireShm: SHM uuid exists, but size does not match!\n");
 		}
 	}
-	else if(nFirstUnusedIndex >= 0)
+	else if(nFirstUnusedIndex >= 0) // next free slot
 	{
 		TRACE("CShmROT::AcquireShm: Create new SHM entry!\n");
 
@@ -174,6 +179,7 @@ CShm* CShmROT::AcquireShm(const char *pszUuid, size_t nSizeElement, size_t nCntE
 				re.flags		= _SHMROT_ENTRY_FLAG_VALID;
 				re.nSizeElement	= (uint32_t)nSizeElement;
 				re.nCntElements	= (uint32_t)nCntElements;
+				re.nCntHandles	= 1;
 				_uuid_copy(&re.uuid, &uuid);
 				memset(re.szDescName, 0, sizeof(re.szDescName));
 
@@ -198,7 +204,7 @@ CShm* CShmROT::AcquireShm(const char *pszUuid, size_t nSizeElement, size_t nCntE
 	}
 	else
 	{
-		TRACE("CShmROT::AcquireShm: SHM uuid not found and no free entries!\n");
+		TRACE("CShmROT::AcquireShm: SHM uuid not found and no slot available!\n");
 	}
 
 	return pShm;
@@ -208,24 +214,30 @@ void CShmROT::ReleaseShm(CShm *pShm)
 {
 	if(pShm)
 	{
-		if(pShm->Release() == 0)
+		const uuid_t &ruuid = pShm->Uuid();
+
+		for(int i = 0; i < (int)m_pTable->maxEntries; i++)
 		{
-			const uuid_t &ruuid = pShm->Uuid();
+			SHMROT_ENTRY &re = m_pTable->rot[i];
 
-			for(int i = 0; i < (int)m_pTable->maxEntries; i++)
+			if(!_uuid_compare(&re.uuid, &ruuid))
 			{
-				SHMROT_ENTRY &re = m_pTable->rot[i];
-
-				if(!_uuid_compare(&re.uuid, &ruuid))
+				if(re.flags & _SHMROT_ENTRY_FLAG_VALID)
 				{
-					re.flags &= ~_SHMROT_ENTRY_FLAG_VALID;
-					break;
+					if(re.nCntHandles > 0)
+						--re.nCntHandles;
+						
+					if(re.nCntHandles == 0)
+						re.flags &= ~_SHMROT_ENTRY_FLAG_VALID;
 				}
+
+				break;
 			}
 		}
 
+		pShm->Release();
 		delete pShm;
-        }
+	}
 }
 
 int CShmROT::Lock(void)
@@ -238,7 +250,7 @@ int CShmROT::Unlock(void)
 	return m_shmRot.Unlock();
 }
 
-void CShmROT::DumpEntries(void)
+void CShmROT::DumpEntries(CShmHandleMap &map)
 {
 	if(!m_pTable)
 	{
@@ -256,13 +268,30 @@ void CShmROT::DumpEntries(void)
 
 		if(re.flags & _SHMROT_ENTRY_FLAG_VALID)
 		{
+			unsigned long nAttached = 0;
 			_uuid_unparse(&re.uuid, szUuid, sizeof(szUuid));
-			printf("uuid: '%s',\n    flags: %08X,\n    size of element: %u,\n    count of elements: %u,\n    name: '%s'\n",
+
+			if(re.nCntHandles > 0)
+			{
+				CShm *pShm = map.LookupShm(re.uuid);
+				if(pShm)
+					nAttached = pShm->GetNumAttached();
+			}
+
+			printf(	"uuid: '%s',\n"						\
+					"    flags:              0x%08x,\n"	\
+					"    size of element:    %u,\n"		\
+					"    number of elements: %u,\n"		\
+					"    name:               '%s',\n"	\
+					"    number of handles:  %u,\n"		\
+					"    number of pointers: %lu\n",
 					szUuid,
 					re.flags,
 					re.nSizeElement,
 					re.nCntElements,
-					re.szDescName);
+					re.szDescName,
+					re.nCntHandles,
+					nAttached);
 		}
 	}
 

+ 30 - 2
src/shmrot.h

@@ -4,11 +4,38 @@
 #if !defined(AGD_SHMROT_H__58C9857B_4E4E_4AE1_B093_DFECBB85F652__INCLUDED_)
 #define AGD_SHMROT_H__58C9857B_4E4E_4AE1_B093_DFECBB85F652__INCLUDED_
 
+#include "gfaipc.h"
 #include "shm.h"
 
 /////////////////////////////////////////////////////////////////////////////
 // shmrot.h - Declarations:
 
+typedef struct _SHM_HANDLE
+{
+	CShm *pShm;
+}SHM_HANDLE, *LPSHM_HANDLE;
+typedef const SHM_HANDLE *LPCSHM_HANDLE;
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define _IPCSHM_MAX_HANDLES			32
+
+class CShmHandleMap
+{
+public:
+	CShmHandleMap(void);
+	~CShmHandleMap(void);
+
+	HSHM AcquireHandle(CShm *pShm);
+	void ReleaseHandle(HSHM hShm);
+	CShm* LookupShm(const uuid_t &uuid);
+
+private:
+	SHM_HANDLE m_handles[_IPCSHM_MAX_HANDLES];
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
 #define _ROT_MAX_TABLE_ENTRIES			32
 #define _ROT_MAX_ENTRY_NAME				128
 
@@ -25,7 +52,8 @@ typedef struct _SHMROT_ENTRY
 	uint32_t flags;
 	uint32_t nSizeElement;
 	uint32_t nCntElements;
-	uint32_t reserved[5];
+	uint32_t nCntHandles;
+	uint32_t reserved[4];
 	char szDescName[_ROT_MAX_ENTRY_NAME];
 }SHMROT_ENTRY, *LPSHMROT_ENTRY;
 typedef const SHMROT_ENTRY *LPCSHMROT_ENTRY;
@@ -60,7 +88,7 @@ public:
 	bool Created(void) const {
 		return !!m_pTable;}
 
-	void DumpEntries(void);
+	void DumpEntries(CShmHandleMap &map);
 
 private:
 	CShm m_shmRot;

+ 79 - 0
src/shmstrvar.cpp

@@ -0,0 +1,79 @@
+#include "shmvar.h"
+#include <QDebug>
+
+#define _IS_VALID_VT(vt)		((vt > CShmStringVariable::VT_Invalid) && (vt < CShmStringVariable::VT_Last))
+
+CShmStringVariable::CShmStringVariable(void *pData, size_t nCChData, VT vt, const std::type_info &rti, HSHM hShm, const char *pszName, int nIndex, QObject *pParent)
+{
+	if(!pData || !hShm || !nCChData || !_IS_VALID_VT(vt))
+	{
+		Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid parameter!");
+		return;
+	}
+
+    m_data.pVoid = pData;
+    m_hShm = hShm;
+    setObjectName(QStringLiteral("CShmVariable"));
+    if((m_nIndex = nIndex) >= 0)
+	{
+		m_varName += QString("%1%2%3").arg('[').arg(nIndex).arg(']');
+	}
+
+    if((rti == typeid(signed char)) || (rti == typeid(unsigned char)))
+    {
+    }
+    else if(rti == typeid(wchar_t))
+	{
+	}
+    else
+	{
+		Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Unknown data type!");
+	}
+}
+
+CShmStringVariable::~CShmStringVariable(void)
+{
+}
+
+void CShmStringVariable::valRaw(QString &v)
+{
+}
+
+QString CShmStringVariable::val(void)
+{
+}
+
+void CShmStringVariable::setVal(const QString &val)
+{
+}
+
+unsigned long long CShmStringVariable::CheckUpdateShm(bool fLock)
+{
+	return 0;
+}
+
+
+void CShmStringVariable::Lock(void)
+{
+	::GfaIpcLockSHM(m_hShm);
+//	qDebug() << "CShmStringVariable::Lock";
+}
+
+void CShmStringVariable::Unlock(void)
+{
+//	qDebug() << "CShmStringVariable::Unlock";
+	::GfaIpcUnlockSHM(m_hShm);
+}
+
+void CShmStringVariable::emitChanged(bool fLock)
+{
+//    qDebug() << "CShmStringVariable: val changed!";
+	if(fLock)
+	    emit valChanged(val());
+	else
+	{
+	    QString v;
+	    valRaw(v);
+	    emit valChanged(v);
+	}
+}