/*===================================================================== * DD SYSTEM base package * DD_Server library * DD_CacheLock.c * V.1.0 * Last revision: * May 29 2015: Version 1.0. First implementation of a lock system for concurrent access to a virtual instrument */ #include #include #include #include typedef struct { char VIID[30]; pthread_mutex_t mutex; } CacheLockVI; #define NB_CACHELOCK_VI 30 typedef struct { CacheLockVI cacheLockVI[NB_CACHELOCK_VI]; pthread_mutex_t mutex; } CacheLockData; extern int Verbose; static CacheLockData* cachelock_data = NULL; /* * Init the shared memory used by the lock system */ void CacheLock_Init() { if (cachelock_data != NULL) return; if(Verbose) fprintf(stderr,"CacheLock_Init\n"); // place our shared data in shared memory int prot = PROT_READ | PROT_WRITE; int flags = MAP_SHARED | MAP_ANONYMOUS; cachelock_data = mmap(NULL, sizeof(CacheLockData), prot, flags, -1, 0); // initialise mutex so it works properly in shared memory // global mutex pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&cachelock_data->mutex, &attr); int i; for (i = 0; i < NB_CACHELOCK_VI; ++i) { // virtual instrument mutex pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&cachelock_data->cacheLockVI[i].mutex, &attr); } } /* * Free the shared memory used by the lock system */ void CacheLock_Free() { if(Verbose) fprintf(stderr,"CacheLock_Free\n"); if (cachelock_data != NULL) munmap(cachelock_data, sizeof(CacheLockData)); cachelock_data = NULL; } /* * Get and lock the access to a virtual instrument */ void CacheLock_Lock(char* VIID) { if (cachelock_data == NULL) return; int i; pthread_mutex_lock(&cachelock_data->mutex); for (i = 0; i < NB_CACHELOCK_VI; ++i) { if (strcmp(VIID, cachelock_data->cacheLockVI[i].VIID) == 0) { //A cache lock already exist for this VI //Try to get access pthread_mutex_lock(&cachelock_data->cacheLockVI[i].mutex); if(Verbose) fprintf(stderr,"CacheLock_Lock. %s is locked\n", VIID); pthread_mutex_unlock(&cachelock_data->mutex); return; } } pthread_mutex_unlock(&cachelock_data->mutex); //No cache lock exist for this VI //Try to find an available cache lock while (1) { pthread_mutex_lock(&cachelock_data->mutex); for (i = 0; i < NB_CACHELOCK_VI; ++i) { if (pthread_mutex_trylock(&cachelock_data->cacheLockVI[i].mutex) == 0) { //This cache lock is now used for this VIID strcpy(cachelock_data->cacheLockVI[i].VIID, VIID); if(Verbose) fprintf(stderr,"CacheLock_Lock. %s is locked\n", VIID); pthread_mutex_unlock(&cachelock_data->mutex); return; } } //No available cache lock for the moment if(Verbose) fprintf(stderr,"CacheLock_Lock. Cannot find an available cache lock for %s => Wait and retry later\n", VIID); pthread_mutex_unlock(&cachelock_data->mutex); sleep(2); } } /* * Unlock the access to a virtual instrument */ void CacheLock_Unlock(char* VIID) { if (cachelock_data == NULL) return; int i; for (i = 0; i < NB_CACHELOCK_VI; ++i) { if (strcmp(VIID, cachelock_data->cacheLockVI[i].VIID) == 0) { if(Verbose) fprintf(stderr,"CacheLock_Unlock. %s is unlocked\n", VIID); pthread_mutex_unlock(&cachelock_data->cacheLockVI[i].mutex); return; } } if(Verbose) fprintf(stderr,"CacheLock_Unlock. Cannot unlock %s\n", VIID); }