互斥锁
互斥量mutex的简单使用
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutex_t *restrict attr); //初始化mutex
int pthread_mutex_destroy(pthread_mutex_t *mutex); //如果mutex是动态分配的,则释放内存前调用此函数。
int pthread_mutex_lock(pthread_mutex_t *mutex); //加锁
int pthread_mutex_trylock(pthread_mutex_t *mutex); //若已有其他线程占用锁,则返回EBUSY,否则返回0,不阻塞。
int pthread_mutex_unlock(pthread_mutex_t *mutex); //解锁
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <pthread.h> 5 #include <errno.h> 6
7int a = 100; 8int b = 200; 9
10pthread_mutex_t lock; -----定义
11
12void * threadA()
13{
14 pthread_mutex_lock(&lock);------加锁
15 printf("thread A got lock!n"); 16 a -= 50; 17 sleep(3); //如果不加锁,threadB输出会是50和20018
b += 50; //加锁后会sleep 3秒后,并为b加上50 threadB才能打印19
pthread_mutex_unlock(&lock);-----解锁
20 printf("thread A released the lock!n");
21 a -= 50; 22} 23
24void * threadC() 25{ 26 sleep(1); 27while(pthread_mutex_trylock(&lock) == EBUSY) //轮询直到获得锁
28 { 29 printf("thread C is trying to get lock!n"); 30 usleep(100000); 31 } 32 printf("thread C got the lock!n"); 33 a = 1000; 34 b = 2000; 35pthread_mutex_unlock(&lock); 36 printf("thread C released the lock!n"); 37
38} 39
40void * threadB() 41{ 42 sleep(2); //让threadA能先执行
43pthread_mutex_lock(&lock); 44 printf("thread B got the lock! a=%d b=%dn", a, b); 45pthread_mutex_unlock(&lock); 46 printf("thread B released the lock!n", a, b); 47} 4849int main() 50{ 51 pthread_t tida, tidb, tidc; 52pthread_mutex_init(&lock, NULL); -----初始化锁53 pthread_create(&tida, NULL, threadA, NULL); 54 pthread_create(&tidb, NULL, threadB, NULL); 55 pthread_create(&tidc, NULL, threadC, NULL); 56 pthread_join(tida, NULL); 57 pthread_join(tidb, NULL); 58 pthread_join(tidc, NULL); 59return0; 60 }
Linux内核互斥锁--mutex:
具体参见linux/kernel/mutex.c
包含头文件:
include <linux/mutex.h >
使用形式:
struct mutex mutex;
mutex_init(&mutex); /*定义*/
...
mutex_lock(&mutex); /*获取互斥锁*/
... /*临界资源*/
mutex_unlock(&mutex); /*释放互斥锁*/
EG:
int frizz_ioctl_hardware_download_firmware( char *name )
{
struct file *filep;
int read_file_size;
unsigned int header;
int modified_ram_size;
int data_size;
unsigned int cmd;
unsigned int ram_addr;
unsigned char *write_ram_data;
unsigned char *read_ram_data;
unsigned char read_data[4];
int i;
struct mutex lock;
mutex_init(&lock);
mutex_lock(&lock);//增加自锁
frizz_gpio_output(1);//sensor HUB GPIO3 拉高
I( "frizz_ioctl_hardware_download_firmware(%s)n", name );
filep = filp_open( name, O_RDONLY | O_LARGEFILE, 0 );
if( IS_ERR( filep ) ) {
printk( "can't open %s n", name );
return 1;
}
frizz_ioctl_hardware_stall();
do {
read_file( filep, read_data, 1, &read_file_size );
header = read_data[0];
if( header == 0xC9 ) {
//get file data size. remove cmd (2byte) and ram addr (4byte)
read_file( filep, read_data, 3, &read_file_size );
data_size = ( ( read_data[0] << 16 ) | ( read_data[1] << 8 ) | ( read_data[2] ) ) - 6;
//get frizz command (command of writting ram)
read_file( filep, read_data, 2, &read_file_size );
cmd = ( read_data[0] << 8 ) | ( read_data[1] );
//get ram address
read_file( filep, read_data, 4, &read_file_size );
ram_addr = ( read_data[0] << 24 ) | ( read_data[1] << 16 ) | ( read_data[2] << 8 ) | ( read_data[3] );
//keep memory
write_ram_data = kmalloc( data_size, GFP_KERNEL | GFP_DMA );
read_file( filep, write_ram_data, data_size, &read_file_size );
modified_ram_size = data_size + 3;
modified_ram_size &= 0xFFFFFFFC;
D( "writing data to ram start. ram_addr=%u, write_ram_data=%p, modified_ram_size=%dn", ram_addr, write_ram_data, modified_ram_size );
serial_write_reg_ram_data( RAM_ADDR_REG_ADDR, ram_addr, write_ram_data, modified_ram_size );
D( "writing data to ram start endn" );
//keep memory (verify)
read_ram_data = kmalloc( data_size, GFP_KERNEL | GFP_DMA );
D( "serial_write_reg_32 start. ram_addr=%un", ram_addr );
serial_write_reg_32( RAM_ADDR_REG_ADDR, ram_addr );
serial_read_reg_array( RAM_DATA_REG_ADDR, read_ram_data, modified_ram_size );
D( "serial_read_reg_array end. read_ram_data=%p, modified_ram_size=%dn", read_ram_data, modified_ram_size );
for( i = 0; i < modified_ram_size; i++ ) {
if( write_ram_data[i] != read_ram_data[i] ) {
D( "firmware download i=%d, write_ram_data[i](=%d) != read_ram_data[i](=%d)n", i, write_ram_data[i], read_ram_data[i] );
break;
}
}
if( i == modified_ram_size ) {
D( "%s: Verify Success. start address %x n", DRIVER_NAME, ram_addr );
} else {
D( "%s: [%d] write ram data %x read ram data %xn", DRIVER_NAME, i, write_ram_data[i], read_ram_data[i] );
D( "%s: Verify Failed. start address %x n", DRIVER_NAME, ram_addr );
}
kfree( write_ram_data );
kfree( read_ram_data );
} else if( header == 0xED00 ) {
//don't execute command and skip data.
read_file( filep, read_data, 2, &read_file_size );
data_size = ( ( read_data[0] << 8 ) | ( read_data[1] ) );
read_file( filep, read_data, 2, &read_file_size );
cmd = ( read_data[0] << 8 ) | ( read_data[1] );
read_file( filep, read_data, 4, &read_file_size );
}
} while( read_file_size != 0 );
frizz_ioctl_software_reset();
mdelay( 1000 );
serial_read_fifo_CNR();
#if defined(FRIZZ_LOW_POWER_MODE_GPIO)
//set low clock mode
serial_write_reg_32( MODE_REG_ADDR, 0x0 );
//send low power command
{
packet_t packet;
packet.header.w = 0xFF81FF01;
packet.data[0] = 0x09010300;
create_frizz_workqueue( ( void* )&packet );
}
#endif
frizz_ioctl_enable_gpio_interrupt();
irq_set_irq_type( frizz_irq, IRQF_SHARED | IRQF_TRIGGER_LOW );
frizz_ioctl_sensor_get_version( SENSOR_TYPE_PDR );
filp_close( filep, NULL );
frizz_gpio_output(0);//Sensoer HUB GPIO3拉低
mutex_unlock(&lock);// jimmy 增加自锁
return 0;
}