RT-Thread: Design pattern of the Producer-consumer model (Semaphore)

来源:互联网 发布:大连淘车网络和中软卓 编辑:程序博客网 时间:2024/05/16 04:22

Lower layer APIs concerning to RT-Thread can be found on 

http://www.rt-thread.org/phpBB3/


1. General description:

        RT-Thread is an open source real-time operating system for embedded devices from China, which has strong scalability: from a tiny kernel runnning on a tiny core, for example ARM Cortex-M, or Cortex-M3/4/7, to a rich feature system running on ARM Cortex-A8, ARM Cortex-A9 DualCore etc.

The producer/consumer design pattern is based on the master/Slave design pattern which used to decouple processes that produce data., and those that consume the data produced. Data queues are used to communicate data between loops in the Producer/Consumer design pattern. These queues offer the advantage of data buffering between producer and consumer loops.

The model is commonly used when acquiring multiple sets of data to be processed in order. Suppose you want to write an application that accepts data while processing them in the order they were received. Because queuing up this data is much faster than the actual processing, the Producer/Consumer design pattern is best suited for this application. We could conceivably put both the producer and consumer in the same loop for this application, but the processing queue will not be able to add any additional data until the first piece of data is done processing. The producer/consumer pattern approach to this application would be to queue the data in the producer loop, and have the actual processing done in the consumer loop. This in effect will allow the consumer loop to process the data at its own pace, while allowing the producer loop to queue additional data at the same time.

semaphore is a lightweight kernel object that solves the problem of thread synchronization. Threads can acquire or release it to achieve the purpose of synchronization or mutual exclusion. The semaphore is like a key that locks a critical area and allows only a key thread to be accessed: the thread gets the key before it is allowed to enter the critical area; after leaving the key is passed to the queue wait for the thread, so that follow-up thread into the critical area in turn.

2. APIs description:

   I'll provide some APIs concerning to semaphore here.

1) Create the semaphore, the kernel firstly creates a semaphore controlling module, then do the initialization work.

    2) Delete the semaphore. Once delete it when a thread is waiting for it, the delete operation will awake the thread on the semaphore. And the return value to the thread is RT_ERROR.

 

3) Detach the semaphore, move away the object of the semaphore from the kernel.

4) Provide the thread to achieve semaphore resources. When the semaphore is over than zero, the thread

will achieve the semaphore.

5) Release the semaphore, when the thread has completely visited the resources, release the semaphore as soon as possible.


3. Test and Codes:

/* * File      : application.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date           Author       Notes * 2017-02-11     Kyrie      the first version * 2014-02-15     Kyrie      make code cleanup.  */#include <board.h>#include <rtthread.h>#include <dfs_posix.h>//#include "tc_comm.h"//debugging interface#ifdef RT_USING_GDB#include <gdb_stub.h>#endif//#include <sha1.h>/*************zzh******************+*/#define MAXSEM 5#define THREAD_PRIORITY 25#define THREAD_STACK_SIZE 512#define THREAD_TIMESLICE 5rt_uint32_t array[MAXSEM];static rt_uint32_t set, get;static rt_thread_t producer_tid = RT_NULL;static rt_thread_t consumer_tid = RT_NULL;struct rt_semaphore sem_lock;struct rt_semaphore sem_empty, sem_full;/*************zzh******************-*/extern void rt_hw_led_set_on(rt_uint8_t led);extern void rt_hw_led_set_off(rt_uint8_t led);/*************zzh******************+*///static rt_thread_t tid = RT_NULL, tid2 = RT_NULL;static rt_sem_t sem = RT_NULL;//sem structstatic rt_thread_t tid = RT_NULL;/*************zzh******************-*/#define MASTER_KEY  "electrical lift controller"/*************zzh******************+*//*static struct rt_thread thread1;ALIGN(4)static rt_uint8_t thread1_stack[THREAD_STACK_SIZE];static struct rt_thread thread2;ALIGN(4)static rt_uint8_t thread2_stack[THREAD_STACK_SIZE];*//*************zzh******************-*///static rt_thread_t tid = RT_NULL;//static rt_thread_t tid2 = RT_NULL;//static rt_uint32_t cnt;static rt_uint32_t test=0;void rt_init_thread_entry2(void* parameter){rt_uint32_t count = 0;rt_uint32_t no = (rt_uint32_t) parameter;while(1){rt_kprintf("thread%d count: %d\n", no, count ++);//rt_thread_delay(10);//rt_thread_yield();}}static void rt_init_thread_entry(void* parameter){//#ifdef RT_USING_COMPONENTS_INIT    /* RT-Thread components initialization *///    rt_components_init();//#endif//rt_kprintf("Hello RT-Thread !!!\n");/*************zzh******************+*///create a thread//rt_uint32_t count = 0;//rt_uint32_t no = (rt_uint32_t) parameter;//rt_uint32_t no;//no = (rt_uint32_t) parameter;rt_err_t result;rt_tick_t tick;tick = rt_tick_get();result = rt_sem_take(sem, 10);if (result == -RT_ETIMEOUT){if(rt_tick_get()-tick!=10){rt_sem_delete(sem);return;}rt_kprintf("take semaphore timeout\n");}else{rt_sem_delete(sem);return;}rt_sem_release(sem);result = rt_sem_take(sem, RT_WAITING_FOREVER);if (result != RT_EOK){rt_sem_delete(sem);return;}rt_sem_delete(sem);/*********zzh******************-*//* SHA-1 test *//*{    sha1_context ctx;    rt_uint8_t output[20];    rt_uint8_t input[4] = {0x30,0x31,0x32,0x33};        rt_uint8_t usr_sn[16];*/        /* generate usr_key *//*    sha1_hmac_reset(&ctx);    sha1_hmac_starts(&ct x,MASTER_KEY,rt_strlen(MASTER_KEY));    sha1_hmac_update(&ctx,input,4);    sha1_hmac_finish(&ctx,output);        rt_memcpy(usr_sn,&output[4],16);*/        /* SEC0 KEYA */    /*    sha1_hmac_reset(&ctx);        sha1_hmac_starts(&ctx,usr_sn,16);        sha1_hmac_update(&ctx,"SEC0KEYA",8);        sha1_hmac_finish(&ctx,output);        rt_kprintf("SHA1-HMAC SEC0 KEYA end...\n");*/        /* SEC0 KEYB */     /*   sha1_hmac_reset(&ctx);        sha1_hmac_starts(&ctx,usr_sn,16);        sha1_hmac_update(&ctx,"SEC0KEYB",8);        sha1_hmac_finish(&ctx,output);        rt_kprintf("SHA1-HMAC SEC0 KEYA end...\n");}*/while(1){static rt_uint8_t tickCount = 0;rt_hw_led_set_on(tickCount);rt_hw_led_set_off(~tickCount);rt_thread_delay(RT_TICK_PER_SECOND);tickCount++;}}int semaphore_dynamic_init(){sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);if(sem== RT_NULL){//tc_stat(TC_STAT_END | TC_STAT_FAILED);return 0;}tid = rt_thread_create("thread",        rt_init_thread_entry,(void*)0,THREAD_STACK_SIZE,THREAD_PRIORITY,THREAD_TIMESLICE);if(tid != RT_NULL)rt_thread_startup(tid);return 0;}void consumer_thread_entry(void* parameter){rt_uint32_t no;rt_uint32_t sum = 0;no = (rt_uint32_t)parameter;while(1){rt_sem_take(&sem_full, RT_WAITING_FOREVER);rt_sem_take(&sem_lock, RT_WAITING_FOREVER);sum += array[get%MAXSEM];rt_kprintf("the consumer[%d] get a number:%d\n",no, array[get%MAXSEM]);get++;rt_sem_release(&sem_lock);rt_sem_release(&sem_empty);if (get == 100) break;rt_thread_delay(10);}rt_kprintf("the consumer[%d] sum is %d \n ", no, sum);rt_kprintf("the consumer[%d] exit!\n");}void producer_thread_entry(void* parameter){rt_int32_t cnt = 0;while(cnt <= 100){rt_sem_take(&sem_empty, RT_WAITING_FOREVER);rt_sem_take(&sem_lock, RT_WAITING_FOREVER);array[set%MAXSEM] = cnt + 1;rt_kprintf("the producer generates a number: %d\n",array[set%MAXSEM]);set++;rt_sem_release(&sem_lock);rt_sem_release(&sem_full);cnt++;rt_thread_delay(10);}rt_kprintf("the producer exit!\n");}int semaphore_producer_consumer_init(){rt_sem_init(&sem_lock , "lock", 1, RT_IPC_FLAG_FIFO);rt_sem_init(&sem_empty,"empty", MAXSEM, RT_IPC_FLAG_FIFO);rt_sem_init(&sem_full , "full", 0, RT_IPC_FLAG_FIFO);producer_tid = rt_thread_create("producer",producer_thread_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE);if (producer_tid != RT_NULL)rt_thread_startup(producer_tid);consumer_tid = rt_thread_create("consumer",consumer_thread_entry,RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);if (consumer_tid != RT_NULL)rt_thread_startup(consumer_tid);return 0;}int rt_application_init(){    //semaphore_dynamic_init();semaphore_producer_consumer_init(); /* rt_thread_t tid;    tid = rt_thread_create("t1",        rt_init_thread_entry,(void*)10,        2048, 10, 5);    if (tid != RT_NULL)        rt_thread_startup(tid);*//*************zzh******************+*///rt_thread_t tid2;/*tid = rt_thread_create("t2",      rt_init_thread_entry,(void*)20,2048,20,5);if (tid != RT_NULL)        rt_thread_startup(tid);*//*************zzh******************-*//*************zzh******************+*//*rt_err_t result;result = rt_thread_init(&thread1, "t1", rt_init_thread_entry, (void*)1, &thread1_stack[0], sizeof(thread1_stack), THREAD_PRIORITY, 10);if (result == RT_EOK) rt_thread_startup(&thread1);elsereturn -1;result = rt_thread_init(&thread1, "t2", rt_init_thread_entry, (void*)2, &thread1_stack[0], sizeof(thread2_stack), THREAD_PRIORITY+1, 10);if (result == RT_EOK) rt_thread_startup(&thread2);elsereturn -1;*//*************zzh******************-*/    return 0;}/*@}*/

Author: Kyrie



0 0
原创粉丝点击