C++ | Mutex | Embedded System | OS
1100

Mutex Example

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>  //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>

using namespace std;

pthread_mutex_t mutex;

int counter = 0;

void *thread_handler(void *vargp)
{
    pthread_mutex_lock(&mutex);
    counter++;
    cout << "Job" << *(int *)vargp << " started, counter=" << counter << endl;
	/* Run below program with/without sleep(1),
	 * when sleep is included, we need to have mutex
	 */
    sleep(1);
    cout << "Job" << *(int *)vargp << " finished, counter=" << counter << endl;
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main()
{
    pthread_t thread_id[30];
    int thread_arg[30];

    /* Non recursive mutex */
    if(pthread_mutex_init(&mutex, NULL)) {
    	cout << "mutex not initialized successfully" << endl;
    }


    printf("Before Thread\r\n");
    for(int i = 0; i < 5; i++) {
    	thread_arg[i] = i;
    	pthread_create(&thread_id[i], NULL, thread_handler, (void *)&thread_arg[i]);
    }

    for(int i = 0; i < 5; i++) {
        pthread_join(thread_id[i], NULL);
    }

    pthread_mutex_destroy(&mutex);

    return 0;
}

Implement Your own Mutex using Spinlock

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>  //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>

using namespace std;

#define THREAD_CNT 30

typedef struct {
	bool mutex; /* true means available, false means not available */
	int lock_cnt;
}MUTEX;

MUTEX m;

int counter = 0;

int mutex_init(MUTEX *p) {
	p ->mutex= true;
	p ->lock_cnt= 0; /*lock count is not implemented here */
	return 0;
}

/* In computer science, read–modify–write is a class of atomic operations
 * (such as test-and-set, fetch-and-add, and compare-and-swap)
 * that both read a memory location and write a new value into it simultaneously,
 * either with a completely new value or some function of the previous value.
 * These operations prevent race conditions in multi-threaded applications.
 * Typically they are used to implement mutexes or semaphores.
 * These atomic operations are also heavily used in non-blocking synchronization.
 */
bool TestAndSet(bool *target)
{
   bool temp  = *target;
   *target = false;
   return temp;
}

int mutex_lock(MUTEX *p) {
	while(TestAndSet(&p->mutex) == false);
	return 0;
}

int mutex_unlock(MUTEX *p) {
	p ->mutex= true;
	return 0;
}

void *thread_handler(void *vargp)
{
    mutex_lock(&m);
    counter++;
    cout << "Job" << *(int *)vargp << " started, counter=" << counter << endl;
    sleep(1);
    cout << "Job" << *(int *)vargp << " finished, counter=" << counter << endl;
    mutex_unlock(&m);
    return NULL;
}

int main()
{
    pthread_t thread_id[THREAD_CNT];
    int thread_arg[THREAD_CNT];

    /* Non recursive mutex */
    if(mutex_init(&m)) {
    	cout << "mutex not initialized successfully" << endl;
    }


    printf("Before Thread\r\n");
    for(int i = 0; i < THREAD_CNT; i++) {
    	thread_arg[i] = i;
    	pthread_create(&thread_id[i], NULL, thread_handler, (void *)&thread_arg[i]);
    }

    for(int i = 0; i < THREAD_CNT; i++) {
        pthread_join(thread_id[i], NULL);
    }

    return 0;
}
Comments (0)