Blame view

src/SERVER/DD_CacheLock.c 3.82 KB
86f177cf   Benjamin Renard   Lock system imple...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*=====================================================================
 *                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 <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <pthread.h>

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);
}