threadx学习笔记(6)信号量

文章参考:

ThreadX学习(6)——信号量_threadx 信号量-CSDN博客

 semaphore意为信号量

有两种操作会影响计数信号量的值:tx_semaphore_get和tx_semaphore_put。get操作将信号量减少1。如果信号量为0,则get操作失败。与get操作相反的是put操作,它将信号量增加1。

二值信号量

二值信号量是一种同步机制,用于控制对共享资源的访问。它只有两个值:0和1。当信号量的值为1时,表示资源可用;当值为0时,表示资源被占用。线程或进程在访问共享资源前,会尝试减少(P 操作)信号量的值;访问结束后,会增加(V 操作)信号量的值。如果一个线程尝试执行P操作时信号量的值为0,则该线程会阻塞,直到信号量的值变为1。

和互斥锁类似。但是二值信号量没有互斥锁的所有权概念,即只有加锁的线程才可以解锁,二值信号量所有的线程都可以进行v操作,所以二值信号量无法解决优先级反转的问题,即便如此,信号量更加通用,还可以用于事件通知和线程间同步。且信号量速度快于互斥锁。

事件通知

计数信号量还可以用于事件通知,就像在生产者-消费者应用程序中一样。

在这个应用程序中,使用者尝试在“消耗”资源(比如队列中的数据)之前获得计数信号量;每当生产者提供一些可用的东西时,它就增加信号量计数。换句话说,生产者将实例放置在信号量中,而消费者尝试从信号量中获取实例。

这类信号量的初始值通常为0,直到生产者为消费者准备好一些东西时才会增加。

1.tx_semaphore_create
TX_SEMAPHORE semaphore_ptr; //先定义再创建
UINT  tx_semaphore_create(	TX_SEMAPHORE *semaphore_ptr, 
							CHAR *name_ptr, 
							ULONG initial_count)

第 1 个参数 semaphore_ptr 是信号量控制块地址。
第 2 个参数 name_ptr 是信号量名。
第 3 个参数 initial_count 是该信号量的初始计数。
返回值:
TX_SUCCESS(0x00)成功创建。
TX_SEMAPHORE_ERROR: (0x0C)无效信号量指针。要么指针是NULL,要么信号量已经创建。
TX_CALLER_ERROR:(0x13)无效的服务调用者。

和之前的线程,互斥锁,计数器等类似,创建的时候在tx_application_define中创建。根据打印结果,信号量创建成功。

VOID tx_application_define(void  *first_unused_memory)
{
	char buffer[256];
	UINT aa= tx_semaphore_create(&semaphore_ptr,"semaphore 0",1);
	snprintf(buffer,sizeof(buffer),"%u\n",aa);
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);
	
  tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,  
            thread_0_stack, DEMO_STACK_SIZE, 
            1, 1, 10, TX_AUTO_START);
	tx_thread_create(&thread_1, "Thread 1", thread_1_entry, 0,
                     thread_1_stack, DEMO_STACK_SIZE,
                     2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
}

2.tx_semaphore_delete
UINT  tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr)

删除信号量

  • 第 1 个参数 semaphore_ptr 是信号量控制块地址。

返回值:

  • TX_SUCCESS(0x00)成功删除。
  • TX_SEMAPHORE_ERROR: (0x0C)无效计数信号量指针。
  • TX_CALLER_ERROR:(0x13)无效的服务调用者。

在线程1中调用信号量删除函数,根据打印结果,成功删除信号量。

void thread_1_entry(ULONG thread_input)
{	
	char buffer[256];
	UINT aa= tx_semaphore_delete(&semaphore_ptr);
	snprintf(buffer,sizeof(buffer),"%u\n",aa);
	HAL_UART_Transmit(&huart1,(uint8_t *)buffer,strlen(buffer),HAL_MAX_DELAY);

	char cc[]="线程2\n";
	HAL_UART_Transmit(&huart1, (uint8_t *)cc, strlen(cc), HAL_MAX_DELAY);
}

 3.tx_semaphore_get
UINT  tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, 
							CHAR **name, 
							ULONG *current_value, 
							TX_THREAD **first_suspended, 
							ULONG *suspended_count, 
							TX_SEMAPHORE **next_semaphore)

获取信号量

每次获取信号量,计数减少1。

第 1 个参数 semaphore_ptr 是信号量控制块地址。
第 2 个参数 wait_option 是等待选项:
TX_NO_WAIT:不等待,直接返回结果。
TX_WAIT_FOREVER:一直等待直到获取信号量。
timeout value:设置等待时间(时钟脉冲)。
返回值:
TX_SUCCESS(0x00)成功获取。
TX_DELETED: (0x01)线程挂起时计数信号量被删除。
TX_NO_INSTANCE: (0x0D)服务无法检索计数信号量的实例(在指定的等待时间内信号量计数为零)。
TX_WAIT_ABORTED: (0x1A)挂起被另一个线程、计时器或ISR中止。
TX_SEMAPHORE_ERROR: (0x0C)无效计数信号量指针。
TX_WAIT_ERROR: (0x04)在非线程调用时指定了TX_NO_WAIT以外的等待选项。

示例代码先让线程获取信号量,再打印信号量信息,再是释放信号量,再次打印信号量信息,经过比对可以得到,获取信号量确实会让计数减少1。在释放信号量后,计数加1。

void thread_1_entry(ULONG thread_input)
{
	CHAR 					*name;
	ULONG 				current_value;
	TX_THREAD 		*first_suspended;
	ULONG 				suspended_count;
	TX_SEMAPHORE 	*next_semaphore;
	
	UINT aa=tx_semaphore_get(&semaphore_ptr,TX_NO_WAIT);
	//先获取信号量
	huartsend(aa);
	UINT bb=tx_semaphore_info_get(&semaphore_ptr, 
							&name, 
							&current_value, 
							&first_suspended, 
							&suspended_count, 
							&next_semaphore);
	//再打印此时信号量的信息
	huartsend(bb);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"name:%s\nvalue:%lu\nsuspendcount:%lu\n", 
							name, 
							current_value, 
							suspended_count);
	HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
	UINT dd=tx_semaphore_put(&semaphore_ptr);
	//再释放信号量
	huartsend(dd);
	UINT ee=tx_semaphore_info_get(&semaphore_ptr, 
							&name, 
							&current_value, 
							&first_suspended, 
							&suspended_count, 
							&next_semaphore);
	//再打印此时信号量的信息
	huartsend(ee);
	snprintf(buffer,sizeof(buffer),"name:%s\nvalue:%lu\nsuspendcount:%lu\n", 
							name, 
							current_value, 
							suspended_count);
	HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);

	char cc[]="线程2\n";
	HAL_UART_Transmit(&huart1, (uint8_t *)cc, strlen(cc), HAL_MAX_DELAY);
}
/* USER CODE END 4 */
void huartsend(UINT cc)
{
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"%u\n",cc);
	HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
}

4.tx_semaphore_info_get 
UINT  tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, 
							CHAR **name, 
							ULONG *current_value, 
							TX_THREAD **first_suspended, 
							ULONG *suspended_count, 
							TX_SEMAPHORE **next_semaphore)

获取信号量信息:

第 1 个参数 semaphore_ptr 是信号量控制块地址。
第 2 个参数 name 是信号量名字符串,获取后存储的指针。
第 3 个参数 current_value 是信号量当前计数,获取后存储的指针。
第 4 个参数 first_suspended 是等待该信号量(信号量挂起列表)的第一个线程TCB指针,获取后存储的指针。
第 5 个参数 suspended_count 是等待该信号量(信号量挂起列表)的线程数,获取后存储的指针。
第 6 个参数 next_semaphore 是信号量列表的下一个信号量控制块指针,获取后存储的指针。
返回值:
TX_SUCCESS(0x00)成功获取信号量信息。
TX_SEMAPHORE_ERROR: (0x0C)无效信号量指针。

相关示例代码在获取信号量函数中展示过了。

5.tx_semaphore_put 
UINT  tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr)

释放信号量,计数加一:

第 1 个参数 semaphore_ptr 是信号量控制块地址。

返回值:

TX_SUCCESS(0x00)成功释放。

TX_SEMAPHORE_ERROR: (0x0C)无效信号量指针。

相关示例代码在获取信号量函数中展示过了。

6.tx_semaphore_prioritize
UINT  tx_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr)

信号量挂起列表的最高优先级线程置队头:

第 1 个参数 semaphore_ptr 是信号量控制块地址。

返回值:

TX_SUCCESS(0x00)成功或挂起列表为空。

TX_SEMAPHORE_ERROR: (0x0C)无效信号量指针。

在获取信号量线程的示例代码后面加上tx_semaphore_prioritize函数,根据打印结果显示,函数调用成功。

void thread_1_entry(ULONG thread_input)
{
	CHAR 					*name;
	ULONG 				current_value;
	TX_THREAD 		*first_suspended;
	ULONG 				suspended_count;
	TX_SEMAPHORE 	*next_semaphore;
	
	UINT aa=tx_semaphore_get(&semaphore_ptr,TX_NO_WAIT);
	//先获取信号量
	huartsend(aa);
	UINT bb=tx_semaphore_info_get(&semaphore_ptr, 
							&name, 
							&current_value, 
							&first_suspended, 
							&suspended_count, 
							&next_semaphore);
	//再打印此时信号量的信息
	huartsend(bb);
	char buffer[256];
	snprintf(buffer,sizeof(buffer),"name:%s\nvalue:%lu\nsuspendcount:%lu\n", 
							name, 
							current_value, 
							suspended_count);
	HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
	UINT dd=tx_semaphore_put(&semaphore_ptr);
	//再释放信号量
	huartsend(dd);
	UINT ee=tx_semaphore_info_get(&semaphore_ptr, 
							&name, 
							&current_value, 
							&first_suspended, 
							&suspended_count, 
							&next_semaphore);
	//再打印此时信号量的信息
	huartsend(ee);
	snprintf(buffer,sizeof(buffer),"name:%s\nvalue:%lu\nsuspendcount:%lu\n", 
							name, 
							current_value, 
							suspended_count);
	HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
	
	UINT ff=tx_semaphore_prioritize(&semaphore_ptr);
	huartsend(ff);
	

	char cc[]="线程2\n";
	HAL_UART_Transmit(&huart1, (uint8_t *)cc, strlen(cc), HAL_MAX_DELAY);
}

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值