Synchronized access to data in shared memory between two processes [duplicate] - c

This question already has answers here:
How do I synchronize access to shared memory in LynxOS/POSIX?
(4 answers)
Closed 6 years ago.
I have two processes that have data in shared memory. This data is going to be updated by both of these process. I was looking for some locking mechanism between two processes. With threads it was easy to have a shared mutex lock. In my case, I tried to save the mutex variable in the shared memory, which then will be used by both processes for locking. This didn't work though. How do I share a mutex between two processes. Some say mutexes cannot be shared, use semaphores. Why mutex cannot be shared but semaphores can be?

It is possible, you have to use the flag PTHREAD_PROCESS_SHARED:
pthread_mutexattr_t mattr;
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
// Init the shared mem barrier
if ( (rv = pthread_mutex_init(&nshared, &mattr)) != 0 ) {
fprintf(stderr, "Failed to initiliaze the shared mutex.\n");
return rv;
}
Where the variable nshared is mapped in shared memory.
Take a look at this documentation. Also, keep in mind that the default value for the mutex is to not share it among processes.
also, take a look at these posts post1 post2
Bonus code to chek the status of the mutex:
void showPshared(pthread_mutexattr_t *mta) {
int rc;
int pshared;
printf("Check pshared attribute\n");
rc = pthread_mutexattr_getpshared(mta, &pshared);
printf("The pshared attributed is: ");
switch (pshared) {
case PTHREAD_PROCESS_PRIVATE:
printf("PTHREAD_PROCESS_PRIVATE\n");
break;
case PTHREAD_PROCESS_SHARED:
printf("PTHREAD_PROCESS_SHARED\n");
break;
default :
printf("! pshared Error !\n");
exit(1);
}
return;
}
I don't remember were I took this piece of code ... found it! here is the source of hal knowledge.

Related

Two threads accessing a locked mutex simultaneously

I have written this code in C language and there are two pthreads that are using this code and trying to access the mutex "firstSection" (in both of them we are sure that the mutex passed to function is the same). The code suppose to check two mutexes, and if both of them were available, performs some actions which take place in function safeUnlockTwoMutexes(), and if failed to acquire at least one of them, it has to wait for two seconds and tries again. ("intersection" mutex is the main-lock to safe check the situation of the other mutexes)
void twoSectionRoute(pthread_mutex_t firstSection, pthread_mutex_t secondSection){
bool pathClear = false;
while (!pathClear){
pthread_mutex_lock(&intersection);
if (pthread_mutex_trylock(&firstSection) == 0){
if (pthread_mutex_trylock(&secondSection) == 0){
pathClear = true;
pthread_mutex_unlock(&intersection);
} else {
pthread_mutex_unlock(&firstSection);
pthread_mutex_unlock(&intersection);
sleep(2);
}
} else {
pthread_mutex_unlock(&intersection);
sleep(2);
}
}
safeUnlockTwoMutexes(firstSection, secondSection, 1);
}
Now the problem with this code is both threads are able to lock the mutex "firstSectio" at almost same time and I don't know why. (maybe because its type is recursive mutex?! I've used "PTHREAD_MUTEX_INITIALIZER" in the beginning of the file as global variables)
I'm wondering how can I fix this issue, and the threads access this sections one after another?
Your function signature passes pthread_mutex_t values firstSection and secondSection by value. You need to pass mutexes by pointer.
void twoSectionRoute(pthread_mutex_t* firstSection, pthread_mutex_t* secondSection){
Then, within the function use just firstSection and secondSection rather than &firstSection and &secondSection.
If you pass the mutex by value (as here), and it compiles, then the mutex itself is copied, so you end up with undefined behaviour and the mutex locks do not operate on the same state.

fork and exec with respect to locking shared memory - C

So I'm just wondering if I had a simple task to do in concurrency, how would I do this with multiple processes using fork() and exec() from a parent process, while locking some aspects of the parent process' memory (so that they don't overwrite each other), but making it available to those processes later?
I know I can do this with POSIX threads with their mutex locks, but what's the process equivalent to that? Is there a way to "lock" shared memory amongst threads? And then would I have to "wait()" for the other threads to finish those locked areas of memory before the other threads could access it?
If you're using the pthreads implementation of mutexes, you would still use them to synchronize between processes... you would place them in shared memory. Initializing a pthread mutex in shared memory addresses this.
You can also use a simple pipe to synchronize access -- pre-fill the pipe with a token and require a successful read of the token to permit resource access. Then write the token back into the pipe in order to release the resource.
First: if you call exec and it succeeds then your process image will be overwritten. You will loose any shared memory and you will need to set it up with your favourite shared memory paradigm (e.g. posix shared memory shm_open).
If you fork then any memory that was mapped shared will remain shared. Means you can place your favourite mutex (e.g. pthread_mutex_t, sem_t) into it and use it with the standard functions that go with it.
void * shared_memory = mmap(
NULL // anywhere
, sysconf(_SC_PAGESIZE) // mmap only works in chunks of pages
// typically 0x1000
, PROT_READ | PROT_WRITE // read-write
, MAP_SHARED // shared
| MAP_ANONYMOUS // anonymous, non-file backed
#ifdef MAP_HASSEMAPHORE
| MAP_HASSEMAPHORE // OS X requires this flag in case you
// intend to have semaphores in that segment
#endif
, -1 // no file backing
, 0
);
if (shared_memory == MAP_FAILED) {
perror("mmap");
abort();
}
// we use that memory to place a mutex tehre
pthread_mutex_t * mutex = shared_memory;
pthread_mutex_init(mutex, NULL);
pid_t pid = fork();
if (pid < 0) {
perror("fork");
abort();
}
if (!pid) {
// child goes here
// use the mutex here
} else {
// parent goes here
// use the mutex here
}

Sharing data between master thread and slave thread in interrupt driven environment in C

I have the following:
f1()
{
while(1)
{
call f(2) if hardware interrupt pin goes high
}
}
f2()
{
if( th() not started )
{
start thread th()
}
else
{
return thread th() status
}
}
th()
{
time-consuming operation
}
At the moment, I use the following to initiate a struct in f2():
static struct SharedData shared;
if( shared == NULL)
{
initialize shared
}
Then I pass a pointer to shared to the thread. The thread then updates shared periodically. f2() will then know if th() has been started based on elements of shared and it will check the status of th() by reading from shared.
Let's assume one of the elements of shared is a mutex to provide thread safety. Is this a good solution? Is there a more elegant way of doing this? I have tested the code and it works. I just need some expert advice here.
Thanks,
Assuming that f2() uses the same mutex in the shared structure to lock before reading the data that the thread th uses to modify the data, I don't see any issues.
If you have more than one thread calling f2(), you may want to use a read-write lock for reading and writing of the thread status of th. The mutex could still be used to serialize the thread creation check. You could also use a pthread_rwlock_wrlock() to serialize th creation, but the code is arguably less clear.
Using a mutex to serialize th creation in f2():
pthread_rwlock_rdlock(&shared.rwlock);
result = shared.th_status;
if (! shared.th_created) {
pthread_mutex_lock(&shared.mutex);
if (! shared.th_created) {
pthread_create(...);
shrared.th_created = 1;
}
pthread_mutex_unlock(&shared_mutex);
}
pthread_rwlock_unlock(&shared.rwlock);
return result;
Using the read-write lock to serialize th creation in f2():
pthread_rwlock_rdlock(&shared.rwlock);
result = shared.th_status;
if (! shared.th_created) {
pthread_rwlock_unlock(&shared.rwlock);
pthread_rwlock_wrlock(&shared.rwlock);
if (! shared.th_created) {
pthread_create(...);
shrared.th_created = 1;
}
}
pthread_rwlock_unlock(&shared.rwlock);
return result;

Managing a mutex in shared memory

I'm attempting the simple task of creating a mutex in shared memory. I have the following code to declare a section of shared memory, and attach it to an int*.
int *mutex;
// allocate shared memory for mutex
if ((shmid2 = shmget(IPC_PRIVATE, 4, IPC_CREAT | 0666)) < 0) {
printf("Could not allocate shared memory for mutex: %d.\n", errno);
exit(errno);
}
if ((mutex = shmat(shmid2, NULL, 0)) == (int*)-1) {
printf("Could not attach shared memory for mutex: %d\n", errno);
exit(errno);
}
// set the mutex to one
mutex[0] = 1;
Now, I attempt to define a critical section, surrounded by locking and unlocking the mutex. (Inside of one of many child processes).
while (*mutex == 0) ;
mutex[0] = 0;
// critical section
...
// end critical section
mutex[0] = 1;
However, I'm finding that this technique does not work, and two child processes can enter the critical section simultaneously, without much issue (it happens very often). So I'm wondering what I can do to fix this, without the use of pthreads.
Your options are:
Use POSIX semaphores instead of trying to implement them yourself with shared-memory spinlocks. See the documentation for semop (2) and related functions for details.
If you must use shared-memory semaphores, you will need to use an atomic compare/exchange. Otherwise, two processes can both simultaneously see *mutex == 0 and set it to 1 at the same time, without "noticing" that the other process is doing the same thing.

Sharing one buffer - thread safe

I am not much into scheduling threads, i have like 4-5 threads and each of them will add data to one same buffer at random time.
How i can schedule the threads so there is no case two or more threads to access the buffer at same time ?
I am coding in C on Windows environment.
Thanks in advance.
The shared buffer needs to be protected from concurrent reads/writes by different threads. A synchronization object should be used to prevent this from occuring. Anytime a thread wants to read from or write to the shared buffer it would acquire the lock, perform its operations on the shared buffer and release the lock once it no longers requires the buffer.
An example synchronization object would be CriticalSection:
static CRITICAL_SECTION shared_buffer_lock;
static char shared_buffer[10];
int main()
{
InitializeCriticalSection(&shared_buffer_lock);
/* Start threads */
...
/* Wait for threads */
...
DeleteCriticalSection(&shared_buffer_lock);
return 0;
}
/* In thread.. */
/* Obtain sole access to 'shared_buffer' */
EnterCriticalSection(&shared_buffer_lock);
/* Use 'shared_buffer' ... */
/* Release sole access of 'shared_buffer' */
LeaveCriticalSection(&shared_buffer_lock);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int sharedData=0;
void *func(void *parm)
{
int rc;
printf("Thread Entered\n");
pthread_mutex_lock(&mutex);
/********** Critical Section *******************/
printf("Start critical section, holding lock\n");
++sharedData;
printf("End critical section, release lock\n");
/********** Critical Section *******************/
pthread_mutex_unlock(&mutex);
}
The example above shows what you are looking for, using pthreads library. Acquire the mutex with pthread_mutex_lock and release it with pthread_mutex_unlock. All threads that request the same lock will be blocked until mutex is released. This guarantees that only one thread has access to your shared data.
You need to implement an exclusive access to the ressource (buffer). Under Windows I would use Mutexes for it (see CreateMutex and WaitForSingleObject/WaitForMultipleObjects in Windows API).

Resources