Reputation: 655
I'm storing a dynamically created 2-dimensional array in shared memory using shm_open, ftruncate, and mmap. When I make an update to the array the update is only seen in the process that made that update, and none of the other processes using that shared memory mapping. Without further ado-- the code(relevant bits):
int fd;
int** graph;
fd = shm_open("/graph", O_RDWR|O_CREAT, 0666);
ftruncate(fd, sizeof(int)*numVertices*numVertices);
graph = (int**) mmap(NULL, sizeof(int)*numVertices*numVertices, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
foo(numVertices, fd);
/* Down to function definition */
void foo(int numVertices, int fd) {
int i=0;
for (i; i<num_processes; i++) {
int pid = fork();
if (pid == 0) {
int **graph = (int**) mmap(NULL, sizeof(int)*numVertices*numVertices, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
graph_algorithm(i, numVertices, graph);
}
}
}
void graph_algorithm(int proc_num, int numVertices, int** graph) {
pthread_mutex_lock(&mutex);
if (proc_num == 0) {
graph[0][0] = 1;
}
pthread_mutex_unlock(&mutex);
printf("Process %d: %d\n", proc_num, graph[0][0]);
}
When the print is done in graph_algorithm the process with proc_num 0 has 1 at graph[0][0], but all the others maintain the old value of 0. I omitted error checking for the fork and mmap-- but that is the gist of the problem. I also tried calling msync(graph, sizeof(int)*numVertices*numVertices, MS_SYNC) after the graph[0][0] = 1 but to no avail. This is my first time working with shared memory and I can't find out what I'm doing wrong. This problem hasn't come up on here, or any other site as far as I've seen. Any help is greatly appreciated.
Upvotes: 0
Views: 1175
Reputation: 41
There is clearly a problem with your mutex. Unless the mutex is shared among the processes it won't prevent concurrent access between the processes. I don't even see a definition or initialization of it.
There is also a race. Even if the mutex is shared, the printf in any other process is not guaranteed to after before process 0.
You should have a method of synchronizing at the end of the graph algorithm, before accessing the results, to ensure all are finished.
There is no issue with the 2D array, so long as the processes all agree on the dimensions.
Upvotes: 2
Reputation: 2551
I suspect the problem is your use of a double pointer, especially given that you aren't specifying to graph_algorithm()
what the dimensions of graph
is. In this context, graph[0][0]
is going to be equivalent to *(*graph)
, which may or may not point into the mapped memory. You need to make sure your array points to a single contiguous area of mapped memory. You can still get a 2d-array as long as you know at least one of the dimensions. So instead of graph[x][y]
you would use graph[x * numVertices + y]
. Depending on your compiler, you might still be able to use a double array, but you need to explicitly provide one of the dimensions of graph
. So your prototype for graph_algorithm
would become something like
void graph_algorithm(int proc_num, int numVertices, int graph[][numVertices])
Upvotes: 4