3676 views|1 replies

7171

Posts

195

Resources
The OP
 

Chapter 9 Concurrency and Competition Learning in "Detailed Explanation and Practice of Atomic Embedded Linux Driver Development" [Copy link]

This post was last edited by Changjianze1 on 2024-4-13 14:58

Chapter 8 Chapter 9 Learning Experience of LINUX Concurrency and Competition

An atomic operation

The original meaning of atom is "the smallest particle that cannot be further divided", and atomic operation means "one or a series of operations that cannot be interrupted", which can ensure that instructions run in an atomic manner, that is, the execution process is not interrupted. If it is interrupted, the execution result may not be consistent with the expectation.

atomic_read(atomic_t * v);
This function performs an atomic read operation on an atomic type variable, and it returns the value of the atomic type variable v.

atomic_set(atomic_t * v, int i);
This function sets the value of the atomic type variable v to i.

void atomic_add(int i, atomic_t *v);
This function adds value i to the atomic type variable v.

atomic_sub(int i, atomic_t *v);
This function subtracts i from the atomic type variable v.

int atomic_sub_and_test(int i, atomic_t *v);
This function subtracts i from the atomic type variable v, and determines whether the result is 0. If it is 0, it returns true, otherwise it returns false.

void atomic_inc(atomic_t *v);
This function atomically increases the value of the atomic type variable v by 1.

void atomic_dec(atomic_t *v);
This function atomically subtracts 1 from the atomic type variable v.

int atomic_dec_and_test(atomic_t *v);
This function atomically subtracts 1 from the atomic type variable v and determines whether the result is 0. If it is 0, it returns true, otherwise it returns false.

int atomic_inc_and_test(atomic_t *v);
This function atomically increases the atomic type variable v by 1 and determines whether the result is 0. If it is 0, it returns true, otherwise it returns false.

int atomic_add_negative(int i, atomic_t *v);
This function atomically increases the atomic type variable v by I and determines whether the result is a negative number. If it is, it returns true, otherwise it returns false.

int atomic_add_return(int i, atomic_t *v);
This function atomically increases the atomic type variable v by i and returns a pointer to v.

int atomic_sub_return(int i, atomic_t *v);
This function subtracts i from the atomic type variable v and returns a pointer to v.

int atomic_inc_return(atomic_t * v);
This function atomically increases the atomic type variable v by 1 and returns a pointer to v.

int atomic_dec_return(atomic_t * v);
This function atomically decreases the atomic type variable v by 1 and returns a pointer to v.

Two spin locks

Atomic operations can only protect integer variables or bits, but in actual usage environments it is impossible to have only integer variables or bits with simple critical sections.

The spin of a spin lock means spinning in place. The purpose of spinning in place is to wait for the spin lock to be available and to access shared resources.

shortcoming:

The thread waiting for the spin lock will always be in the spinning state, which will waste processor time and reduce system performance, so the spin lock cannot be held for too long. Therefore, the spin lock is suitable for short-term lightweight locking.

Spin lock is a mutually exclusive device, which has only two states: locked and unlocked.

Spinlock example:

Test routine:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <pthread.h>

//#include<vector>



pthread_spinlock_t spin_lock;

char num = 0;



void xprintf(char *str)

{

 int i = 0;

 while(str[i] != '\0')

 {

 printf("%c", str[i++]);

 fflush(stdout);

 sleep(1);

 }

 return NULL;

}



void *producer(void *arg)

{

 int times = 1000000;

 while(times--)

 {

 pthread_spin_lock(&spin_lock);

 num+=1;

printf("%d",num);

 pthread_spin_unlock(&spin_lock);

 }

}

void *comsumer(void *arg)

{

 int times = 1000000;

 while(times--)

 {

 pthread_spin_lock(&spin_lock);

 num-=1;

printf("%d",num);

 pthread_spin_unlock(&spin_lock);

 }

}



int main()

{

 pthread_spin_init(&spin_lock,0);

 pthread_t thread1,thread2;

 pthread_create(&thread1,NULL,producer,NULL);

 pthread_create(&thread2,NULL,comsumer,NULL);

 pthread_join(thread1,NULL);

 pthread_join(thread2,NULL);

 printf("%d",num);

return 0;

}

Three semaphores

The concept of semaphore has actually been learned in micro-operating systems such as UCOS. It is somewhat similar, but there are still differences.

Characteristics of semaphores:

1Semaphore can make the waiting resource enter the dormant state immediately, so it is suitable for those occasions where resources are occupied for a long time.

2Semaphores cannot be used in terminals because they cause sleep, and interrupts cannot sleep.

3. If the shared resource is held for a short time, it is not suitable to use semaphores, because the overhead caused by frequent sleep and switching is far greater than the advantage brought by semaphores.


#include <stdio.h>

#include <pthread.h>

#include <semaphore.h>

#include <unistd.h>



sem_t sem;



void xprintf(char *str)

{

 int i = 0;

 while(str[i] != '\0')

 {

 printf("%c", str[i++]);

 fflush(stdout);

 sleep(1);

 }

 return NULL;

}



void *task_fun1(void *arg)

{

 sem_wait(&sem);

 xprintf((char *)arg);

 sem_post(&sem);

 return NULL;

}



void *task_fun2(void *arg)

{

 sem_wait(&sem);



 xprintf((char *)arg);



 sem_post(&sem);



 return NULL;

}





int main(int argc, char const *argv[])

{



 sem_init(&sem, 0, 1);



 pthread_t pthid1, pthid2;



 pthread_create(&pthid1, NULL, task_fun1, "TASK1");

 pthread_create(&pthid2, NULL, task_fun2, "TASK2");



 pthread_join(pthid1, NULL);

 pthread_join(pthid2, NULL);





 sem_destroy(&sem);



 return 0;

}

Multithreading is used here, so add -pthread

gcc sem_thread.c -lpthread

Practical testing

This post is from Embedded System

Latest reply

Support the original poster, thank you for your hard work, thank you for sharing the technical content of embedded Linux driver development, I hope you will continue to work hard   Details Published on 2024-10-1 12:29

413

Posts

0

Resources
2
 

Support the original poster, thank you for your hard work, thank you for sharing the technical content of embedded Linux driver development, I hope you will continue to work hard

This post is from Embedded System
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list