1 Star 0 Fork 6

jack/cothread2

forked from 覃攀/cothread2 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
cothread_demo_rtos.c 6.62 KB
一键复制 编辑 原始数据 按行查看 历史
linux 提交于 2019-05-26 19:21 . 修改demo
/* 简介:cothread 是一个轻量级协程调度器,由纯C语言实现,易于移植到各种单片机。
* 同时,由于该调度器仅仅运行在一个实际线程中,所以它也适用于服务器高并发场景。
*
* 版本: 1.0.0 2019/02/25
*
* 作者: 覃攀 <qinpan1003@qq.com>
*
*/
#include <pthread.h>
#include "rtos.h"
int thread_test(int argc,char **argv)
{
return 0;
}
/* demo 需要提供给 rtos 的接口函数 */
/*-----------------------------------------------------------------------*/
static int io_inited = 0;
static int input_arrived = 0;
static char ch;
static pthread_t thread_hold = 0;
static irq_state_t interrupt_disabled = 0;
static int tx_inprogress = 0;
static char write_buff[1024];
static int write_head = 0;
static int write_tail = 0;
static void uart_irq_handler(void)
{
if (read_flag())
wakeup_shell_thread();
if (write_completed())
wakeup_log_thread();
cothread_scheduler_wakeup();
}
static void ll_read(void)
{
if (input_arrived)
return;
input_arrived = fread(&ch, 1, 1, stdin);
if (input_arrived)
uart_irq_handler();
}
static void ll_write(void)
{
int count = 0;
int write_head_tmp = write_head;
if (write_tail == write_head_tmp)
return;
tx_inprogress = 1;
/* 控制每次发送字节数,模拟串口发送阻塞,波特率 = bytes * 8 * 1000 */
int bytes = 10;
while (write_tail != write_head_tmp && count < bytes)
{
printf("%c", write_buff[write_tail]);
fflush(stdout);
if (++write_tail >= sizeof(write_buff))
write_tail = 0;
count++;
}
if (write_tail != write_head_tmp)
return;
tx_inprogress = 0;
uart_irq_handler();
}
static void io_init(void)
{
int flags = fcntl(0, F_GETFL, 0);
fcntl(0, F_SETFL, flags | O_NONBLOCK);
io_inited = 1;
}
int irq_log_enable = 0;
int enable_irq_log(int argc, char **argv)
{
if (argc < 2)
return - 1;
if (strcmp(argv[1], "on") == 0)
irq_log_enable = 1;
else if (strcmp(argv[1], "off") == 0)
irq_log_enable = 0;
return 0;
}
static int timer_count = 0;
static void timer_thread(int signo)
{
signal(SIGALRM, timer_thread);
if (interrupt_disabled)
return;
timer_count++;
/* 模拟串口输入中断 */
ll_read();
/* 模拟串口发送 */
ll_write();
system_tick();
if (irq_log_enable)
LOG("log from interrupt.\n");
}
static void hardware_init(void)
{
io_init();
}
int read_flag(void)
{
if (!io_inited)
return 0;
return input_arrived;
}
int read_data(void)
{
int ch_tmp = ch;
input_arrived = 0;
return ch_tmp;
}
int write_completed(void)
{
if (!io_inited)
return 0;
return !tx_inprogress;
}
void write_ch(char ch)
{
int write_head_tmp;
if (!io_inited)
return;
write_head_tmp = write_head + 1;
if (write_head_tmp >= sizeof(write_buff))
write_head_tmp = 0;
/* 满 */
if (write_tail == write_head_tmp)
return;
write_buff[write_head] = ch;
write_head = write_head_tmp;
}
irq_state_t irq_save_disable(void)
{
while (interrupt_disabled && thread_hold != pthread_self())
usleep(2);
interrupt_disabled = 1;
thread_hold = pthread_self();
return 0;
}
void irq_restore(irq_state_t stat)
{
interrupt_disabled = 0;
}
void system_timer_start(void)
{
struct itimerval value, ovalue;
signal(SIGALRM, timer_thread);
value.it_value.tv_sec = 0;
value.it_value.tv_usec = 1000;
value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = 1000;
setitimer(ITIMER_REAL, &value, &ovalue);
}
static pthread_mutex_t wakeup_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER;
void cothread_scheduler_wakeup(void)
{
if (pthread_mutex_trylock(&wakeup_mtx))
return;
pthread_cond_broadcast(&wakeup_cond);
pthread_mutex_unlock(&wakeup_mtx);
}
void cothread_scheduler_wait(void)
{
if (pthread_mutex_trylock(&wakeup_mtx))
return;
pthread_cond_wait(&wakeup_cond, &wakeup_mtx);
pthread_mutex_unlock(&wakeup_mtx);
}
/*-----------------------------------------------------------------------*/
static coresult_t main_thread_8(ccb_t *ccb)
{
thread_start();
while (1)
{
thread_sleep(1000);
LOG("[%s] run on scheduler %p.\n", __FUNCTION__, ccb->scheduler);
}
thread_end();
}
static coresult_t main_thread_9(ccb_t *ccb)
{
thread_start();
while (1)
{
thread_sleep(300);
LOG("[%s] run on scheduler %p.\n", __FUNCTION__, ccb->scheduler);
}
thread_end();
}
static void sig_block(int sig)
{
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, sig);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
}
static void *rtos_thread1(void *arg)
{
sig_block(SIGALRM);
struct cothread_scheduler *scheduler =
alloc_scheduler(COTHREAD_NR, THREAD_PRIO_NR, (void *)pthread_self());
create_shell_thread();
create_log_thread();
int i;
for (i = 0; i < 20; i++)
thread_create_on_scheduler(scheduler, main_thread_8,
NULL, THREAD_PRIO_HIGH);
while (1)
{
if (cothread_loop_once(scheduler) <= 0)
cothread_scheduler_wait();
}
return NULL;
}
static void *rtos_thread2(void *arg)
{
sig_block(SIGALRM);
struct cothread_scheduler *scheduler =
alloc_scheduler(50, 3, (void *)pthread_self());
int i;
for (i = 0; i < 20; i++)
thread_create_on_scheduler(scheduler, main_thread_9,
NULL, THREAD_PRIO_HIGH);
while (1)
{
if (cothread_loop_once(scheduler) <= 0)
cothread_scheduler_wait();
}
return NULL;
}
/* 1、使用 pthread 模拟两个 rtos 线程
* 2、在 rtos 线程中建立 cothread 调度器,通过 cothread 实现多线程
* 这样可以结合 rtos 编程的便利、cothread 小内存优势
*/
int main(void)
{
pthread_t pid1, pid2;
hardware_init();
system_timer_start();
pthread_create(&pid1, NULL, rtos_thread1, NULL);
pthread_create(&pid2, NULL, rtos_thread2, NULL);
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/jack998/cothread2.git
git@gitee.com:jack998/cothread2.git
jack998
cothread2
cothread2
master

搜索帮助