cpu_port.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*
  2. * author : prife (goprife@gmail.com)
  3. * date : 2013/01/14 01:18:50
  4. * version: v 0.2.0
  5. */
  6. #include <rtthread.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <pthread.h>
  10. #include <signal.h>
  11. #include <unistd.h>
  12. #include <semaphore.h>
  13. #include <time.h>
  14. #include <sys/time.h>
  15. //#define TRACE printf
  16. #define TRACE(...)
  17. typedef struct _thread
  18. {
  19. pthread_t pthread;
  20. void (*task)(void *);
  21. void *para;
  22. void (*exit)(void);
  23. sem_t sem;
  24. rt_thread_t rtthread;
  25. int status;
  26. void *data;
  27. } thread_t;
  28. #define THREAD_T(thread) ((thread_t *)thread)
  29. #define MSG_SUSPEND SIGUSR1 /* 10 */
  30. #define MSG_RESUME SIGUSR2
  31. #define MSG_TICK SIGALRM /* 14 */
  32. #define TIMER_TYPE ITIMER_REAL
  33. #define MAX_INTERRUPT_NUM ((unsigned int)sizeof(unsigned int) * 8)
  34. #define INTERRUPT_ENABLE 0
  35. #define INTERRUPT_DISABLE 1
  36. /* 线程挂起状态,共两种取值 */
  37. #define SUSPEND_LOCK 0
  38. #define SUSPEND_SIGWAIT 1
  39. #define THREAD_RUNNING 2
  40. /* interrupt flag, if 1, disable, if 0, enable */
  41. static long interrupt_disable_flag;
  42. //static int systick_signal_flag;
  43. /* flag in interrupt handling */
  44. rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
  45. rt_uint32_t rt_thread_switch_interrupt_flag;
  46. /* interrupt event mutex */
  47. static pthread_mutex_t *ptr_int_mutex;
  48. static pthread_cond_t cond_int_hit; /* interrupt occured! */
  49. static volatile unsigned int cpu_pending_interrupts;
  50. static int (* cpu_isr_table[MAX_INTERRUPT_NUM])(void) = {0};
  51. static pthread_t mainthread_pid;
  52. /* function definition */
  53. static void start_sys_timer(void);
  54. static int tick_interrupt_isr(void);
  55. static void mthread_signal_tick(int sig);
  56. static int mainthread_scheduler(void);
  57. int signal_install(int sig, void (*func)(int))
  58. {
  59. struct sigaction act;
  60. /* set the signal handler */
  61. act.sa_handler = func ;
  62. sigemptyset(&act.sa_mask);
  63. act.sa_flags = 0;
  64. sigaction(sig, &act, 0);
  65. }
  66. int signal_mask(void)
  67. {
  68. sigset_t sigmask, oldmask;
  69. /* set signal mask */
  70. sigemptyset(&sigmask);
  71. sigaddset(&sigmask, SIGALRM);
  72. pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
  73. }
  74. static void thread_suspend_signal_handler(int sig)
  75. {
  76. sigset_t sigmask;
  77. pthread_t pid = pthread_self();
  78. thread_t *thread_from;
  79. thread_t *thread_to;
  80. rt_thread_t tid;
  81. if (sig != MSG_SUSPEND)
  82. {
  83. printf("get an unexpected signal <%d>, exit\n", sig);
  84. exit(EXIT_FAILURE);
  85. }
  86. thread_from = (thread_t *) rt_interrupt_from_thread;
  87. thread_to = (thread_t *) rt_interrupt_to_thread;
  88. /* 注意!此时 rt_thread_self的值是to线程的值! */
  89. tid = rt_thread_self();
  90. /* FIXME RT_ASSERT(thread_from->pthread == pid); */
  91. RT_ASSERT((thread_t *)(tid->sp) == thread_to);
  92. TRACE("signal: SIGSUSPEND suspend <%s>\n", thread_from->rtthread->name);
  93. /* 使用sigwait或者sigsuspend来挂起from线程 */
  94. //sem_wait(&thread_from->sem);
  95. sigemptyset(&sigmask);
  96. sigaddset(&sigmask, MSG_RESUME);
  97. /* Beginnig Linux Programming上说,当信号处理函数运行中,此信号就会被屏蔽,
  98. * 以防止重复执行信号处理函数
  99. */
  100. thread_from->status = SUSPEND_SIGWAIT;
  101. if (sigwait(&sigmask, &sig) != 0)
  102. {
  103. printf("sigwait faild, %d\n", sig);
  104. }
  105. thread_to = (thread_t *) rt_interrupt_to_thread;
  106. RT_ASSERT(thread_to == thread_from);
  107. thread_to->status = THREAD_RUNNING;
  108. TRACE("signal: SIGSUSPEND resume <%s>\n", thread_from->rtthread->name);
  109. }
  110. static void thread_resume_signal_handler(int sig)
  111. {
  112. sigset_t sigmask;
  113. pthread_t pid = pthread_self();
  114. thread_t *thread_from;
  115. thread_t *thread_to;
  116. rt_thread_t tid;
  117. thread_from = (thread_t *) rt_interrupt_from_thread;
  118. thread_to = (thread_t *) rt_interrupt_to_thread;
  119. /* 注意!此时 rt_thread_self的值是to线程的值! */
  120. tid = rt_thread_self();
  121. RT_ASSERT((thread_t *)(tid->sp) == thread_to);
  122. TRACE("signal: SIGRESUME resume <%s>\n", thread_to->rtthread->name);
  123. }
  124. static void *thread_run(void *parameter)
  125. {
  126. rt_thread_t tid;
  127. thread_t *thread;
  128. thread = THREAD_T(parameter);
  129. int res;
  130. /* set signal mask, mask the timer! */
  131. signal_mask();
  132. thread->status = SUSPEND_LOCK;
  133. TRACE("pid <%08x> stop on sem...\n", (unsigned int)(thread->pthread));
  134. sem_wait(&thread->sem);
  135. tid = rt_thread_self();
  136. TRACE("pid <%08x> tid <%s> starts...\n", (unsigned int)(thread->pthread),
  137. tid->parent.name);
  138. thread->rtthread = tid;
  139. thread->task(thread->para);
  140. TRACE("pid <%08x> tid <%s> exit...\n", (unsigned int)(thread->pthread),
  141. tid->parent.name);
  142. thread->exit();
  143. /*TODO:
  144. * 最后一行的pthread_exit永远没有机会执行,这是因为在threead->exit函数中
  145. * 会发生线程切换,并永久将此pthread线程挂起,所以更完美的解决方案是在这
  146. * 里发送信号给主线程,主线程中再次唤醒此线程令其自动退出。
  147. */
  148. //sem_destroy(&thread->sem);
  149. pthread_exit(NULL);
  150. }
  151. static int thread_create(
  152. thread_t *thread, void *task, void *parameter, void *pexit)
  153. {
  154. int res;
  155. pthread_attr_t attr;
  156. thread->task = task;
  157. thread->para = parameter;
  158. thread->exit = pexit;
  159. if (sem_init(&thread->sem, 0, 0) != 0)
  160. {
  161. printf("init thread->sem failed, exit \n");
  162. exit(EXIT_FAILURE);
  163. }
  164. /* No need to join the threads. */
  165. pthread_attr_init(&attr);
  166. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  167. /* create a posix thread */
  168. res = pthread_create(&thread->pthread, &attr, &thread_run, (void *)thread);
  169. if (res)
  170. {
  171. printf("pthread create faild, <%d>\n", res);
  172. exit(EXIT_FAILURE);
  173. }
  174. return 0;
  175. }
  176. /* resume the thread */
  177. static int thread_resume(thread_t *thread)
  178. {
  179. sem_post(& thread->sem);
  180. }
  181. rt_uint8_t *rt_hw_stack_init(
  182. void *pEntry,
  183. void *pParam,
  184. rt_uint8_t *pStackAddr,
  185. void *pExit)
  186. {
  187. thread_t *thread;
  188. thread = (thread_t *)(pStackAddr - sizeof(thread_t));
  189. /* set the filed to zero */
  190. memset(thread, 0x00, sizeof(thread_t));
  191. thread_create(thread, pEntry, pParam, pExit);
  192. //TRACE("thread %x created\n", (unsigned int)thread_table[t].pthread);
  193. return (rt_uint8_t *) thread;
  194. }
  195. rt_base_t rt_hw_interrupt_disable(void)
  196. {
  197. long back;
  198. if (ptr_int_mutex == NULL)
  199. {
  200. return 0;
  201. }
  202. pthread_mutex_lock(ptr_int_mutex);
  203. back = interrupt_disable_flag;
  204. interrupt_disable_flag = INTERRUPT_DISABLE;
  205. /*TODO: It may need to unmask the signal */
  206. return back;
  207. }
  208. void rt_hw_interrupt_enable(rt_base_t level)
  209. {
  210. struct rt_thread * tid;
  211. pthread_t pid;
  212. thread_t *thread_from;
  213. thread_t *thread_to;
  214. if (ptr_int_mutex == NULL)
  215. return;
  216. interrupt_disable_flag = level;
  217. pthread_mutex_unlock(ptr_int_mutex);
  218. /* 如果已经中断仍然关闭 */
  219. if (interrupt_disable_flag)
  220. {
  221. return;
  222. }
  223. /* 表示当前中断打开, 检查是否有挂起的中断 */
  224. pthread_mutex_lock(ptr_int_mutex);
  225. if (!cpu_pending_interrupts)
  226. {
  227. pthread_mutex_unlock(ptr_int_mutex);
  228. return;
  229. }
  230. thread_from = (thread_t *) rt_interrupt_from_thread;
  231. thread_to = (thread_t *) rt_interrupt_to_thread;
  232. tid = rt_thread_self();
  233. pid = pthread_self();
  234. //pid != mainthread_pid &&
  235. if (thread_from->pthread == pid)
  236. {
  237. /* 注意这段代码是在RTT普通线程函数总函数中执行的,
  238. * from线程就是当前rtt线程 */
  239. /* 需要检查是否有挂起的中断需要处理 */
  240. TRACE("conswitch: P in pid<%x> ,suspend <%s>, resume <%s>!\n",
  241. (unsigned int)pid,
  242. thread_from->rtthread->name,
  243. thread_to->rtthread->name);
  244. cpu_pending_interrupts --;
  245. thread_from->status = SUSPEND_LOCK;
  246. pthread_mutex_unlock(ptr_int_mutex);
  247. /* 唤醒被挂起的线程 */
  248. if (thread_to->status == SUSPEND_SIGWAIT)
  249. {
  250. pthread_kill(thread_to->pthread, MSG_RESUME);
  251. }
  252. else if (thread_to->status == SUSPEND_LOCK)
  253. {
  254. sem_post(& thread_to->sem);
  255. }
  256. else
  257. {
  258. printf("conswitch: should not be here! %d\n", __LINE__);
  259. exit(EXIT_FAILURE);
  260. }
  261. /* 挂起当前的线程 */
  262. sem_wait(& thread_from->sem);
  263. pthread_mutex_lock(ptr_int_mutex);
  264. thread_from->status = THREAD_RUNNING;
  265. pthread_mutex_unlock(ptr_int_mutex);
  266. }
  267. else
  268. {
  269. /* 注意这段代码可能在多种情况下运行:
  270. * 1. 在system tick中执行, 即主线程的SIGALRM信号处理函数中执行
  271. * 2. 其他线程中调用,比如用于获取按键输入的线程中调用
  272. */
  273. TRACE("conswitch: S in pid<%x> ,suspend <%s>, resume <%s>!\n",
  274. (unsigned int)pid,
  275. thread_from->rtthread->name,
  276. thread_to->rtthread->name);
  277. cpu_pending_interrupts --;
  278. /* 需要把解锁函数放在前面,以防止死锁?? */
  279. pthread_mutex_unlock(ptr_int_mutex);
  280. /* 挂起from线程 */
  281. pthread_kill(thread_from->pthread, MSG_SUSPEND);
  282. /* 注意:这里需要确保线程被挂起了, 否则312行就很可能就会报错退出
  283. * 因为这里挂起线程是通过信号实现的,所以一定要确保线程挂起才行 */
  284. while (thread_from->status != SUSPEND_SIGWAIT)
  285. {
  286. sched_yield();
  287. }
  288. /* 唤醒to线程 */
  289. if (thread_to->status == SUSPEND_SIGWAIT)
  290. {
  291. pthread_kill(thread_to->pthread, MSG_RESUME);
  292. }
  293. else if (thread_to->status == SUSPEND_LOCK)
  294. {
  295. sem_post(& thread_to->sem);
  296. }
  297. else
  298. {
  299. printf("conswitch: should not be here! %d\n", __LINE__);
  300. exit(EXIT_FAILURE);
  301. }
  302. }
  303. /*TODO: It may need to unmask the signal */
  304. }
  305. void rt_hw_context_switch(rt_uint32_t from,
  306. rt_uint32_t to)
  307. {
  308. struct rt_thread * tid;
  309. pthread_t pid;
  310. thread_t *thread_from;
  311. thread_t *thread_to;
  312. RT_ASSERT(from != to);
  313. #if 0
  314. //TODO: 可能还需要考虑嵌套切换的情况
  315. if (rt_thread_switch_interrupt_flag != 1)
  316. {
  317. rt_thread_switch_interrupt_flag = 1;
  318. // set rt_interrupt_from_thread
  319. rt_interrupt_from_thread = *((rt_uint32_t *)from);
  320. }
  321. #endif
  322. pthread_mutex_lock(ptr_int_mutex);
  323. rt_interrupt_from_thread = *((rt_uint32_t *)from);
  324. rt_interrupt_to_thread = *((rt_uint32_t *)to);
  325. /* 这个函数只是并不会真正执行中断处理函数,而只是简单的
  326. * 设置一下中断挂起标志位
  327. */
  328. cpu_pending_interrupts ++;
  329. pthread_mutex_unlock(ptr_int_mutex);
  330. }
  331. void rt_hw_context_switch_interrupt(rt_uint32_t from,
  332. rt_uint32_t to)
  333. {
  334. rt_hw_context_switch(from, to);
  335. }
  336. void rt_hw_context_switch_to(rt_uint32_t to)
  337. {
  338. //set to thread
  339. rt_interrupt_to_thread = *((rt_uint32_t *)(to));
  340. //clear from thread
  341. rt_interrupt_from_thread = 0;
  342. //set interrupt to 1
  343. rt_thread_switch_interrupt_flag = 0; //TODO: 还需要考虑这个嵌套切换的情况
  344. /* enable interrupt
  345. * note: NOW, there are only one interrupt in simposix: system tick */
  346. rt_hw_interrupt_enable(0);
  347. //start the main thread scheduler
  348. mainthread_scheduler();
  349. //never reach here!
  350. return;
  351. }
  352. static int mainthread_scheduler(void)
  353. {
  354. int i, res, sig;
  355. thread_t *thread_from;
  356. thread_t *thread_to;
  357. pthread_mutex_t mutex;
  358. pthread_mutexattr_t mutexattr;
  359. sigset_t sigmask, oldmask;
  360. /* save the main thread id */
  361. mainthread_pid = pthread_self();
  362. TRACE("pid <%08x> mainthread\n", (unsigned int)(mainthread_pid));
  363. /* 屏蔽suspend信号和resume信号 */
  364. sigemptyset(&sigmask);
  365. sigaddset(&sigmask, MSG_SUSPEND);
  366. sigaddset(&sigmask, MSG_RESUME);
  367. pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
  368. sigemptyset(&sigmask);
  369. sigaddset(&sigmask, SIGALRM);
  370. /* install signal handler of system tick */
  371. signal_install(SIGALRM, mthread_signal_tick);
  372. /* install signal handler used to suspend/resume threads */
  373. signal_install(MSG_SUSPEND, thread_suspend_signal_handler);
  374. signal_install(MSG_RESUME, thread_resume_signal_handler);
  375. /* create a mutex and condition val, used to indicate interrupts occrue */
  376. ptr_int_mutex = &mutex;
  377. pthread_mutexattr_init(&mutexattr);
  378. pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
  379. pthread_mutex_init(ptr_int_mutex, &mutexattr);
  380. /* start timer */
  381. start_sys_timer();
  382. thread_to = (thread_t *) rt_interrupt_to_thread;
  383. thread_resume(thread_to);
  384. for (;;)
  385. {
  386. #if 1
  387. if (sigwait(&sigmask, &sig) != 0)
  388. {
  389. printf("mthread: sigwait get unexpected sig %d\n", sig);
  390. }
  391. #else
  392. pause();
  393. #endif
  394. TRACE("mthread:got sig %d\n", sig);
  395. /* signal mask sigalrm 屏蔽SIGALRM信号 */
  396. pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
  397. // if (systick_signal_flag != 0)
  398. if (pthread_mutex_trylock(ptr_int_mutex) == 0)
  399. {
  400. tick_interrupt_isr();
  401. // systick_signal_flag = 0;
  402. pthread_mutex_unlock(ptr_int_mutex);
  403. }
  404. else
  405. {
  406. TRACE("try lock failed.\n");
  407. }
  408. /* 开启SIGALRM信号 */
  409. pthread_sigmask(SIG_UNBLOCK, &sigmask, &oldmask);
  410. }
  411. return 0;
  412. }
  413. /*
  414. * Setup the systick timer to generate the tick interrupts at the required
  415. * frequency.
  416. */
  417. static void start_sys_timer(void)
  418. {
  419. struct itimerval itimer, oitimer;
  420. int us;
  421. RT_ASSERT(RT_TICK_PER_SECOND <= 1000000 || RT_TICK_PER_SECOND >= 1);
  422. us = 1000000 / RT_TICK_PER_SECOND - 1;
  423. TRACE("start system tick!\n");
  424. /* Initialise the structure with the current timer information. */
  425. if (0 != getitimer(TIMER_TYPE, &itimer))
  426. {
  427. TRACE("get timer failed.\n");
  428. exit(EXIT_FAILURE);
  429. }
  430. /* Set the interval between timer events. */
  431. itimer.it_interval.tv_sec = 0;
  432. itimer.it_interval.tv_usec = us;
  433. /* Set the current count-down. */
  434. itimer.it_value.tv_sec = 0;
  435. itimer.it_value.tv_usec = us;
  436. /* Set-up the timer interrupt. */
  437. if (0 != setitimer(TIMER_TYPE, &itimer, &oitimer))
  438. {
  439. TRACE("set timer failed.\n");
  440. exit(EXIT_FAILURE);
  441. }
  442. }
  443. static void mthread_signal_tick(int sig)
  444. {
  445. int res;
  446. pthread_t pid = pthread_self();
  447. if (sig == SIGALRM)
  448. {
  449. TRACE("pid <%x> signal: SIGALRM enter!\n", (unsigned int)pid);
  450. //systick_signal_flag = 1;
  451. TRACE("pid <%x> signal: SIGALRM leave!\n", (unsigned int)pid);
  452. }
  453. else
  454. {
  455. TRACE("got an unexpected signal <%d>\n", sig);
  456. exit(EXIT_FAILURE);
  457. }
  458. }
  459. /* isr return value: 1, should not be masked, if 0, can be masked */
  460. static int tick_interrupt_isr(void)
  461. {
  462. TRACE("isr: systick enter!\n");
  463. /* enter interrupt */
  464. rt_interrupt_enter();
  465. rt_tick_increase();
  466. /* leave interrupt */
  467. rt_interrupt_leave();
  468. TRACE("isr: systick leave!\n");
  469. return 0;
  470. }