代码拉取完成,页面将自动刷新
同步操作将从 覃攀/cothread2 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/* 简介: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;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。