ctime.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-08-21 zhangjun copy from minilibc
  9. * 2020-09-07 Meco Man combine gcc armcc iccarm
  10. * 2021-02-05 Meco Man add timegm()
  11. * 2021-02-07 Meco Man fixed gettimeofday()
  12. * 2021-02-08 Meco Man add settimeofday() stime()
  13. * 2021-02-10 Meco Man add ctime_r() and re-implement ctime()
  14. * 2021-02-11 Meco Man fix bug #3183 - align days[] and months[] to 4 bytes
  15. * 2021-02-12 Meco Man add errno
  16. * 2012-12-08 Bernard <clock_time.c> fix the issue of _timevalue.tv_usec initialization,
  17. * which found by Rob <rdent@iinet.net.au>
  18. * 2021-02-12 Meco Man move all of the functions located in <clock_time.c> to this file
  19. * 2021-03-15 Meco Man fixed a bug of leaking memory in asctime()
  20. * 2021-05-01 Meco Man support fixed timezone
  21. * 2021-07-21 Meco Man implement that change/set timezone APIs
  22. * 2023-07-03 xqyjlj refactor posix time and timer
  23. * 2023-07-16 Shell update signal generation routine for lwp
  24. * adapt to new api and do the signal handling in thread context
  25. * 2023-08-12 Meco Man re-implement RT-Thread lightweight timezone API
  26. * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
  27. * 2023-10-23 Shell add lock for _g_timerid
  28. * 2023-11-16 Shell Fixup of nanosleep if previous call was interrupted
  29. */
  30. #include "sys/time.h"
  31. #include <rthw.h>
  32. #include <rtthread.h>
  33. #ifdef RT_USING_RTC
  34. #include <rtdevice.h>
  35. #endif /* RT_USING_RTC */
  36. #include <sys/errno.h>
  37. #include <unistd.h>
  38. #ifdef RT_USING_SMART
  39. #include <lwp.h>
  40. #endif
  41. #ifdef RT_USING_POSIX_DELAY
  42. #include <delay.h>
  43. #endif
  44. #ifdef RT_USING_CLOCK_TIME
  45. #include <drivers/clock_time.h>
  46. #endif
  47. #define DBG_TAG "time"
  48. #define DBG_LVL DBG_INFO
  49. #include <rtdbg.h>
  50. #define _WARNING_NO_RTC "Cannot find a RTC device!"
  51. /* days per month -- nonleap! */
  52. static const short __spm[13] =
  53. {
  54. 0,
  55. (31),
  56. (31 + 28),
  57. (31 + 28 + 31),
  58. (31 + 28 + 31 + 30),
  59. (31 + 28 + 31 + 30 + 31),
  60. (31 + 28 + 31 + 30 + 31 + 30),
  61. (31 + 28 + 31 + 30 + 31 + 30 + 31),
  62. (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31),
  63. (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30),
  64. (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31),
  65. (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30),
  66. (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31),
  67. };
  68. rt_align(RT_ALIGN_SIZE) static const char days[] = "Sun Mon Tue Wed Thu Fri Sat ";
  69. rt_align(RT_ALIGN_SIZE) static const char months[] = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ";
  70. #ifndef __isleap
  71. static int __isleap(int year)
  72. {
  73. /* every fourth year is a leap year except for century years that are
  74. * not divisible by 400. */
  75. /* return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); */
  76. return (!(year % 4) && ((year % 100) || !(year % 400)));
  77. }
  78. #endif
  79. static void num2str(char *c, int i)
  80. {
  81. c[0] = i / 10 + '0';
  82. c[1] = i % 10 + '0';
  83. }
  84. #ifdef RT_USING_RTC
  85. static rt_err_t _control_rtc(int cmd, void *arg)
  86. {
  87. static rt_device_t device = RT_NULL;
  88. rt_err_t rst = -RT_ERROR;
  89. if (device == RT_NULL)
  90. {
  91. device = rt_device_find("rtc");
  92. }
  93. /* read timestamp from RTC device */
  94. if (device != RT_NULL)
  95. {
  96. if (rt_device_open(device, 0) == RT_EOK)
  97. {
  98. rst = rt_device_control(device, cmd, arg);
  99. rt_device_close(device);
  100. }
  101. }
  102. else
  103. {
  104. LOG_W(_WARNING_NO_RTC);
  105. return -RT_ENOSYS;
  106. }
  107. return rst;
  108. }
  109. #endif /* RT_USING_RTC */
  110. /* lightweight timezone and daylight saving time */
  111. #ifdef RT_LIBC_USING_LIGHT_TZ_DST
  112. #ifndef RT_LIBC_TZ_DEFAULT_HOUR
  113. #define RT_LIBC_TZ_DEFAULT_HOUR (8U)
  114. #endif /* RT_LIBC_TZ_DEFAULT_HOUR */
  115. #ifndef RT_LIBC_TZ_DEFAULT_MIN
  116. #define RT_LIBC_TZ_DEFAULT_MIN (0U)
  117. #endif /* RT_LIBC_TZ_DEFAULT_MIN */
  118. #ifndef RT_LIBC_TZ_DEFAULT_SEC
  119. #define RT_LIBC_TZ_DEFAULT_SEC (0U)
  120. #endif /* RT_LIBC_TZ_DEFAULT_SEC */
  121. static volatile int32_t _current_tz_offset_sec = \
  122. RT_LIBC_TZ_DEFAULT_HOUR * 3600U + RT_LIBC_TZ_DEFAULT_MIN * 60U + RT_LIBC_TZ_DEFAULT_SEC;
  123. /* return current timezone offset in seconds */
  124. void rt_tz_set(int32_t offset_sec)
  125. {
  126. _current_tz_offset_sec = offset_sec;
  127. }
  128. int32_t rt_tz_get(void)
  129. {
  130. return _current_tz_offset_sec;
  131. }
  132. int8_t rt_tz_is_dst(void)
  133. {
  134. return 0U; /* TODO */
  135. }
  136. #endif /* RT_LIBC_USING_LIGHT_TZ_DST */
  137. struct tm *gmtime_r(const time_t *timep, struct tm *r)
  138. {
  139. int i;
  140. int work;
  141. if(timep == RT_NULL || r == RT_NULL)
  142. {
  143. rt_set_errno(EFAULT);
  144. return RT_NULL;
  145. }
  146. rt_memset(r, RT_NULL, sizeof(struct tm));
  147. work = *timep % (24*60*60);
  148. r->tm_sec = work % 60;
  149. work /= 60;
  150. r->tm_min = work % 60;
  151. r->tm_hour = work / 60;
  152. work = (int)(*timep / (24*60*60));
  153. r->tm_wday = (4 + work) % 7;
  154. for (i = 1970;; ++i)
  155. {
  156. int k = __isleap(i) ? 366 : 365;
  157. if (work >= k)
  158. work -= k;
  159. else
  160. break;
  161. }
  162. r->tm_year = i - 1900;
  163. r->tm_yday = work;
  164. r->tm_mday = 1;
  165. if (__isleap(i) && (work > 58))
  166. {
  167. if (work == 59)
  168. r->tm_mday = 2; /* 29.2. */
  169. work -= 1;
  170. }
  171. for (i = 11; i && (__spm[i] > work); --i);
  172. r->tm_mon = i;
  173. r->tm_mday += work - __spm[i];
  174. #if defined(RT_LIBC_USING_LIGHT_TZ_DST)
  175. r->tm_isdst = rt_tz_is_dst();
  176. #else
  177. r->tm_isdst = 0U;
  178. #endif /* RT_LIBC_USING_LIGHT_TZ_DST */
  179. return r;
  180. }
  181. RTM_EXPORT(gmtime_r);
  182. struct tm* gmtime(const time_t* t)
  183. {
  184. static struct tm tmp;
  185. return gmtime_r(t, &tmp);
  186. }
  187. RTM_EXPORT(gmtime);
  188. struct tm* localtime_r(const time_t* t, struct tm* r)
  189. {
  190. time_t local_tz;
  191. #if defined(RT_LIBC_USING_LIGHT_TZ_DST)
  192. local_tz = *t + rt_tz_get();
  193. #else
  194. local_tz = *t + 0U;
  195. #endif /* RT_LIBC_USING_LIGHT_TZ_DST */
  196. return gmtime_r(&local_tz, r);
  197. }
  198. RTM_EXPORT(localtime_r);
  199. struct tm* localtime(const time_t* t)
  200. {
  201. static struct tm tmp;
  202. return localtime_r(t, &tmp);
  203. }
  204. RTM_EXPORT(localtime);
  205. time_t mktime(struct tm * const t)
  206. {
  207. time_t timestamp;
  208. timestamp = timegm(t);
  209. #if defined(RT_LIBC_USING_LIGHT_TZ_DST)
  210. timestamp = timestamp - rt_tz_get();
  211. #else
  212. timestamp = timestamp - 0U;
  213. #endif /* RT_LIBC_USING_LIGHT_TZ_DST */
  214. return timestamp;
  215. }
  216. RTM_EXPORT(mktime);
  217. char* asctime_r(const struct tm *t, char *buf)
  218. {
  219. if(t == RT_NULL || buf == RT_NULL)
  220. {
  221. rt_set_errno(EFAULT);
  222. return RT_NULL;
  223. }
  224. rt_memset(buf, RT_NULL, 26);
  225. /* Checking input validity */
  226. if ((int)rt_strlen(days) <= (t->tm_wday << 2) || (int)rt_strlen(months) <= (t->tm_mon << 2))
  227. {
  228. LOG_W("asctime_r: the input parameters exceeded the limit, please check it.");
  229. *(int*) buf = *(int*) days;
  230. *(int*) (buf + 4) = *(int*) months;
  231. num2str(buf + 8, t->tm_mday);
  232. if (buf[8] == '0')
  233. buf[8] = ' ';
  234. buf[10] = ' ';
  235. num2str(buf + 11, t->tm_hour);
  236. buf[13] = ':';
  237. num2str(buf + 14, t->tm_min);
  238. buf[16] = ':';
  239. num2str(buf + 17, t->tm_sec);
  240. buf[19] = ' ';
  241. num2str(buf + 20, 2000 / 100);
  242. num2str(buf + 22, 2000 % 100);
  243. buf[24] = '\n';
  244. buf[25] = '\0';
  245. return buf;
  246. }
  247. /* "Wed Jun 30 21:49:08 1993\n" */
  248. *(int*) buf = *(int*) (days + (t->tm_wday << 2));
  249. *(int*) (buf + 4) = *(int*) (months + (t->tm_mon << 2));
  250. num2str(buf + 8, t->tm_mday);
  251. if (buf[8] == '0')
  252. buf[8] = ' ';
  253. buf[10] = ' ';
  254. num2str(buf + 11, t->tm_hour);
  255. buf[13] = ':';
  256. num2str(buf + 14, t->tm_min);
  257. buf[16] = ':';
  258. num2str(buf + 17, t->tm_sec);
  259. buf[19] = ' ';
  260. num2str(buf + 20, (t->tm_year + 1900) / 100);
  261. num2str(buf + 22, (t->tm_year + 1900) % 100);
  262. buf[24] = '\n';
  263. buf[25] = '\0';
  264. return buf;
  265. }
  266. RTM_EXPORT(asctime_r);
  267. char *asctime(const struct tm *timeptr)
  268. {
  269. static char buf[26];
  270. return asctime_r(timeptr, buf);
  271. }
  272. RTM_EXPORT(asctime);
  273. char *ctime_r(const time_t * tim_p, char * result)
  274. {
  275. struct tm tm;
  276. return asctime_r(localtime_r(tim_p, &tm), result);
  277. }
  278. RTM_EXPORT(ctime_r);
  279. char *ctime(const time_t *tim_p)
  280. {
  281. return asctime(localtime(tim_p));
  282. }
  283. RTM_EXPORT(ctime);
  284. #if (!defined __ARMCC_VERSION) && (!defined __CC_ARM) && (!defined __ICCARM__)
  285. double difftime(time_t time1, time_t time2)
  286. {
  287. return (double)(time1 - time2);
  288. }
  289. #endif
  290. RTM_EXPORT(difftime);
  291. RTM_EXPORT(strftime); /* inherent in the toolchain */
  292. /**
  293. * Returns the current time.
  294. *
  295. * @param time_t * t the timestamp pointer, if not used, keep NULL.
  296. *
  297. * @return The value ((time_t)-1) is returned if the calendar time is not available.
  298. * If timer is not a NULL pointer, the return value is also stored in timer.
  299. *
  300. */
  301. rt_weak time_t time(time_t *t)
  302. {
  303. #ifdef RT_USING_RTC
  304. time_t _t;
  305. if (_control_rtc(RT_DEVICE_CTRL_RTC_GET_TIME, &_t) != RT_EOK)
  306. {
  307. rt_set_errno(EFAULT);
  308. return (time_t)-1;
  309. }
  310. if (t)
  311. *t = _t;
  312. return _t;
  313. #else
  314. rt_set_errno(EFAULT);
  315. return (time_t)-1;
  316. #endif
  317. }
  318. RTM_EXPORT(time);
  319. rt_weak clock_t clock(void)
  320. {
  321. return rt_tick_get(); // TODO should return cpu usage time
  322. }
  323. RTM_EXPORT(clock);
  324. int stime(const time_t *t)
  325. {
  326. #ifdef RT_USING_RTC
  327. if ((t != RT_NULL) && (_control_rtc(RT_DEVICE_CTRL_RTC_SET_TIME, (void *)t) == RT_EOK))
  328. {
  329. return 0;
  330. }
  331. #endif /* RT_USING_RTC */
  332. rt_set_errno(EFAULT);
  333. return -1;
  334. }
  335. RTM_EXPORT(stime);
  336. time_t timegm(struct tm * const t)
  337. {
  338. time_t day;
  339. time_t i;
  340. time_t years;
  341. if(t == RT_NULL)
  342. {
  343. rt_set_errno(EFAULT);
  344. return (time_t)-1;
  345. }
  346. years = (time_t)t->tm_year - 70;
  347. if (t->tm_sec > 60) /* seconds after the minute - [0, 60] including leap second */
  348. {
  349. t->tm_min += t->tm_sec / 60;
  350. t->tm_sec %= 60;
  351. }
  352. if (t->tm_min >= 60) /* minutes after the hour - [0, 59] */
  353. {
  354. t->tm_hour += t->tm_min / 60;
  355. t->tm_min %= 60;
  356. }
  357. if (t->tm_hour >= 24) /* hours since midnight - [0, 23] */
  358. {
  359. t->tm_mday += t->tm_hour / 24;
  360. t->tm_hour %= 24;
  361. }
  362. if (t->tm_mon >= 12) /* months since January - [0, 11] */
  363. {
  364. t->tm_year += t->tm_mon / 12;
  365. t->tm_mon %= 12;
  366. }
  367. while (t->tm_mday > __spm[1 + t->tm_mon])
  368. {
  369. if (t->tm_mon == 1 && __isleap(t->tm_year + 1900))
  370. {
  371. --t->tm_mday;
  372. }
  373. t->tm_mday -= __spm[t->tm_mon];
  374. ++t->tm_mon;
  375. if (t->tm_mon > 11)
  376. {
  377. t->tm_mon = 0;
  378. ++t->tm_year;
  379. }
  380. }
  381. if (t->tm_year < 70)
  382. {
  383. rt_set_errno(EINVAL);
  384. return (time_t) -1;
  385. }
  386. /* Days since 1970 is 365 * number of years + number of leap years since 1970 */
  387. day = years * 365 + (years + 1) / 4;
  388. /* After 2100 we have to substract 3 leap years for every 400 years
  389. This is not intuitive. Most mktime implementations do not support
  390. dates after 2059, anyway, so we might leave this out for it's
  391. bloat. */
  392. if (years >= 131)
  393. {
  394. years -= 131;
  395. years /= 100;
  396. day -= (years >> 2) * 3 + 1;
  397. if ((years &= 3) == 3)
  398. years--;
  399. day -= years;
  400. }
  401. day += t->tm_yday = __spm[t->tm_mon] + t->tm_mday - 1 +
  402. (__isleap(t->tm_year + 1900) & (t->tm_mon > 1));
  403. /* day is now the number of days since 'Jan 1 1970' */
  404. i = 7;
  405. t->tm_wday = (int)((day + 4) % i); /* Sunday=0, Monday=1, ..., Saturday=6 */
  406. i = 24;
  407. day *= i;
  408. i = 60;
  409. return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec;
  410. }
  411. RTM_EXPORT(timegm);
  412. int gettimeofday(struct timeval *tv, struct timezone *tz)
  413. {
  414. /* The use of the timezone structure is obsolete;
  415. * the tz argument should normally be specified as NULL.
  416. * The tz_dsttime field has never been used under Linux.
  417. * Thus, the following is purely of historic interest.
  418. */
  419. if(tz != RT_NULL)
  420. {
  421. tz->tz_dsttime = DST_NONE;
  422. #if defined(RT_LIBC_USING_LIGHT_TZ_DST)
  423. tz->tz_minuteswest = -(rt_tz_get() / 60);
  424. #else
  425. tz->tz_minuteswest = 0;
  426. #endif /* RT_LIBC_USING_LIGHT_TZ_DST */
  427. }
  428. #ifdef RT_USING_RTC
  429. if (tv != RT_NULL)
  430. {
  431. tv->tv_sec = 0;
  432. tv->tv_usec = 0;
  433. if (_control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMEVAL, tv) == RT_EOK)
  434. {
  435. return 0;
  436. }
  437. else
  438. {
  439. if (_control_rtc(RT_DEVICE_CTRL_RTC_GET_TIME, (void *)&tv->tv_sec) == RT_EOK)
  440. {
  441. return 0;
  442. }
  443. }
  444. }
  445. #endif /* RT_USING_RTC */
  446. rt_set_errno(EINVAL);
  447. return -1;
  448. }
  449. RTM_EXPORT(gettimeofday);
  450. int settimeofday(const struct timeval *tv, const struct timezone *tz)
  451. {
  452. /* The use of the timezone structure is obsolete;
  453. * the tz argument should normally be specified as NULL.
  454. * The tz_dsttime field has never been used under Linux.
  455. * Thus, the following is purely of historic interest.
  456. */
  457. #ifdef RT_USING_RTC
  458. if (tv != RT_NULL && (long)tv->tv_usec >= 0 && (long)tv->tv_sec >= 0)
  459. {
  460. if (_control_rtc(RT_DEVICE_CTRL_RTC_SET_TIMEVAL, (void *)tv) == RT_EOK)
  461. {
  462. return 0;
  463. }
  464. else
  465. {
  466. if (_control_rtc(RT_DEVICE_CTRL_RTC_SET_TIME, (void *)&tv->tv_sec) == RT_EOK)
  467. {
  468. return 0;
  469. }
  470. }
  471. }
  472. #endif /* RT_USING_RTC */
  473. rt_set_errno(EINVAL);
  474. return -1;
  475. }
  476. RTM_EXPORT(settimeofday);
  477. #if defined(RT_USING_POSIX_DELAY) && defined(RT_USING_CLOCK_TIME)
  478. int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
  479. {
  480. struct timespec old_ts = {0};
  481. struct timespec new_ts = {0};
  482. if (rqtp == RT_NULL)
  483. {
  484. rt_set_errno(EFAULT);
  485. return -1;
  486. }
  487. if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NANOSECOND_PER_SECOND)
  488. {
  489. rt_set_errno(EINVAL);
  490. return -1;
  491. }
  492. unsigned long ns = rqtp->tv_sec * NANOSECOND_PER_SECOND + rqtp->tv_nsec;
  493. rt_clock_time_boottime_ns(&old_ts);
  494. rt_clock_ndelay(ns);
  495. if (rt_get_errno() == RT_EINTR)
  496. {
  497. if (rmtp)
  498. {
  499. rt_base_t rsec, rnsec;
  500. rt_clock_time_boottime_ns(&new_ts);
  501. rsec = old_ts.tv_sec + rqtp->tv_sec - new_ts.tv_sec;
  502. rnsec = old_ts.tv_nsec + rqtp->tv_nsec - new_ts.tv_nsec;
  503. if (rnsec < 0)
  504. {
  505. rmtp->tv_sec = rsec - 1;
  506. rmtp->tv_nsec = NANOSECOND_PER_SECOND + rnsec;
  507. }
  508. else
  509. {
  510. rmtp->tv_sec = rsec;
  511. rmtp->tv_nsec = rnsec;
  512. }
  513. }
  514. rt_set_errno(EINTR);
  515. return -1;
  516. }
  517. return 0;
  518. }
  519. RTM_EXPORT(nanosleep);
  520. #endif /* RT_USING_POSIX_DELAY && RT_USING_CLOCK_TIME */
  521. #if defined(RT_USING_POSIX_CLOCK) && defined(RT_USING_CLOCK_TIME)
  522. int clock_getres(clockid_t clockid, struct timespec *res)
  523. {
  524. if (res == RT_NULL)
  525. {
  526. rt_set_errno(EFAULT);
  527. return -1;
  528. }
  529. switch (clockid)
  530. {
  531. case CLOCK_REALTIME: // use RTC
  532. case CLOCK_REALTIME_COARSE:
  533. #ifdef RT_USING_RTC
  534. return _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMERES, res);
  535. #endif /* RT_USING_RTC */
  536. case CLOCK_MONOTONIC: // use cputimer
  537. case CLOCK_MONOTONIC_COARSE:
  538. case CLOCK_MONOTONIC_RAW:
  539. case CLOCK_BOOTTIME:
  540. case CLOCK_PROCESS_CPUTIME_ID:
  541. case CLOCK_THREAD_CPUTIME_ID:
  542. res->tv_sec = 0;
  543. res->tv_nsec = (rt_clock_time_getres() / RT_CLOCK_TIME_RESMUL);
  544. return 0;
  545. default:
  546. rt_set_errno(EINVAL);
  547. return -1;
  548. }
  549. }
  550. RTM_EXPORT(clock_getres);
  551. int clock_gettime(clockid_t clockid, struct timespec *tp)
  552. {
  553. if (tp == RT_NULL)
  554. {
  555. rt_set_errno(EFAULT);
  556. return -1;
  557. }
  558. switch (clockid)
  559. {
  560. case CLOCK_REALTIME: // use RTC
  561. case CLOCK_REALTIME_COARSE:
  562. #ifdef RT_USING_RTC
  563. return _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMESPEC, tp);
  564. #endif /* RT_USING_RTC */
  565. case CLOCK_MONOTONIC: // use boottime
  566. case CLOCK_MONOTONIC_COARSE:
  567. case CLOCK_MONOTONIC_RAW:
  568. case CLOCK_BOOTTIME:
  569. return rt_clock_time_boottime_ns(tp);
  570. case CLOCK_PROCESS_CPUTIME_ID:
  571. case CLOCK_THREAD_CPUTIME_ID:
  572. return rt_clock_time_boottime_ns(tp); // TODO not yet implemented
  573. default:
  574. tp->tv_sec = 0;
  575. tp->tv_nsec = 0;
  576. rt_set_errno(EINVAL);
  577. return -1;
  578. }
  579. }
  580. RTM_EXPORT(clock_gettime);
  581. int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, struct timespec *rmtp)
  582. {
  583. struct timespec ts = {0};
  584. rt_err_t err = -RT_EINVAL;
  585. if (rqtp == RT_NULL)
  586. {
  587. rt_set_errno(EFAULT);
  588. return -1;
  589. }
  590. if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NANOSECOND_PER_SECOND)
  591. {
  592. rt_set_errno(EINVAL);
  593. return -1;
  594. }
  595. switch (clockid)
  596. {
  597. case CLOCK_REALTIME: // use RTC
  598. #ifdef RT_USING_RTC
  599. if (flags & TIMER_ABSTIME)
  600. err = _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMESPEC, &ts);
  601. break;
  602. #endif /* RT_USING_RTC */
  603. case CLOCK_MONOTONIC: // use boottime
  604. case CLOCK_PROCESS_CPUTIME_ID:
  605. if (flags & TIMER_ABSTIME)
  606. err = rt_clock_time_boottime_ns(&ts);
  607. break;
  608. default:
  609. rt_set_errno(EINVAL);
  610. return -1;
  611. }
  612. if (err != RT_EOK)
  613. return err;
  614. rt_int64_t ns = rqtp->tv_nsec - ts.tv_nsec + (rt_int64_t)(rqtp->tv_sec - ts.tv_sec) * NANOSECOND_PER_SECOND;
  615. if (ns <= 0)
  616. return 0;
  617. if (flags & TIMER_ABSTIME)
  618. {
  619. ts.tv_nsec = ns % NANOSECOND_PER_SECOND;
  620. ts.tv_sec = ns / NANOSECOND_PER_SECOND;
  621. return nanosleep(&ts, rmtp);
  622. }
  623. else
  624. {
  625. return nanosleep(rqtp, rmtp);
  626. }
  627. }
  628. RTM_EXPORT(clock_nanosleep);
  629. int clock_settime(clockid_t clockid, const struct timespec *tp)
  630. {
  631. if (tp == RT_NULL)
  632. {
  633. rt_set_errno(EFAULT);
  634. return -1;
  635. }
  636. if (tp->tv_sec < 0 || tp->tv_nsec < 0 || tp->tv_nsec >= NANOSECOND_PER_SECOND)
  637. {
  638. rt_set_errno(EINVAL);
  639. return -1;
  640. }
  641. switch (clockid)
  642. {
  643. #ifdef RT_USING_RTC
  644. case CLOCK_REALTIME:
  645. return _control_rtc(RT_DEVICE_CTRL_RTC_SET_TIMESPEC, (void *)tp);
  646. #endif /* RT_USING_RTC */
  647. case CLOCK_REALTIME_COARSE:
  648. case CLOCK_MONOTONIC:
  649. case CLOCK_MONOTONIC_COARSE:
  650. case CLOCK_MONOTONIC_RAW:
  651. case CLOCK_BOOTTIME:
  652. case CLOCK_PROCESS_CPUTIME_ID:
  653. case CLOCK_THREAD_CPUTIME_ID:
  654. rt_set_errno(EPERM);
  655. return -1;
  656. default:
  657. rt_set_errno(EINVAL);
  658. return -1;
  659. }
  660. }
  661. RTM_EXPORT(clock_settime);
  662. #endif /* RT_USING_POSIX_CLOCK && RT_USING_CLOCK_TIME */
  663. #ifdef RT_USING_POSIX_CLOCK
  664. /**
  665. * @brief Convert absolute timespec to relative tick
  666. * @param time Absolute time
  667. * @return Relative tick value
  668. *
  669. * @note This function is available when RT_USING_POSIX_CLOCK is defined,
  670. * regardless of RT_USING_CLOCK_TIME, to support POSIX semaphores and other APIs.
  671. */
  672. int rt_timespec_to_tick(const struct timespec *time)
  673. {
  674. int tick;
  675. int second;
  676. long long nsecond;
  677. struct timespec tp = {0};
  678. RT_ASSERT(time != RT_NULL);
  679. tick = RT_WAITING_FOREVER;
  680. if (time != NULL)
  681. {
  682. /* get current tp */
  683. clock_gettime(CLOCK_REALTIME, &tp);
  684. if ((time->tv_nsec - tp.tv_nsec) < 0)
  685. {
  686. nsecond = NANOSECOND_PER_SECOND - (tp.tv_nsec - time->tv_nsec);
  687. second = time->tv_sec - tp.tv_sec - 1;
  688. }
  689. else
  690. {
  691. nsecond = time->tv_nsec - tp.tv_nsec;
  692. second = time->tv_sec - tp.tv_sec;
  693. }
  694. tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND;
  695. if (tick < 0) tick = 0;
  696. }
  697. return tick;
  698. }
  699. RTM_EXPORT(rt_timespec_to_tick);
  700. #endif /* RT_USING_POSIX_CLOCK */
  701. #if defined(RT_USING_POSIX_TIMER) && defined(RT_USING_CLOCK_TIME)
  702. #include <resource_id.h>
  703. #define ACTIVE 1
  704. #define NOT_ACTIVE 0
  705. struct timer_obj
  706. {
  707. struct rt_clock_hrtimer hrtimer;
  708. void (*sigev_notify_func)(union sigval val);
  709. union sigval val;
  710. struct timespec interval; /* Reload value */
  711. struct timespec value; /* Reload value */
  712. unsigned long reload; /* Reload value in ms */
  713. rt_uint32_t status;
  714. int sigev_signo;
  715. clockid_t clockid;
  716. timer_t timer_id;
  717. #ifdef RT_USING_SMART
  718. pid_t pid;
  719. struct rt_work *work;
  720. rt_list_t lwp_node;
  721. #endif
  722. };
  723. #ifdef RT_USING_SMART
  724. struct lwp_timer_event_param
  725. {
  726. struct rt_work work;
  727. union
  728. {
  729. int tid;
  730. pid_t pid;
  731. };
  732. int signo;
  733. };
  734. static void _lwp_timer_event_from_tid(struct rt_work *work, void *param)
  735. {
  736. rt_err_t ret;
  737. struct lwp_timer_event_param *data = rt_container_of(work, struct lwp_timer_event_param, work);
  738. rt_thread_t thread;
  739. RT_ASSERT(data->tid);
  740. /* stop others from delete thread */
  741. thread = lwp_tid_get_thread_and_inc_ref(data->tid);
  742. /** The tid of thread is a READ ONLY value, but here still facing the risk of thread already been delete error */
  743. ret = lwp_thread_signal_kill(thread, data->signo, SI_TIMER, 0);
  744. lwp_tid_dec_ref(thread);
  745. if (ret)
  746. {
  747. LOG_D("%s: Do kill failed(tid %d) returned %d", __func__, data->tid, ret);
  748. }
  749. }
  750. static void _lwp_timer_event_from_pid(struct rt_work *work, void *param)
  751. {
  752. rt_err_t ret;
  753. struct lwp_timer_event_param *data = rt_container_of(work, struct lwp_timer_event_param, work);
  754. struct rt_lwp *lwp;
  755. lwp_pid_lock_take();
  756. lwp = lwp_from_pid_locked(data->pid);
  757. if (lwp)
  758. lwp_ref_inc(lwp);
  759. lwp_pid_lock_release();
  760. ret = lwp_signal_kill(lwp, data->signo, SI_TIMER, 0);
  761. if (lwp)
  762. lwp_ref_dec(lwp);
  763. if (ret)
  764. {
  765. LOG_D("%s: Do kill failed(pid %d) returned %d", __func__, data->pid, ret);
  766. }
  767. }
  768. int timer_list_free(rt_list_t *timer_list)
  769. {
  770. struct timer_obj *pos, *n;
  771. rt_list_for_each_entry_safe(pos, n, timer_list, lwp_node)
  772. {
  773. timer_delete(pos->timer_id);
  774. }
  775. return 0;
  776. }
  777. #endif /* RT_USING_SMART */
  778. static void rtthread_timer_wrapper(void *timerobj)
  779. {
  780. struct timer_obj *timer;
  781. timer = (struct timer_obj *)timerobj;
  782. if (timer->reload == 0U)
  783. {
  784. timer->status = NOT_ACTIVE;
  785. }
  786. timer->reload = ((timer->interval.tv_sec * NANOSECOND_PER_SECOND + timer->interval.tv_nsec) * RT_CLOCK_TIME_RESMUL) /
  787. rt_clock_time_getres();
  788. if (timer->reload)
  789. {
  790. rt_clock_hrtimer_start(&timer->hrtimer, timer->reload);
  791. }
  792. #ifdef RT_USING_SMART
  793. /* this field is named as tid in musl */
  794. void *ptid = &timer->sigev_notify_func;
  795. int tid = *(int *)ptid;
  796. struct lwp_timer_event_param *data = rt_container_of(timer->work, struct lwp_timer_event_param, work);
  797. data->signo = timer->sigev_signo;
  798. if (!tid)
  799. {
  800. data->pid = timer->pid;
  801. rt_work_init(timer->work, _lwp_timer_event_from_pid, 0);
  802. }
  803. else
  804. {
  805. data->tid = tid;
  806. rt_work_init(timer->work, _lwp_timer_event_from_tid, 0);
  807. }
  808. if (rt_work_submit(timer->work, 0))
  809. RT_ASSERT(0);
  810. #else
  811. if(timer->sigev_notify_func != RT_NULL)
  812. {
  813. (timer->sigev_notify_func)(timer->val);
  814. }
  815. #endif /* RT_USING_SMART */
  816. }
  817. #define TIMER_ID_MAX 50
  818. static struct rt_spinlock _timer_id_lock = RT_SPINLOCK_INIT;
  819. static struct timer_obj *_g_timerid[TIMER_ID_MAX];
  820. static void *timer_id[TIMER_ID_MAX];
  821. static resource_id_t id_timer = RESOURCE_ID_INIT(TIMER_ID_MAX, timer_id);
  822. /**
  823. * @brief Create a per-process timer.
  824. *
  825. * This API does not accept SIGEV_THREAD as valid signal event notification
  826. * type.
  827. *
  828. * See IEEE 1003.1
  829. */
  830. int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
  831. {
  832. static int num = 0;
  833. int _timerid = 0;
  834. struct timer_obj *timer;
  835. char timername[RT_NAME_MAX] = {0};
  836. if (evp == RT_NULL || timerid == RT_NULL)
  837. {
  838. rt_set_errno(EINVAL);
  839. return -1;
  840. }
  841. if (evp->sigev_notify == SIGEV_THREAD) // TODO need to implement
  842. {
  843. rt_set_errno(EINVAL);
  844. return -1;
  845. }
  846. switch (clockid)
  847. {
  848. case CLOCK_REALTIME:
  849. case CLOCK_REALTIME_ALARM:
  850. case CLOCK_MONOTONIC:
  851. case CLOCK_BOOTTIME:
  852. case CLOCK_BOOTTIME_ALARM:
  853. case CLOCK_PROCESS_CPUTIME_ID:
  854. case CLOCK_THREAD_CPUTIME_ID:
  855. break; // Only these ids are supported
  856. default:
  857. rt_set_errno(EINVAL);
  858. return -1;
  859. }
  860. timer = rt_malloc(sizeof(struct timer_obj));
  861. if(timer == RT_NULL)
  862. {
  863. rt_set_errno(ENOMEM);
  864. return -1;
  865. }
  866. rt_snprintf(timername, RT_NAME_MAX, "psx_tm%02d", num++);
  867. num %= 100;
  868. timer->sigev_signo = evp->sigev_signo;
  869. #ifdef RT_USING_SMART
  870. struct rt_work *work;
  871. struct rt_lwp *lwp = lwp_self();
  872. struct lwp_timer_event_param *param;
  873. param = rt_malloc(sizeof(struct lwp_timer_event_param));
  874. work = &param->work;
  875. if (!work)
  876. {
  877. rt_set_errno(ENOMEM);
  878. return -1;
  879. }
  880. if (lwp)
  881. {
  882. timer->pid = lwp_self()->pid;
  883. rt_list_insert_after(&lwp->timer, &timer->lwp_node);
  884. }
  885. else
  886. {
  887. timer->pid = 0; /* pid 0 is never used */
  888. }
  889. timer->work = work;
  890. #endif /* RT_USING_SMART */
  891. timer->sigev_notify_func = evp->sigev_notify_function;
  892. timer->val = evp->sigev_value;
  893. timer->interval.tv_sec = 0;
  894. timer->interval.tv_nsec = 0;
  895. timer->reload = 0U;
  896. timer->status = NOT_ACTIVE;
  897. timer->clockid = clockid;
  898. rt_clock_hrtimer_init(&timer->hrtimer, timername, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_HARD_TIMER,
  899. rtthread_timer_wrapper, timer);
  900. _timerid = resource_id_get(&id_timer);
  901. if (_timerid < 0)
  902. {
  903. #ifdef RT_USING_SMART
  904. rt_free(param);
  905. #endif /* RT_USING_SMART */
  906. rt_clock_hrtimer_detach(&timer->hrtimer);
  907. rt_free(timer);
  908. rt_set_errno(ENOMEM);
  909. return -1;
  910. }
  911. _g_timerid[_timerid] = timer;
  912. timer->timer_id = (timer_t)(rt_ubase_t)_timerid;
  913. *timerid = (timer_t)(rt_ubase_t)_timerid;
  914. return 0;
  915. }
  916. RTM_EXPORT(timer_create);
  917. /**
  918. * @brief Delete a per-process timer.
  919. *
  920. * See IEEE 1003.1
  921. */
  922. int timer_delete(timer_t timerid)
  923. {
  924. struct timer_obj *timer;
  925. rt_ubase_t ktimerid;
  926. ktimerid = (rt_ubase_t)timerid;
  927. if (ktimerid < 0 || ktimerid >= TIMER_ID_MAX)
  928. {
  929. rt_set_errno(EINVAL);
  930. return -1;
  931. }
  932. RT_DEBUG_NOT_IN_INTERRUPT;
  933. rt_spin_lock(&_timer_id_lock);
  934. timer = _g_timerid[ktimerid];
  935. if (timer != NULL)
  936. {
  937. _g_timerid[ktimerid] = RT_NULL;
  938. resource_id_put(&id_timer, ktimerid);
  939. }
  940. rt_spin_unlock(&_timer_id_lock);
  941. if (timer == RT_NULL)
  942. {
  943. rt_set_errno(EINVAL);
  944. LOG_D("can not find timer %ld", ktimerid);
  945. return -1;
  946. }
  947. if (timer->status == ACTIVE)
  948. {
  949. timer->status = NOT_ACTIVE;
  950. rt_clock_hrtimer_stop(&timer->hrtimer);
  951. }
  952. rt_clock_hrtimer_detach(&timer->hrtimer);
  953. #ifdef RT_USING_SMART
  954. if (timer->pid)
  955. rt_list_remove(&timer->lwp_node);
  956. rt_free(timer->work);
  957. #endif
  958. rt_free(timer);
  959. return 0;
  960. }
  961. RTM_EXPORT(timer_delete);
  962. /**
  963. *
  964. * Return the overrun count for the last timer expiration.
  965. * It is subefficient to create a new structure to get overrun count.
  966. **/
  967. int timer_getoverrun(timer_t timerid)
  968. {
  969. rt_set_errno(ENOSYS);
  970. return -1;
  971. }
  972. /**
  973. * @brief Get amount of time left for expiration on a per-process timer.
  974. *
  975. * See IEEE 1003.1
  976. */
  977. int timer_gettime(timer_t timerid, struct itimerspec *its)
  978. {
  979. struct timer_obj *timer;
  980. rt_uint32_t seconds, nanoseconds;
  981. timer = _g_timerid[(rt_ubase_t)timerid];
  982. if (timer == NULL)
  983. {
  984. rt_set_errno(EINVAL);
  985. return -1;
  986. }
  987. if (its == NULL)
  988. {
  989. rt_set_errno(EFAULT);
  990. return -1;
  991. }
  992. if (timer->status == ACTIVE)
  993. {
  994. unsigned long remain_cnt;
  995. rt_clock_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_GET_REMAIN_TIME, &remain_cnt);
  996. nanoseconds = ((remain_cnt - rt_clock_time_getcnt()) * rt_clock_time_getres()) / RT_CLOCK_TIME_RESMUL;
  997. seconds = nanoseconds / NANOSECOND_PER_SECOND;
  998. nanoseconds = nanoseconds % NANOSECOND_PER_SECOND;
  999. its->it_value.tv_sec = (rt_int32_t)seconds;
  1000. its->it_value.tv_nsec = (rt_int32_t)nanoseconds;
  1001. }
  1002. else
  1003. {
  1004. /* Timer is disarmed */
  1005. its->it_value.tv_sec = 0;
  1006. its->it_value.tv_nsec = 0;
  1007. }
  1008. /* The interval last set by timer_settime() */
  1009. its->it_interval = timer->interval;
  1010. return 0;
  1011. }
  1012. RTM_EXPORT(timer_gettime);
  1013. /**
  1014. * @brief Sets expiration time of per-process timer.
  1015. *
  1016. * See IEEE 1003.1
  1017. */
  1018. int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
  1019. struct itimerspec *ovalue)
  1020. {
  1021. struct timespec ts = {0};
  1022. rt_err_t err = RT_EOK;
  1023. struct timer_obj *timer;
  1024. timer = _g_timerid[(rt_ubase_t)timerid];
  1025. if (timer == NULL ||
  1026. value->it_interval.tv_nsec < 0 ||
  1027. value->it_interval.tv_nsec >= NANOSECOND_PER_SECOND ||
  1028. value->it_interval.tv_sec < 0 ||
  1029. value->it_value.tv_nsec < 0 ||
  1030. value->it_value.tv_nsec >= NANOSECOND_PER_SECOND ||
  1031. value->it_value.tv_sec < 0)
  1032. {
  1033. rt_set_errno(EINVAL);
  1034. return -1;
  1035. }
  1036. /* Save time to expire and old reload value. */
  1037. if (ovalue != NULL)
  1038. {
  1039. timer_gettime(timerid, ovalue);
  1040. }
  1041. /* Stop the timer if the value is 0 */
  1042. if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0))
  1043. {
  1044. if (timer->status == ACTIVE)
  1045. {
  1046. rt_clock_hrtimer_stop(&timer->hrtimer);
  1047. }
  1048. timer->status = NOT_ACTIVE;
  1049. return 0;
  1050. }
  1051. switch (timer->clockid)
  1052. {
  1053. #ifdef RT_USING_RTC
  1054. case CLOCK_REALTIME:
  1055. case CLOCK_REALTIME_ALARM:
  1056. if (flags & TIMER_ABSTIME)
  1057. err = _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMESPEC, &ts);
  1058. break;
  1059. #endif /* RT_USING_RTC */
  1060. case CLOCK_MONOTONIC:
  1061. case CLOCK_BOOTTIME:
  1062. case CLOCK_BOOTTIME_ALARM:
  1063. case CLOCK_PROCESS_CPUTIME_ID:
  1064. case CLOCK_THREAD_CPUTIME_ID:
  1065. if (flags & TIMER_ABSTIME)
  1066. err = rt_clock_time_boottime_ns(&ts);
  1067. break;
  1068. default:
  1069. rt_set_errno(EINVAL);
  1070. return -1;
  1071. }
  1072. if (err != RT_EOK)
  1073. return err;
  1074. rt_int64_t ns = value->it_value.tv_nsec - ts.tv_nsec + (rt_int64_t)(value->it_value.tv_sec - ts.tv_sec) * NANOSECOND_PER_SECOND;
  1075. if (ns <= 0)
  1076. return 0;
  1077. unsigned long res = rt_clock_time_getres();
  1078. timer->reload = (ns * RT_CLOCK_TIME_RESMUL) / res;
  1079. timer->interval.tv_sec = value->it_interval.tv_sec;
  1080. timer->interval.tv_nsec = value->it_interval.tv_nsec;
  1081. timer->value.tv_sec = value->it_value.tv_sec;
  1082. timer->value.tv_nsec = value->it_value.tv_nsec;
  1083. if (timer->status == ACTIVE)
  1084. {
  1085. rt_clock_hrtimer_stop(&timer->hrtimer);
  1086. }
  1087. timer->status = ACTIVE;
  1088. if ((value->it_interval.tv_sec == 0) && (value->it_interval.tv_nsec == 0))
  1089. rt_clock_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_SET_ONESHOT, RT_NULL);
  1090. else
  1091. rt_clock_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL);
  1092. rt_clock_hrtimer_start(&timer->hrtimer, timer->reload);
  1093. return 0;
  1094. }
  1095. RTM_EXPORT(timer_settime);
  1096. #endif /* RT_USING_POSIX_TIMER && RT_USING_CLOCK_TIME */