Kernel.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450
  1. // SoftEther VPN Source Code - Stable Edition Repository
  2. // Mayaqua Kernel
  3. //
  4. // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
  5. //
  6. // Copyright (c) Daiyuu Nobori.
  7. // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
  8. // Copyright (c) SoftEther Corporation.
  9. // Copyright (c) all contributors on SoftEther VPN project in GitHub.
  10. //
  11. // All Rights Reserved.
  12. //
  13. // http://www.softether.org/
  14. //
  15. // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
  16. // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
  17. // Contributors:
  18. // - nattoheaven (https://github.com/nattoheaven)
  19. //
  20. // License: The Apache License, Version 2.0
  21. // https://www.apache.org/licenses/LICENSE-2.0
  22. //
  23. // DISCLAIMER
  24. // ==========
  25. //
  26. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  27. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  28. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  29. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  30. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  31. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  32. // SOFTWARE.
  33. //
  34. // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
  35. // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
  36. // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
  37. // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
  38. // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
  39. // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
  40. // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
  41. // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
  42. // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
  43. // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
  44. // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
  45. // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
  46. // LAW OR COURT RULE.
  47. //
  48. // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
  49. // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
  50. // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
  51. // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
  52. // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
  53. // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
  54. // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
  55. // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
  56. // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
  57. // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
  58. // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
  59. // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
  60. // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
  61. // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
  62. // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
  63. // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
  64. // STATEMENT FOR WARNING AND DISCLAIMER.
  65. //
  66. // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
  67. // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
  68. // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
  69. //
  70. //
  71. // SOURCE CODE CONTRIBUTION
  72. // ------------------------
  73. //
  74. // Your contribution to SoftEther VPN Project is much appreciated.
  75. // Please send patches to us through GitHub.
  76. // Read the SoftEther VPN Patch Acceptance Policy in advance:
  77. // http://www.softether.org/5-download/src/9.patch
  78. //
  79. //
  80. // DEAR SECURITY EXPERTS
  81. // ---------------------
  82. //
  83. // If you find a bug or a security vulnerability please kindly inform us
  84. // about the problem immediately so that we can fix the security problem
  85. // to protect a lot of users around the world as soon as possible.
  86. //
  87. // Our e-mail address for security reports is:
  88. // softether-vpn-security [at] softether.org
  89. //
  90. // Please note that the above e-mail address is not a technical support
  91. // inquiry address. If you need technical assistance, please visit
  92. // http://www.softether.org/ and ask your question on the users forum.
  93. //
  94. // Thank you for your cooperation.
  95. //
  96. //
  97. // NO MEMORY OR RESOURCE LEAKS
  98. // ---------------------------
  99. //
  100. // The memory-leaks and resource-leaks verification under the stress
  101. // test has been passed before release this source code.
  102. // Kernel.c
  103. // System service processing routine
  104. #include <GlobalConst.h>
  105. #include <stdio.h>
  106. #include <stdlib.h>
  107. #include <string.h>
  108. #include <wchar.h>
  109. #include <stdarg.h>
  110. #include <time.h>
  111. #include <errno.h>
  112. #include <Mayaqua/Mayaqua.h>
  113. #ifndef TM_YEAR_MAX
  114. #define TM_YEAR_MAX 2106
  115. #endif
  116. #ifndef TM_MON_MAX
  117. #define TM_MON_MAX 1
  118. #endif
  119. #ifndef TM_MDAY_MAX
  120. #define TM_MDAY_MAX 7
  121. #endif
  122. #ifndef TM_HOUR_MAX
  123. #define TM_HOUR_MAX 6
  124. #endif
  125. #ifndef TM_MIN_MAX
  126. #define TM_MIN_MAX 28
  127. #endif
  128. #ifndef TM_SEC_MAX
  129. #define TM_SEC_MAX 14
  130. #endif
  131. #define ADJUST_TM(tm_member, tm_carry, modulus) \
  132. if ((tm_member) < 0){ \
  133. tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
  134. tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
  135. } else if ((tm_member) >= (modulus)) { \
  136. tm_carry += (tm_member) / (modulus); \
  137. tm_member = (tm_member) % (modulus); \
  138. }
  139. #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  140. #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
  141. #define leapday(m, y) ((m) == 1 && leap (y))
  142. #define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
  143. static int ydays[] =
  144. {
  145. 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  146. };
  147. static UINT current_num_thread = 0;
  148. static UINT cached_number_of_cpus = 0;
  149. static wchar_t *default_locale_str =
  150. L"- - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)";
  151. static LOCALE current_locale;
  152. LOCK *tick_manual_lock = NULL;
  153. UINT g_zero = 0;
  154. #define MONSPERYEAR 12
  155. #define DAYSPERNYEAR 365
  156. #define DAYSPERLYEAR 366
  157. #define SECSPERMIN 60
  158. #define SECSPERHOUR (60*60)
  159. #define SECSPERDAY (24*60*60)
  160. #define DAYSPERWEEK 7
  161. #define TM_SUNDAY 0
  162. #define TM_MONDAY 1
  163. #define TM_TUESDAY 2
  164. #define TM_WEDNESDAY 3
  165. #define TM_THURSDAY 4
  166. #define TM_FRIDAY 5
  167. #define TM_SATURDAY 6
  168. #define TM_YEAR_BASE 1900
  169. #define EPOCH_YEAR 1970
  170. #define EPOCH_WDAY TM_THURSDAY
  171. #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
  172. static const int mon_lengths[2][MONSPERYEAR] = {
  173. { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  174. { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  175. };
  176. static const int year_lengths[2] = {
  177. DAYSPERNYEAR, DAYSPERLYEAR
  178. };
  179. /*
  180. * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
  181. * localtime.c 7.78.
  182. * tzfile.h 1.8
  183. * adapted to be replacement gmtime_r.
  184. */
  185. static void
  186. c_timesub(timep, offset, tmp)
  187. const time_64t * const timep;
  188. const long offset;
  189. struct tm * const tmp;
  190. {
  191. INT64 days;
  192. INT64 rem;
  193. INT64 y;
  194. int yleap;
  195. const int * ip;
  196. days = *timep / SECSPERDAY;
  197. rem = *timep % SECSPERDAY;
  198. rem += (offset);
  199. while (rem < 0) {
  200. rem += SECSPERDAY;
  201. --days;
  202. }
  203. while (rem >= SECSPERDAY) {
  204. rem -= SECSPERDAY;
  205. ++days;
  206. }
  207. tmp->tm_hour = (int) (rem / SECSPERHOUR);
  208. rem = rem % SECSPERHOUR;
  209. tmp->tm_min = (int) (rem / SECSPERMIN);
  210. /*
  211. ** A positive leap second requires a special
  212. ** representation. This uses "... ??:59:60" et seq.
  213. */
  214. tmp->tm_sec = (int) (rem % SECSPERMIN) ;
  215. tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
  216. if (tmp->tm_wday < 0)
  217. tmp->tm_wday += DAYSPERWEEK;
  218. y = EPOCH_YEAR;
  219. #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
  220. while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
  221. INT64 newy;
  222. newy = y + days / DAYSPERNYEAR;
  223. if (days < 0)
  224. --newy;
  225. days -= (newy - y) * DAYSPERNYEAR +
  226. LEAPS_THRU_END_OF(newy - 1) -
  227. LEAPS_THRU_END_OF(y - 1);
  228. y = newy;
  229. }
  230. tmp->tm_year = (int)(y - TM_YEAR_BASE);
  231. tmp->tm_yday = (int) days;
  232. ip = mon_lengths[yleap];
  233. for (tmp->tm_mon = 0; days >= (INT64) ip[tmp->tm_mon]; ++(tmp->tm_mon))
  234. days = days - (INT64) ip[tmp->tm_mon];
  235. tmp->tm_mday = (int) (days + 1);
  236. tmp->tm_isdst = 0;
  237. }
  238. /*
  239. * Re-entrant version of gmtime.
  240. */
  241. struct tm * c_gmtime_r(const time_64t* timep, struct tm *tm)
  242. {
  243. c_timesub(timep, 0L, tm);
  244. return tm;
  245. }
  246. // Get the real-time system timer
  247. UINT TickRealtime()
  248. {
  249. #if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES) || defined(UNIX_MACOS)
  250. return Tick() + 1;
  251. #else
  252. return TickRealtimeManual() + 1;
  253. #endif
  254. }
  255. #ifndef OS_WIN32
  256. static UINT64 last_manual_tick = 0;
  257. static UINT64 manual_tick_add_value = 0;
  258. // For systems which not have clock_gettime (such as MacOS X)
  259. UINT TickRealtimeManual()
  260. {
  261. UINT64 ret;
  262. Lock(tick_manual_lock);
  263. {
  264. ret = TickGetRealtimeTickValue64();
  265. if (last_manual_tick != 0 && (last_manual_tick > ret))
  266. {
  267. manual_tick_add_value += (last_manual_tick - ret);
  268. }
  269. last_manual_tick = ret;
  270. }
  271. Unlock(tick_manual_lock);
  272. return (UINT)(ret + manual_tick_add_value);
  273. }
  274. // Returns a appropriate value from the current time
  275. UINT64 TickGetRealtimeTickValue64()
  276. {
  277. struct timeval tv;
  278. struct timezone tz;
  279. UINT64 ret;
  280. memset(&tv, 0, sizeof(tv));
  281. memset(&tz, 0, sizeof(tz));
  282. gettimeofday(&tv, &tz);
  283. if (sizeof(tv.tv_sec) != 4)
  284. {
  285. ret = (UINT64)tv.tv_sec * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
  286. }
  287. else
  288. {
  289. ret = (UINT64)((UINT64)((UINT32)tv.tv_sec)) * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
  290. }
  291. return ret;
  292. }
  293. #endif // OS_WIN32
  294. // Get the number of CPUs
  295. UINT GetNumberOfCpu()
  296. {
  297. UINT ret = 0;
  298. if (cached_number_of_cpus == 0)
  299. {
  300. UINT i = 0;
  301. #ifdef OS_WIN32
  302. i = Win32GetNumberOfCpuInner();
  303. #else // OS_WIN32
  304. i = UnixGetNumberOfCpuInner();
  305. #endif // OS_WIN32
  306. if (i == 0)
  307. {
  308. i = 8;
  309. }
  310. cached_number_of_cpus = i;
  311. }
  312. ret = cached_number_of_cpus;
  313. if (ret == 0)
  314. {
  315. ret = 1;
  316. }
  317. if (ret > 128)
  318. {
  319. ret = 128;
  320. }
  321. return ret;
  322. }
  323. // Creating a thread list
  324. LIST *NewThreadList()
  325. {
  326. LIST *o = NewList(NULL);
  327. return o;
  328. }
  329. // Remove the thread from the thread list
  330. void DelThreadFromThreadList(LIST *o, THREAD *t)
  331. {
  332. // Validate arguments
  333. if (o == NULL || t == NULL)
  334. {
  335. return;
  336. }
  337. LockList(o);
  338. {
  339. if (Delete(o, t))
  340. {
  341. ReleaseThread(t);
  342. }
  343. }
  344. UnlockList(o);
  345. }
  346. // Add the thread to the thread list
  347. void AddThreadToThreadList(LIST *o, THREAD *t)
  348. {
  349. // Validate arguments
  350. if (o == NULL || t == NULL)
  351. {
  352. return;
  353. }
  354. LockList(o);
  355. {
  356. if (IsInList(o, t) == false)
  357. {
  358. AddRef(t->ref);
  359. Add(o, t);
  360. }
  361. }
  362. UnlockList(o);
  363. }
  364. // Maintain thread list
  365. void MainteThreadList(LIST *o)
  366. {
  367. UINT i;
  368. LIST *delete_list = NULL;
  369. // Validate arguments
  370. if (o == NULL)
  371. {
  372. return;
  373. }
  374. LockList(o);
  375. {
  376. for (i = 0;i < LIST_NUM(o);i++)
  377. {
  378. THREAD *t = LIST_DATA(o, i);
  379. if (t->Stopped)
  380. {
  381. if (delete_list == NULL)
  382. {
  383. delete_list = NewListFast(NULL);
  384. }
  385. Add(delete_list, t);
  386. }
  387. }
  388. if (delete_list != NULL)
  389. {
  390. for (i = 0;i < LIST_NUM(delete_list);i++)
  391. {
  392. THREAD *t = LIST_DATA(delete_list, i);
  393. ReleaseThread(t);
  394. Delete(o, t);
  395. }
  396. ReleaseList(delete_list);
  397. }
  398. }
  399. UnlockList(o);
  400. }
  401. // Wait until all threads in the thread list will be stopped
  402. void WaitAllThreadsWillBeStopped(LIST *o)
  403. {
  404. // Validate arguments
  405. if (o == NULL)
  406. {
  407. return;
  408. }
  409. while (LIST_NUM(o) != 0)
  410. {
  411. SleepThread(100);
  412. }
  413. }
  414. // Stop all the threads in the thread list
  415. void StopThreadList(LIST *o)
  416. {
  417. UINT i;
  418. // Validate arguments
  419. if (o == NULL)
  420. {
  421. return;
  422. }
  423. LockList(o);
  424. {
  425. for (i = 0;i < LIST_NUM(o);i++)
  426. {
  427. THREAD *t = LIST_DATA(o, i);
  428. WaitThread(t, INFINITE);
  429. }
  430. }
  431. UnlockList(o);
  432. }
  433. // Release the thread list
  434. void FreeThreadList(LIST *o)
  435. {
  436. UINT i;
  437. // Validate arguments
  438. if (o == NULL)
  439. {
  440. return;
  441. }
  442. LockList(o);
  443. {
  444. for (i = 0;i < LIST_NUM(o);i++)
  445. {
  446. THREAD *t = LIST_DATA(o, i);
  447. WaitThread(t, INFINITE);
  448. ReleaseThread(t);
  449. }
  450. DeleteAll(o);
  451. }
  452. UnlockList(o);
  453. ReleaseList(o);
  454. }
  455. // Get the home directory
  456. void GetHomeDirW(wchar_t *path, UINT size)
  457. {
  458. // Validate arguments
  459. if (path == NULL)
  460. {
  461. return;
  462. }
  463. if (GetEnvW(L"HOME", path, size) == false)
  464. {
  465. wchar_t drive[MAX_SIZE];
  466. wchar_t hpath[MAX_SIZE];
  467. if (GetEnvW(L"HOMEDRIVE", drive, sizeof(drive)) &&
  468. GetEnvW(L"HOMEPATH", hpath, sizeof(hpath)))
  469. {
  470. UniFormat(path, size, L"%s%s", drive, hpath);
  471. }
  472. else
  473. {
  474. #ifdef OS_WIN32
  475. Win32GetCurrentDirW(path, size);
  476. #else // OS_WIN32
  477. UnixGetCurrentDirW(path, size);
  478. #endif // OS_WIN32
  479. }
  480. }
  481. }
  482. void GetHomeDir(char *path, UINT size)
  483. {
  484. // Validate arguments
  485. if (path == NULL)
  486. {
  487. return;
  488. }
  489. if (GetEnv("HOME", path, size) == false)
  490. {
  491. char drive[MAX_SIZE];
  492. char hpath[MAX_SIZE];
  493. if (GetEnv("HOMEDRIVE", drive, sizeof(drive)) &&
  494. GetEnv("HOMEPATH", hpath, sizeof(hpath)))
  495. {
  496. Format(path, size, "%s%s", drive, hpath);
  497. }
  498. else
  499. {
  500. #ifdef OS_WIN32
  501. Win32GetCurrentDir(path, size);
  502. #else // OS_WIN32
  503. UnixGetCurrentDir(path, size);
  504. #endif // OS_WIN32
  505. }
  506. }
  507. }
  508. // Get the environment variable string
  509. bool GetEnv(char *name, char *data, UINT size)
  510. {
  511. char *ret;
  512. // Validate arguments
  513. if (name == NULL || data == NULL)
  514. {
  515. return false;
  516. }
  517. StrCpy(data, size, "");
  518. ret = getenv(name);
  519. if (ret == NULL)
  520. {
  521. return false;
  522. }
  523. StrCpy(data, size, ret);
  524. return true;
  525. }
  526. bool GetEnvW(wchar_t *name, wchar_t *data, UINT size)
  527. {
  528. #ifdef OS_WIN32
  529. return GetEnvW_ForWin32(name, data, size);
  530. #else // OS_WIN32
  531. return GetEnvW_ForUnix(name, data, size);
  532. #endif // OS_WIN32
  533. }
  534. #ifdef OS_WIN32
  535. bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size)
  536. {
  537. wchar_t *ret;
  538. // Validate arguments
  539. if (name == NULL || data == NULL)
  540. {
  541. return false;
  542. }
  543. if (IsNt() == false)
  544. {
  545. bool ret;
  546. char *name_a = CopyUniToStr(name);
  547. char data_a[MAX_SIZE];
  548. ret = GetEnv(name_a, data_a, sizeof(data_a));
  549. if (ret)
  550. {
  551. StrToUni(data, size, data_a);
  552. }
  553. Free(name_a);
  554. return ret;
  555. }
  556. UniStrCpy(data, size, L"");
  557. ret = _wgetenv(name);
  558. if (ret == NULL)
  559. {
  560. return false;
  561. }
  562. UniStrCpy(data, size, ret);
  563. return true;
  564. }
  565. #endif // OS_WIN32
  566. #ifdef OS_UNIX
  567. bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size)
  568. {
  569. char *name_a;
  570. bool ret;
  571. char data_a[MAX_SIZE];
  572. // Validate arguments
  573. if (name == NULL || data == NULL)
  574. {
  575. return false;
  576. }
  577. name_a = CopyUniToUtf(name);
  578. ret = GetEnv(name_a, data_a, sizeof(data_a));
  579. if (ret)
  580. {
  581. UtfToUni(data, size, data_a);
  582. }
  583. Free(name_a);
  584. return ret;
  585. }
  586. #endif // OS_UNIX
  587. // Get the memory information
  588. void GetMemInfo(MEMINFO *info)
  589. {
  590. OSGetMemInfo(info);
  591. }
  592. // Start the single-instance
  593. INSTANCE *NewSingleInstance(char *instance_name)
  594. {
  595. return NewSingleInstanceEx(instance_name, false);
  596. }
  597. INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local)
  598. {
  599. char name[MAX_SIZE];
  600. INSTANCE *ret;
  601. void *data;
  602. if (instance_name != NULL)
  603. {
  604. if (user_local == false)
  605. {
  606. HashInstanceName(name, sizeof(name), instance_name);
  607. }
  608. else
  609. {
  610. HashInstanceNameLocal(name, sizeof(name), instance_name);
  611. }
  612. data = OSNewSingleInstance(name);
  613. }
  614. else
  615. {
  616. data = OSNewSingleInstance(NULL);
  617. }
  618. if (data == NULL)
  619. {
  620. return NULL;
  621. }
  622. ret = ZeroMalloc(sizeof(INSTANCE));
  623. if (instance_name != NULL)
  624. {
  625. ret->Name = CopyStr(instance_name);
  626. }
  627. ret->pData = data;
  628. return ret;
  629. }
  630. // Release of single instance
  631. void FreeSingleInstance(INSTANCE *inst)
  632. {
  633. // Validate arguments
  634. if (inst == NULL)
  635. {
  636. return;
  637. }
  638. OSFreeSingleInstance(inst->pData);
  639. if (inst->Name != NULL)
  640. {
  641. Free(inst->Name);
  642. }
  643. Free(inst);
  644. }
  645. // Hashing the instance name
  646. void HashInstanceName(char *name, UINT size, char *instance_name)
  647. {
  648. char tmp[MAX_SIZE];
  649. UCHAR hash[SHA1_SIZE];
  650. char key[11];
  651. // Validate arguments
  652. if (name == NULL || instance_name == NULL)
  653. {
  654. return;
  655. }
  656. StrCpy(tmp, sizeof(tmp), instance_name);
  657. Trim(tmp);
  658. StrUpper(tmp);
  659. Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
  660. BinToStr(key, sizeof(key), hash, 5);
  661. key[10] = 0;
  662. Format(name, size, "VPN-%s", key);
  663. if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
  664. {
  665. if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
  666. GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
  667. {
  668. StrCpy(tmp, sizeof(tmp), name);
  669. Format(name, size, "Global\\%s", tmp);
  670. }
  671. }
  672. }
  673. void HashInstanceNameLocal(char *name, UINT size, char *instance_name)
  674. {
  675. char tmp[MAX_SIZE];
  676. UCHAR hash[SHA1_SIZE];
  677. char key[11];
  678. // Validate arguments
  679. if (name == NULL || instance_name == NULL)
  680. {
  681. return;
  682. }
  683. StrCpy(tmp, sizeof(tmp), instance_name);
  684. Trim(tmp);
  685. StrUpper(tmp);
  686. Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
  687. BinToStr(key, sizeof(key), hash, 5);
  688. key[10] = 0;
  689. Format(name, size, "VPN-%s", key);
  690. if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
  691. {
  692. if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
  693. GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
  694. {
  695. StrCpy(tmp, sizeof(tmp), name);
  696. Format(name, size, "Local\\%s", tmp);
  697. }
  698. }
  699. }
  700. // Run the process
  701. bool Run(char *filename, char *arg, bool hide, bool wait)
  702. {
  703. // Validate arguments
  704. if (filename == NULL)
  705. {
  706. return false;
  707. }
  708. return OSRun(filename, arg, hide, wait);
  709. }
  710. bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
  711. {
  712. // Validate arguments
  713. if (filename == NULL)
  714. {
  715. return false;
  716. }
  717. return OSRunW(filename, arg, hide, wait);
  718. }
  719. // Date and time related functions
  720. void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64)
  721. {
  722. char tmp[MAX_SIZE];
  723. if (str == NULL)
  724. {
  725. return;
  726. }
  727. GetDateTimeStr64(tmp, sizeof(tmp), sec64);
  728. StrToUni(str, size, tmp);
  729. }
  730. void GetDateTimeStr64(char *str, UINT size, UINT64 sec64)
  731. {
  732. SYSTEMTIME st;
  733. UINT64ToSystem(&st, sec64);
  734. GetDateTimeStr(str, size, &st);
  735. }
  736. void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64)
  737. {
  738. SYSTEMTIME st;
  739. UINT64ToSystem(&st, sec64);
  740. GetDateTimeStrMilli(str, size, &st);
  741. }
  742. void GetDateTimeStrMilli64ForFileName(char *str, UINT size, UINT64 sec64)
  743. {
  744. SYSTEMTIME st;
  745. UINT64ToSystem(&st, sec64);
  746. GetDateTimeStrMilliForFileName(str, size, &st);
  747. }
  748. void GetDateTimeStrMilliForFileName(char *str, UINT size, SYSTEMTIME *tm)
  749. {
  750. Format(str, size, "%04u%02u%02u_%02u%02u%02u",
  751. tm->wYear, tm->wMonth, tm->wDay, tm->wHour, tm->wMinute, tm->wSecond);
  752. }
  753. void GetDateStr64(char *str, UINT size, UINT64 sec64)
  754. {
  755. SYSTEMTIME st;
  756. if (sec64 == 0)
  757. {
  758. StrCpy(str, size, "(Unknown)");
  759. return;
  760. }
  761. UINT64ToSystem(&st, sec64);
  762. GetDateStr(str, size, &st);
  763. }
  764. void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
  765. {
  766. SYSTEMTIME st;
  767. if (locale == NULL)
  768. {
  769. locale = &current_locale;
  770. }
  771. if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
  772. {
  773. UniStrCpy(str, size, locale->Unknown);
  774. return;
  775. }
  776. UINT64ToSystem(&st, sec64);
  777. GetDateTimeStrEx(str, size, &st, locale);
  778. }
  779. void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
  780. {
  781. SYSTEMTIME st;
  782. if (locale == NULL)
  783. {
  784. locale = &current_locale;
  785. }
  786. if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
  787. {
  788. UniStrCpy(str, size, locale->Unknown);
  789. return;
  790. }
  791. UINT64ToSystem(&st, sec64);
  792. GetTimeStrEx(str, size, &st, locale);
  793. }
  794. void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
  795. {
  796. SYSTEMTIME st;
  797. if (locale == NULL)
  798. {
  799. locale = &current_locale;
  800. }
  801. if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
  802. {
  803. UniStrCpy(str, size, locale->Unknown);
  804. return;
  805. }
  806. UINT64ToSystem(&st, sec64);
  807. GetDateStrEx(str, size, &st, locale);
  808. }
  809. void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64)
  810. {
  811. SYSTEMTIME st;
  812. if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
  813. {
  814. StrCpy(str, size, "(Unknown)");
  815. return;
  816. }
  817. UINT64ToSystem(&st, sec64);
  818. GetTimeStrMilli(str, size, &st);
  819. }
  820. void GetTimeStr64(char *str, UINT size, UINT64 sec64)
  821. {
  822. SYSTEMTIME st;
  823. if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
  824. {
  825. StrCpy(str, size, "(Unknown)");
  826. return;
  827. }
  828. UINT64ToSystem(&st, sec64);
  829. GetTimeStr(str, size, &st);
  830. }
  831. // Convert to a time to be used safely in the current POSIX implementation
  832. UINT64 SafeTime64(UINT64 sec64)
  833. {
  834. return MAKESURE(sec64, 0, 4102243323123ULL);
  835. }
  836. // Thread pool
  837. static SK *thread_pool = NULL;
  838. static COUNTER *thread_count = NULL;
  839. // Initialization of thread pool
  840. void InitThreading()
  841. {
  842. thread_pool = NewSk();
  843. thread_count = NewCounter();
  844. }
  845. // Release of thread pool
  846. void FreeThreading()
  847. {
  848. while (true)
  849. {
  850. if (Count(thread_count) == 0)
  851. {
  852. break;
  853. }
  854. SleepThread(25);
  855. }
  856. while (true)
  857. {
  858. THREAD_POOL_DATA *pd;
  859. THREAD *t = Pop(thread_pool);
  860. if (t == NULL)
  861. {
  862. break;
  863. }
  864. pd = (THREAD_POOL_DATA *)t->param;
  865. pd->ThreadProc = NULL;
  866. Set(pd->Event);
  867. WaitThreadInternal(t);
  868. pd = (THREAD_POOL_DATA *)t->param;
  869. ReleaseEvent(pd->Event);
  870. ReleaseEvent(pd->InitFinishEvent);
  871. ReleaseThreadInternal(t);
  872. Free(pd);
  873. }
  874. ReleaseSk(thread_pool);
  875. DeleteCounter(thread_count);
  876. thread_count = NULL;
  877. }
  878. // Thread pool procedure
  879. void ThreadPoolProc(THREAD *t, void *param)
  880. {
  881. THREAD_POOL_DATA *pd;
  882. // Validate arguments
  883. if (t == NULL)
  884. {
  885. return;
  886. }
  887. pd = (THREAD_POOL_DATA *)param;
  888. NoticeThreadInitInternal(t);
  889. while (true)
  890. {
  891. THREAD *thread;
  892. UINT i, num;
  893. EVENT **ee;
  894. // Wait for the next job
  895. Wait(pd->Event, INFINITE);
  896. if (pd->ThreadProc == NULL)
  897. {
  898. // Stop the pool thread
  899. break;
  900. }
  901. thread = pd->Thread;
  902. thread->ThreadId = ThreadId();
  903. // Initialization is completed
  904. Set(pd->InitFinishEvent);
  905. // Set the thread name
  906. if (thread->Name != NULL)
  907. {
  908. SetThreadName(thread->ThreadId, thread->Name, thread->param);
  909. }
  910. else
  911. {
  912. SetThreadName(thread->ThreadId, "Unknown", 0);
  913. }
  914. // Run the thread procedure
  915. pd->ThreadProc(pd->Thread, thread->param);
  916. // Set the thread name
  917. SetThreadName(thread->ThreadId, NULL, 0);
  918. pd->Thread->Stopped = true;
  919. thread->PoolHalting = true;
  920. // Set the waiting event list
  921. LockList(thread->PoolWaitList);
  922. {
  923. num = LIST_NUM(thread->PoolWaitList);
  924. ee = ToArray(thread->PoolWaitList);
  925. DeleteAll(thread->PoolWaitList);
  926. }
  927. UnlockList(thread->PoolWaitList);
  928. for (i = 0;i < num;i++)
  929. {
  930. EVENT *e = ee[i];
  931. Set(e);
  932. ReleaseEvent(e);
  933. }
  934. Free(ee);
  935. while (true)
  936. {
  937. if (Count(thread->ref->c) <= 1)
  938. {
  939. break;
  940. }
  941. Wait(thread->release_event, 256);
  942. }
  943. ReleaseThread(thread);
  944. #ifdef OS_WIN32
  945. // For Win32: Recover the priority of the thread
  946. MsRestoreThreadPriority();
  947. #endif // OS_WIN32
  948. // Register the thread itself to the thread pool
  949. LockSk(thread_pool);
  950. {
  951. Push(thread_pool, t);
  952. }
  953. UnlockSk(thread_pool);
  954. Dec(thread_count);
  955. }
  956. }
  957. // Set the thread name
  958. void SetThreadName(UINT thread_id, char *name, void *param)
  959. {
  960. #ifdef OS_WIN32
  961. if (IsDebug())
  962. {
  963. char tmp[MAX_SIZE];
  964. if (name == NULL)
  965. {
  966. strcpy(tmp, "idle");
  967. }
  968. else
  969. {
  970. sprintf(tmp, "%s (0x%x)", name, (UINT)param);
  971. }
  972. Win32SetThreadName(thread_id, tmp);
  973. }
  974. #else // OS_WIN32
  975. #ifdef _DEBUG
  976. #ifdef PR_SET_NAME
  977. char tmp[MAX_SIZE];
  978. if (name == NULL)
  979. {
  980. strcpy(tmp, "idle");
  981. }
  982. else
  983. {
  984. sprintf(tmp, "%s (%p)", name, param);
  985. }
  986. tmp[15] = 0;
  987. prctl(PR_SET_NAME, (unsigned long)tmp, 0, 0, 0);
  988. #endif // PR_SET_NAME
  989. #endif // _DEBUG
  990. #endif // OS_WIN32
  991. }
  992. // Do Nothing
  993. UINT DoNothing()
  994. {
  995. return g_zero;
  996. }
  997. // Thread creation (pool)
  998. THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
  999. {
  1000. THREAD *host = NULL;
  1001. THREAD_POOL_DATA *pd = NULL;
  1002. THREAD *ret;
  1003. bool new_thread = false;
  1004. // Validate arguments
  1005. if (thread_proc == NULL)
  1006. {
  1007. return NULL;
  1008. }
  1009. if (IsTrackingEnabled() == false)
  1010. {
  1011. DoNothing();
  1012. }
  1013. Inc(thread_count);
  1014. LockSk(thread_pool);
  1015. {
  1016. // Examine whether there is a thread that is currently vacant in the pool
  1017. host = Pop(thread_pool);
  1018. }
  1019. UnlockSk(thread_pool);
  1020. if (host == NULL)
  1021. {
  1022. // Create a new thread because a vacant thread is not found
  1023. pd = ZeroMalloc(sizeof(THREAD_POOL_DATA));
  1024. pd->Event = NewEvent();
  1025. pd->InitFinishEvent = NewEvent();
  1026. host = NewThreadInternal(ThreadPoolProc, pd);
  1027. WaitThreadInitInternal(host);
  1028. new_thread = true;
  1029. }
  1030. else
  1031. {
  1032. pd = (THREAD_POOL_DATA *)host->param;
  1033. }
  1034. // Creating a thread pool
  1035. ret = ZeroMalloc(sizeof(THREAD));
  1036. ret->ref = NewRef();
  1037. ret->thread_proc = thread_proc;
  1038. ret->param = param;
  1039. ret->pData = NULL;
  1040. ret->init_finished_event = NewEvent();
  1041. ret->PoolThread = true;
  1042. ret->PoolWaitList = NewList(NULL);
  1043. ret->PoolHostThread = host;
  1044. ret->release_event = NewEvent();
  1045. if (IsEmptyStr(name) == false)
  1046. {
  1047. ret->Name = CopyStr(name);
  1048. }
  1049. // Run
  1050. pd->ThreadProc = thread_proc;
  1051. pd->Thread = ret;
  1052. AddRef(ret->ref);
  1053. Set(pd->Event);
  1054. Wait(pd->InitFinishEvent, INFINITE);
  1055. current_num_thread++;
  1056. // Debug("current_num_thread = %u\n", current_num_thread);
  1057. return ret;
  1058. }
  1059. // Clean up of thread (pool)
  1060. void CleanupThread(THREAD *t)
  1061. {
  1062. // Validate arguments
  1063. if (t == NULL)
  1064. {
  1065. return;
  1066. }
  1067. ReleaseEvent(t->init_finished_event);
  1068. ReleaseEvent(t->release_event);
  1069. ReleaseList(t->PoolWaitList);
  1070. if (t->Name != NULL)
  1071. {
  1072. Free(t->Name);
  1073. }
  1074. Free(t);
  1075. current_num_thread--;
  1076. //Debug("current_num_thread = %u\n", current_num_thread);
  1077. }
  1078. // Release thread (pool)
  1079. void ReleaseThread(THREAD *t)
  1080. {
  1081. UINT ret;
  1082. EVENT *e;
  1083. // Validate arguments
  1084. if (t == NULL)
  1085. {
  1086. return;
  1087. }
  1088. e = t->release_event;
  1089. if (e != NULL)
  1090. {
  1091. AddRef(e->ref);
  1092. }
  1093. ret = Release(t->ref);
  1094. Set(e);
  1095. ReleaseEvent(e);
  1096. if (ret == 0)
  1097. {
  1098. CleanupThread(t);
  1099. }
  1100. }
  1101. // Notify the completion of the thread initialization (pool)
  1102. void NoticeThreadInit(THREAD *t)
  1103. {
  1104. // Validate arguments
  1105. if (t == NULL)
  1106. {
  1107. return;
  1108. }
  1109. // Notification
  1110. Set(t->init_finished_event);
  1111. }
  1112. // Wait the completion of the thread initialization (pool)
  1113. void WaitThreadInit(THREAD *t)
  1114. {
  1115. // Validate arguments
  1116. if (t == NULL)
  1117. {
  1118. return;
  1119. }
  1120. // KS
  1121. KS_INC(KS_WAITFORTHREAD_COUNT);
  1122. // Wait
  1123. Wait(t->init_finished_event, INFINITE);
  1124. }
  1125. // Wait for the termination of the thread (pool)
  1126. bool WaitThread(THREAD *t, UINT timeout)
  1127. {
  1128. bool ret = false;
  1129. EVENT *e = NULL;
  1130. // Validate arguments
  1131. if (t == NULL)
  1132. {
  1133. return false;
  1134. }
  1135. LockList(t->PoolWaitList);
  1136. {
  1137. if (t->PoolHalting)
  1138. {
  1139. // Has already been stopped
  1140. ret = true;
  1141. }
  1142. else
  1143. {
  1144. // Register the completion notifying event to the list
  1145. e = NewEvent();
  1146. AddRef(e->ref);
  1147. Insert(t->PoolWaitList, e);
  1148. }
  1149. }
  1150. UnlockList(t->PoolWaitList);
  1151. if (e != NULL)
  1152. {
  1153. // Wait Event
  1154. ret = Wait(e, timeout);
  1155. LockList(t->PoolWaitList);
  1156. {
  1157. if (Delete(t->PoolWaitList, e))
  1158. {
  1159. ReleaseEvent(e);
  1160. }
  1161. }
  1162. UnlockList(t->PoolWaitList);
  1163. ReleaseEvent(e);
  1164. }
  1165. return ret;
  1166. }
  1167. // Get Thread ID
  1168. UINT ThreadId()
  1169. {
  1170. return OSThreadId();
  1171. }
  1172. // Creating a thread
  1173. THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param)
  1174. {
  1175. THREAD *t;
  1176. UINT retry = 0;
  1177. // Validate arguments
  1178. if (thread_proc == NULL)
  1179. {
  1180. return NULL;
  1181. }
  1182. // Initialize Thread object
  1183. t = ZeroMalloc(sizeof(THREAD));
  1184. t->init_finished_event = NewEvent();
  1185. t->param = param;
  1186. t->ref = NewRef();
  1187. t->thread_proc = thread_proc;
  1188. // Wait until the OS to initialize the thread
  1189. while (true)
  1190. {
  1191. if ((retry++) > 60)
  1192. {
  1193. printf("\n\n*** error: new thread create failed.\n\n");
  1194. AbortExit();
  1195. }
  1196. if (OSInitThread(t))
  1197. {
  1198. break;
  1199. }
  1200. SleepThread(500);
  1201. }
  1202. // KS
  1203. KS_INC(KS_NEWTHREAD_COUNT);
  1204. return t;
  1205. }
  1206. // Release of thread
  1207. void ReleaseThreadInternal(THREAD *t)
  1208. {
  1209. // Validate arguments
  1210. if (t == NULL)
  1211. {
  1212. return;
  1213. }
  1214. if (Release(t->ref) == 0)
  1215. {
  1216. CleanupThreadInternal(t);
  1217. }
  1218. }
  1219. // Clean up of the thread
  1220. void CleanupThreadInternal(THREAD *t)
  1221. {
  1222. // Validate arguments
  1223. if (t == NULL)
  1224. {
  1225. return;
  1226. }
  1227. // Release of the thread
  1228. OSFreeThread(t);
  1229. // Release the event
  1230. ReleaseEvent(t->init_finished_event);
  1231. // Memory release
  1232. Free(t);
  1233. // KS
  1234. KS_INC(KS_FREETHREAD_COUNT);
  1235. }
  1236. // Wait for the termination of the thread
  1237. bool WaitThreadInternal(THREAD *t)
  1238. {
  1239. // Validate arguments
  1240. if (t == NULL)
  1241. {
  1242. return false;
  1243. }
  1244. return OSWaitThread(t);
  1245. }
  1246. // Notify that the thread initialization is complete
  1247. void NoticeThreadInitInternal(THREAD *t)
  1248. {
  1249. // Validate arguments
  1250. if (t == NULL)
  1251. {
  1252. return;
  1253. }
  1254. // Notify
  1255. Set(t->init_finished_event);
  1256. }
  1257. // Wait for completion of thread initialization
  1258. void WaitThreadInitInternal(THREAD *t)
  1259. {
  1260. // Validate arguments
  1261. if (t == NULL)
  1262. {
  1263. return;
  1264. }
  1265. // KS
  1266. KS_INC(KS_WAITFORTHREAD_COUNT);
  1267. // Wait
  1268. Wait(t->init_finished_event, INFINITE);
  1269. }
  1270. // Get the date and time string by using the locale information
  1271. void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
  1272. {
  1273. wchar_t tmp1[MAX_SIZE];
  1274. wchar_t tmp2[MAX_SIZE];
  1275. // Validate arguments
  1276. if (str == NULL || st == NULL)
  1277. {
  1278. return;
  1279. }
  1280. GetDateStrEx(tmp1, sizeof(tmp1), st, locale);
  1281. GetTimeStrEx(tmp2, sizeof(tmp2), st, locale);
  1282. UniFormat(str, size, L"%s %s", tmp1, tmp2);
  1283. }
  1284. // Get the time string by using the locale information
  1285. void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
  1286. {
  1287. wchar_t *tag = L"%02u%s%02u%s%02u%s";
  1288. // Validate arguments
  1289. if (str == NULL || st == NULL)
  1290. {
  1291. return;
  1292. }
  1293. if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
  1294. {
  1295. tag = L"%2u%s%2u%s%2u%s";
  1296. }
  1297. locale = (locale != NULL ? locale : &current_locale);
  1298. UniFormat(str, size,
  1299. tag,
  1300. st->wHour, locale->HourStr,
  1301. st->wMinute, locale->MinuteStr,
  1302. st->wSecond, locale->SecondStr);
  1303. }
  1304. // Get a date string by using the locale information
  1305. void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
  1306. {
  1307. wchar_t *tag = L"%04u%s%02u%s%02u%s (%s)";
  1308. // Validate arguments
  1309. if (str == NULL || st == NULL)
  1310. {
  1311. return;
  1312. }
  1313. if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
  1314. {
  1315. tag = L"%4u%s%2u%s%2u%s(%s)";
  1316. }
  1317. locale = (locale != NULL ? locale : &current_locale);
  1318. UniFormat(str, size,
  1319. tag,
  1320. st->wYear, locale->YearStr,
  1321. st->wMonth, locale->MonthStr,
  1322. st->wDay, locale->DayStr,
  1323. locale->DayOfWeek[st->wDayOfWeek]);
  1324. }
  1325. // Get the time string to milliseconds (for example, 12:34:56.789)
  1326. void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
  1327. {
  1328. // Validate arguments
  1329. if (st == NULL || str == NULL)
  1330. {
  1331. return;
  1332. }
  1333. Format(str, size, "%02u:%02u:%02u.%03u",
  1334. st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
  1335. }
  1336. // Get the time string (for example, 12:34:56)
  1337. void GetTimeStr(char *str, UINT size, SYSTEMTIME *st)
  1338. {
  1339. // Validate arguments
  1340. if (str == NULL || st == NULL)
  1341. {
  1342. return;
  1343. }
  1344. Format(str, size, "%02u:%02u:%02u",
  1345. st->wHour, st->wMinute, st->wSecond);
  1346. }
  1347. // Get the date string (example: 2004/07/23)
  1348. void GetDateStr(char *str, UINT size, SYSTEMTIME *st)
  1349. {
  1350. // Validate arguments
  1351. if (str == NULL || st == NULL)
  1352. {
  1353. return;
  1354. }
  1355. Format(str, size, "%04u-%02u-%02u",
  1356. st->wYear, st->wMonth, st->wDay);
  1357. }
  1358. // Get the date and time string (example: 2004/07/23 12:34:56)
  1359. void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st)
  1360. {
  1361. // Validate arguments
  1362. if (str == NULL || st == NULL)
  1363. {
  1364. return;
  1365. }
  1366. Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u",
  1367. st->wYear, st->wMonth, st->wDay,
  1368. st->wHour, st->wMinute, st->wSecond);
  1369. }
  1370. // Get the date and time string in milliseconds (example: 2004/07/23 12:34:56.789)
  1371. void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
  1372. {
  1373. // Validate arguments
  1374. if (str == NULL || st == NULL)
  1375. {
  1376. return;
  1377. }
  1378. Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
  1379. st->wYear, st->wMonth, st->wDay,
  1380. st->wHour, st->wMinute, st->wSecond,
  1381. st->wMilliseconds);
  1382. }
  1383. // Convert string RFC3339 format (example: 2017-09-27T18:25:55.434-9:00) to UINT64
  1384. UINT64 DateTimeStrRFC3339ToSystemTime64(char *str)
  1385. {
  1386. SYSTEMTIME st;
  1387. if (DateTimeStrRFC3339ToSystemTime(&st, str))
  1388. {
  1389. return SystemToUINT64(&st);
  1390. }
  1391. else
  1392. {
  1393. return 0;
  1394. }
  1395. }
  1396. // Convert string RFC3339 format (example: 2017-09-27T18:25:55.434-9:00) to SYSTEMTIME
  1397. bool DateTimeStrRFC3339ToSystemTime(SYSTEMTIME *st, char *str)
  1398. {
  1399. bool ok = false;
  1400. UINT index_plus;
  1401. char tmp[MAX_PATH];
  1402. Zero(st, sizeof(SYSTEMTIME));
  1403. if (st == NULL || str == NULL)
  1404. {
  1405. return false;
  1406. }
  1407. StrCpy(tmp, sizeof(tmp), str);
  1408. index_plus = SearchStrEx(tmp, "+", 0, false);
  1409. if (index_plus != INFINITE)
  1410. {
  1411. tmp[index_plus] = 0;
  1412. }
  1413. if (StrLen(tmp) >= 19)
  1414. {
  1415. if (tmp[4] == '-' && tmp[7] == '-' && tmp[10] == 'T' && tmp[13] == ':' &&
  1416. tmp[16] == ':')
  1417. {
  1418. char str_year[16], str_month[16], str_day[16], str_hour[16], str_minute[16],
  1419. str_second[16], str_msec[16];
  1420. StrCpy(str_year, sizeof(str_year), tmp + 0);
  1421. str_year[4] = 0;
  1422. StrCpy(str_month, sizeof(str_month), tmp + 5);
  1423. str_month[2] = 0;
  1424. StrCpy(str_day, sizeof(str_day), tmp + 8);
  1425. str_day[2] = 0;
  1426. StrCpy(str_hour, sizeof(str_hour), tmp + 11);
  1427. str_hour[2] = 0;
  1428. StrCpy(str_minute, sizeof(str_minute), tmp + 14);
  1429. str_minute[2] = 0;
  1430. StrCpy(str_second, sizeof(str_second), tmp + 17);
  1431. str_second[2] = 0;
  1432. str_msec[0] = 0;
  1433. if (StrLen(tmp) >= 21 && tmp[19] == '.')
  1434. {
  1435. StrCpy(str_msec, sizeof(str_msec), tmp + 20);
  1436. str_msec[StrLen(tmp) - 21] = 0;
  1437. while (StrLen(str_msec) < 3)
  1438. {
  1439. StrCat(str_msec, sizeof(str_msec), "0");
  1440. }
  1441. str_msec[3] = 0;
  1442. }
  1443. st->wYear = ToInt(str_year);
  1444. st->wMonth = ToInt(str_month);
  1445. st->wDay = ToInt(str_day);
  1446. st->wHour = ToInt(str_hour);
  1447. st->wMinute = ToInt(str_minute);
  1448. st->wSecond = ToInt(str_second);
  1449. st->wMilliseconds = ToInt(str_msec);
  1450. NormalizeSystem(st);
  1451. ok = true;
  1452. }
  1453. }
  1454. return ok;
  1455. }
  1456. // Get the date and time string in RFC3339 format (example: 2017-09-27T18:25:55.434-9:00)
  1457. void GetDateTimeStrRFC3339(char *str, UINT size, SYSTEMTIME *st, int timezone_min){
  1458. // Validate arguments
  1459. if (str == NULL || st == NULL)
  1460. {
  1461. ClearStr(str, size);
  1462. return;
  1463. }
  1464. if(timezone_min == 0){
  1465. Format(str, size, "%04u-%02u-%02uT%02u:%02u:%02u.%03uZ",
  1466. st->wYear, st->wMonth, st->wDay,
  1467. st->wHour, st->wMinute, st->wSecond,
  1468. st->wMilliseconds);
  1469. }else{
  1470. Format(str, size, "%04u-%02u-%02uT%02u:%02u:%02u.%03u%+02d:%02d",
  1471. st->wYear, st->wMonth, st->wDay,
  1472. st->wHour, st->wMinute, st->wSecond,
  1473. st->wMilliseconds, timezone_min/60, timezone_min%60);
  1474. }
  1475. }
  1476. // Get the time string
  1477. void GetSpanStr(char *str, UINT size, UINT64 sec64)
  1478. {
  1479. char tmp[MAX_SIZE];
  1480. // Validate arguments
  1481. if (str == NULL)
  1482. {
  1483. return;
  1484. }
  1485. StrCpy(tmp, sizeof(tmp), "");
  1486. if (sec64 >= (UINT64)(1000 * 3600 * 24))
  1487. {
  1488. Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
  1489. }
  1490. Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u", tmp,
  1491. (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
  1492. (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
  1493. (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000);
  1494. Trim(tmp);
  1495. StrCpy(str, size, tmp);
  1496. }
  1497. // Get the time string (in milliseconds)
  1498. void GetSpanStrMilli(char *str, UINT size, UINT64 sec64)
  1499. {
  1500. char tmp[MAX_SIZE];
  1501. // Validate arguments
  1502. if (str == NULL)
  1503. {
  1504. return;
  1505. }
  1506. StrCpy(tmp, sizeof(tmp), "");
  1507. if (sec64 >= (UINT64)(1000 * 3600 * 24))
  1508. {
  1509. Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
  1510. }
  1511. Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u.%03u", tmp,
  1512. (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
  1513. (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
  1514. (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
  1515. (UINT)(sec64 % (UINT64)(1000)));
  1516. Trim(tmp);
  1517. StrCpy(str, size, tmp);
  1518. }
  1519. // Get the time string (extended)
  1520. void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
  1521. {
  1522. wchar_t tmp[MAX_SIZE];
  1523. // Validate arguments
  1524. if (str == NULL)
  1525. {
  1526. return;
  1527. }
  1528. locale = (locale != NULL ? locale : &current_locale);
  1529. UniStrCpy(tmp, sizeof(tmp), L"");
  1530. if (sec64 >= (UINT64)(1000 * 3600 * 24))
  1531. {
  1532. UniFormat(tmp, sizeof(tmp), L"%u%s ", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)),
  1533. locale->SpanDay);
  1534. }
  1535. UniFormat(tmp, sizeof(tmp), L"%s%u%s %02u%s %02u%s", tmp,
  1536. (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
  1537. locale->SpanHour,
  1538. (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
  1539. locale->SpanMinute,
  1540. (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
  1541. locale->SpanSecond);
  1542. UniTrim(tmp);
  1543. UniStrCpy(str, size, tmp);
  1544. }
  1545. // Get the current locale information
  1546. void GetCurrentLocale(LOCALE *locale)
  1547. {
  1548. // Validate arguments
  1549. if (locale == NULL)
  1550. {
  1551. return;
  1552. }
  1553. Copy(locale, &current_locale, sizeof(LOCALE));
  1554. }
  1555. // Set the locale information
  1556. void SetLocale(wchar_t *str)
  1557. {
  1558. wchar_t *set_locale_str;
  1559. LOCALE tmp;
  1560. if (str != NULL)
  1561. {
  1562. set_locale_str = str;
  1563. }
  1564. else
  1565. {
  1566. set_locale_str = default_locale_str;
  1567. }
  1568. if (LoadLocale(&tmp, set_locale_str) == false)
  1569. {
  1570. if (LoadLocale(&tmp, default_locale_str) == false)
  1571. {
  1572. return;
  1573. }
  1574. }
  1575. Copy(&current_locale, &tmp, sizeof(LOCALE));
  1576. }
  1577. #define COPY_LOCALE_STR(dest, size, src) UniStrCpy(dest, size, UniStrCmp(src, L"$") == 0 ? L"" : src)
  1578. // Read the locale information
  1579. bool LoadLocale(LOCALE *locale, wchar_t *str)
  1580. {
  1581. UNI_TOKEN_LIST *tokens;
  1582. UINT i;
  1583. // Validate arguments
  1584. if (locale == NULL || str == NULL)
  1585. {
  1586. return false;
  1587. }
  1588. // Analysis of the token
  1589. tokens = UniParseToken(str, L" ");
  1590. if (tokens->NumTokens != 18)
  1591. {
  1592. UniFreeToken(tokens);
  1593. return false;
  1594. }
  1595. // Set to the structure
  1596. Zero(locale, sizeof(LOCALE));
  1597. COPY_LOCALE_STR(locale->YearStr, sizeof(locale->YearStr), tokens->Token[0]);
  1598. COPY_LOCALE_STR(locale->MonthStr, sizeof(locale->MonthStr), tokens->Token[1]);
  1599. COPY_LOCALE_STR(locale->DayStr, sizeof(locale->DayStr), tokens->Token[2]);
  1600. COPY_LOCALE_STR(locale->HourStr, sizeof(locale->HourStr), tokens->Token[3]);
  1601. COPY_LOCALE_STR(locale->MinuteStr, sizeof(locale->MinuteStr), tokens->Token[4]);
  1602. COPY_LOCALE_STR(locale->SecondStr, sizeof(locale->SecondStr), tokens->Token[5]);
  1603. for (i = 0;i < 7;i++)
  1604. {
  1605. COPY_LOCALE_STR(locale->DayOfWeek[i], sizeof(locale->DayOfWeek[i]),
  1606. tokens->Token[6 + i]);
  1607. }
  1608. COPY_LOCALE_STR(locale->SpanDay, sizeof(locale->SpanDay), tokens->Token[13]);
  1609. COPY_LOCALE_STR(locale->SpanHour, sizeof(locale->SpanHour), tokens->Token[14]);
  1610. COPY_LOCALE_STR(locale->SpanMinute, sizeof(locale->SpanMinute), tokens->Token[15]);
  1611. COPY_LOCALE_STR(locale->SpanSecond, sizeof(locale->SpanSecond), tokens->Token[16]);
  1612. COPY_LOCALE_STR(locale->Unknown, sizeof(locale->Unknown), tokens->Token[17]);
  1613. UniFreeToken(tokens);
  1614. return true;
  1615. }
  1616. // Convert SYSTEMTIME into DOS date
  1617. USHORT SystemToDosDate(SYSTEMTIME *st)
  1618. {
  1619. return (USHORT)(
  1620. ((UINT)(st->wYear - 1980) << 9) |
  1621. ((UINT)st->wMonth<< 5) |
  1622. (UINT)st->wDay);
  1623. }
  1624. USHORT System64ToDosDate(UINT64 i)
  1625. {
  1626. SYSTEMTIME st;
  1627. UINT64ToSystem(&st, i);
  1628. return SystemToDosDate(&st);
  1629. }
  1630. // Convert SYSTEMTIME into DOS time
  1631. USHORT SystemToDosTime(SYSTEMTIME *st)
  1632. {
  1633. return (USHORT)(
  1634. ((UINT)st->wHour << 11) |
  1635. ((UINT)st->wMinute << 5) |
  1636. ((UINT)st->wSecond >> 1));
  1637. }
  1638. USHORT System64ToDosTime(UINT64 i)
  1639. {
  1640. SYSTEMTIME st;
  1641. UINT64ToSystem(&st, i);
  1642. return SystemToDosTime(&st);
  1643. }
  1644. // Convert the tm to the SYSTEMTIME
  1645. void TmToSystem(SYSTEMTIME *st, struct tm *t)
  1646. {
  1647. struct tm tmp;
  1648. // Validate arguments
  1649. if (st == NULL || t == NULL)
  1650. {
  1651. return;
  1652. }
  1653. Copy(&tmp, t, sizeof(struct tm));
  1654. NormalizeTm(&tmp);
  1655. Zero(st, sizeof(SYSTEMTIME));
  1656. st->wYear = MAKESURE(tmp.tm_year + 1900, 1970, 2099);
  1657. st->wMonth = MAKESURE(tmp.tm_mon + 1, 1, 12);
  1658. st->wDay = MAKESURE(tmp.tm_mday, 1, 31);
  1659. st->wDayOfWeek = MAKESURE(tmp.tm_wday, 0, 6);
  1660. st->wHour = MAKESURE(tmp.tm_hour, 0, 23);
  1661. st->wMinute = MAKESURE(tmp.tm_min, 0, 59);
  1662. st->wSecond = MAKESURE(tmp.tm_sec, 0, 59);
  1663. st->wMilliseconds = 0;
  1664. }
  1665. // Convert the SYSTEMTIME to tm
  1666. void SystemToTm(struct tm *t, SYSTEMTIME *st)
  1667. {
  1668. // Validate arguments
  1669. if (t == NULL || st == NULL)
  1670. {
  1671. return;
  1672. }
  1673. Zero(t, sizeof(struct tm));
  1674. t->tm_year = MAKESURE(st->wYear, 1970, 2099) - 1900;
  1675. t->tm_mon = MAKESURE(st->wMonth, 1, 12) - 1;
  1676. t->tm_mday = MAKESURE(st->wDay, 1, 31);
  1677. t->tm_hour = MAKESURE(st->wHour, 0, 23);
  1678. t->tm_min = MAKESURE(st->wMinute, 0, 59);
  1679. t->tm_sec = MAKESURE(st->wSecond, 0, 59);
  1680. t->tm_isdst = -1;
  1681. NormalizeTm(t);
  1682. }
  1683. // Convert the time_t to SYSTEMTIME
  1684. void TimeToSystem(SYSTEMTIME *st, time_64t t)
  1685. {
  1686. struct tm tmp;
  1687. // Validate arguments
  1688. if (st == NULL)
  1689. {
  1690. return;
  1691. }
  1692. TimeToTm(&tmp, t);
  1693. TmToSystem(st, &tmp);
  1694. }
  1695. // Convert the time_t to 64-bit SYSTEMTIME
  1696. UINT64 TimeToSystem64(time_64t t)
  1697. {
  1698. SYSTEMTIME st;
  1699. TimeToSystem(&st, t);
  1700. return SystemToUINT64(&st);
  1701. }
  1702. // Convert the SYSTEMTIME to time_t
  1703. time_64t SystemToTime(SYSTEMTIME *st)
  1704. {
  1705. struct tm t;
  1706. // Validate arguments
  1707. if (st == NULL)
  1708. {
  1709. return 0;
  1710. }
  1711. SystemToTm(&t, st);
  1712. return TmToTime(&t);
  1713. }
  1714. // Convert a 64-bit SYSTEMTIME to a time_t
  1715. time_64t System64ToTime(UINT64 i)
  1716. {
  1717. SYSTEMTIME st;
  1718. UINT64ToSystem(&st, i);
  1719. return SystemToTime(&st);
  1720. }
  1721. // Convert the tm to time_t
  1722. time_64t TmToTime(struct tm *t)
  1723. {
  1724. time_64t tmp;
  1725. // Validate arguments
  1726. if (t == NULL)
  1727. {
  1728. return 0;
  1729. }
  1730. tmp = c_mkgmtime(t);
  1731. if (tmp == (time_64t)-1)
  1732. {
  1733. return 0;
  1734. }
  1735. return tmp;
  1736. }
  1737. // Convert time_t to tm
  1738. void TimeToTm(struct tm *t, time_64t time)
  1739. {
  1740. // Validate arguments
  1741. if (t == NULL)
  1742. {
  1743. return;
  1744. }
  1745. Zero(t, sizeof(struct tm));
  1746. c_gmtime_r(&time, t);
  1747. }
  1748. // Normalize the tm
  1749. void NormalizeTm(struct tm *t)
  1750. {
  1751. time_64t tmp;
  1752. // Validate arguments
  1753. if (t == NULL)
  1754. {
  1755. return;
  1756. }
  1757. tmp = c_mkgmtime(t);
  1758. if (tmp == (time_64t)-1)
  1759. {
  1760. return;
  1761. }
  1762. c_gmtime_r(&tmp, t);
  1763. }
  1764. // Normalize the SYSTEMTIME
  1765. void NormalizeSystem(SYSTEMTIME *st)
  1766. {
  1767. UINT64 sec64;
  1768. // Validate arguments
  1769. if (st == NULL)
  1770. {
  1771. return;
  1772. }
  1773. sec64 = SystemToUINT64(st);
  1774. UINT64ToSystem(st, sec64);
  1775. }
  1776. // Convert a 64-bit local time to a system time
  1777. UINT64 LocalToSystem64(UINT64 t)
  1778. {
  1779. SYSTEMTIME st;
  1780. UINT64ToSystem(&st, t);
  1781. LocalToSystem(&st, &st);
  1782. return SystemToUINT64(&st);
  1783. }
  1784. // Convert the 64bit system time to local time
  1785. UINT64 SystemToLocal64(UINT64 t)
  1786. {
  1787. SYSTEMTIME st;
  1788. UINT64ToSystem(&st, t);
  1789. SystemToLocal(&st, &st);
  1790. return SystemToUINT64(&st);
  1791. }
  1792. // Convert local time to system time
  1793. void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local)
  1794. {
  1795. UINT64 sec64;
  1796. // Validate arguments
  1797. if (local == NULL || system == NULL)
  1798. {
  1799. return;
  1800. }
  1801. sec64 = (UINT64)((INT64)SystemToUINT64(local) - GetTimeDiffEx(local, true));
  1802. UINT64ToSystem(system, sec64);
  1803. }
  1804. // Convert the system time to local time
  1805. void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system)
  1806. {
  1807. UINT64 sec64;
  1808. // Validate arguments
  1809. if (local == NULL || system == NULL)
  1810. {
  1811. return;
  1812. }
  1813. sec64 = (UINT64)((INT64)SystemToUINT64(system) + GetTimeDiffEx(system, false));
  1814. UINT64ToSystem(local, sec64);
  1815. }
  1816. // Get the time difference between the local time and the system time based on the specified time
  1817. INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
  1818. {
  1819. time_t tmp;
  1820. struct tm t1, t2;
  1821. SYSTEMTIME snow;
  1822. struct tm now;
  1823. SYSTEMTIME s1, s2;
  1824. INT64 ret;
  1825. Copy(&snow, basetime, sizeof(SYSTEMTIME));
  1826. if (sizeof(time_t) == 4)
  1827. {
  1828. if (snow.wYear >= 2038)
  1829. {
  1830. // For old systems: avoid the 2038-year problem
  1831. snow.wYear = 2037;
  1832. }
  1833. }
  1834. SystemToTm(&now, &snow);
  1835. if (local_time == false)
  1836. {
  1837. tmp = (time_t)c_mkgmtime(&now);
  1838. }
  1839. else
  1840. {
  1841. tmp = mktime(&now);
  1842. }
  1843. if (tmp == (time_t)-1)
  1844. {
  1845. return 0;
  1846. }
  1847. #ifndef OS_UNIX
  1848. Copy(&t1, localtime(&tmp), sizeof(struct tm));
  1849. Copy(&t2, gmtime(&tmp), sizeof(struct tm));
  1850. #else // OS_UNIX
  1851. localtime_r(&tmp, &t1);
  1852. gmtime_r(&tmp, &t2);
  1853. #endif // OS_UNIX
  1854. TmToSystem(&s1, &t1);
  1855. TmToSystem(&s2, &t2);
  1856. ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
  1857. return ret;
  1858. }
  1859. // Convert UINT64 to the SYSTEMTIME
  1860. void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64)
  1861. {
  1862. UINT64 tmp64;
  1863. UINT sec, millisec;
  1864. time_64t time;
  1865. // Validate arguments
  1866. if (st == NULL)
  1867. {
  1868. return;
  1869. }
  1870. sec64 = SafeTime64(sec64 + 32400000ULL);
  1871. tmp64 = sec64 / (UINT64)1000;
  1872. millisec = (UINT)(sec64 - tmp64 * (UINT64)1000);
  1873. sec = (UINT)tmp64;
  1874. time = (time_64t)sec;
  1875. TimeToSystem(st, time);
  1876. st->wMilliseconds = (WORD)millisec;
  1877. }
  1878. // Convert the SYSTEMTIME to UINT64
  1879. UINT64 SystemToUINT64(SYSTEMTIME *st)
  1880. {
  1881. UINT64 sec64;
  1882. time_64t time;
  1883. // Validate arguments
  1884. if (st == NULL)
  1885. {
  1886. return 0;
  1887. }
  1888. time = SystemToTime(st);
  1889. //For times before 1970-01-01, clamp to the minimum
  1890. //because we have to return an unsigned integer.
  1891. //This is less wrong than casting it to UINT64
  1892. //and returning a time far in the future.
  1893. //For some reason we subtract 9 hours below, so
  1894. //account for that here.
  1895. if( time < 32400000LL ) return 0;
  1896. sec64 = (UINT64)time * (UINT64)1000;
  1897. sec64 += st->wMilliseconds;
  1898. return sec64 - 32400000ULL;
  1899. }
  1900. // Get local time in UINT64
  1901. UINT64 LocalTime64()
  1902. {
  1903. SYSTEMTIME s;
  1904. LocalTime(&s);
  1905. return SystemToUINT64(&s);
  1906. }
  1907. // Get the system time in UINT64
  1908. UINT64 SystemTime64()
  1909. {
  1910. SYSTEMTIME s;
  1911. SystemTime(&s);
  1912. return SystemToUINT64(&s);
  1913. }
  1914. // Get local time
  1915. void LocalTime(SYSTEMTIME *st)
  1916. {
  1917. SYSTEMTIME tmp;
  1918. // Validate arguments
  1919. if (st == NULL)
  1920. {
  1921. return;
  1922. }
  1923. SystemTime(&tmp);
  1924. SystemToLocal(st, &tmp);
  1925. }
  1926. // Get the System Time
  1927. void SystemTime(SYSTEMTIME *st)
  1928. {
  1929. // Validate arguments
  1930. if (st == NULL)
  1931. {
  1932. return;
  1933. }
  1934. OSGetSystemTime(st);
  1935. // KS
  1936. KS_INC(KS_GETTIME_COUNT);
  1937. }
  1938. time_64t c_mkgmtime(struct tm *tm)
  1939. {
  1940. int years, months, days, hours, minutes, seconds;
  1941. years = tm->tm_year + 1900; /* year - 1900 -> year */
  1942. months = tm->tm_mon; /* 0..11 */
  1943. days = tm->tm_mday - 1; /* 1..31 -> 0..30 */
  1944. hours = tm->tm_hour; /* 0..23 */
  1945. minutes = tm->tm_min; /* 0..59 */
  1946. seconds = tm->tm_sec; /* 0..61 in ANSI C. */
  1947. ADJUST_TM(seconds, minutes, 60);
  1948. ADJUST_TM(minutes, hours, 60);
  1949. ADJUST_TM(hours, days, 24);
  1950. ADJUST_TM(months, years, 12);
  1951. if (days < 0)
  1952. do {
  1953. if (--months < 0) {
  1954. --years;
  1955. months = 11;
  1956. }
  1957. days += monthlen(months, years);
  1958. } while (days < 0);
  1959. else
  1960. while (days >= monthlen(months, years)) {
  1961. days -= monthlen(months, years);
  1962. if (++months >= 12) {
  1963. ++years;
  1964. months = 0;
  1965. }
  1966. }
  1967. /* Restore adjusted values in tm structure */
  1968. tm->tm_year = years - 1900;
  1969. tm->tm_mon = months;
  1970. tm->tm_mday = days + 1;
  1971. tm->tm_hour = hours;
  1972. tm->tm_min = minutes;
  1973. tm->tm_sec = seconds;
  1974. /* Set `days' to the number of days into the year. */
  1975. days += ydays[months] + (months > 1 && leap (years));
  1976. tm->tm_yday = days;
  1977. /* Now calculate `days' to the number of days since Jan 1, 1970. */
  1978. days = (unsigned)days + 365 * (unsigned)(years - 1970) +
  1979. (unsigned)(nleap (years));
  1980. tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
  1981. tm->tm_isdst = 0;
  1982. if (years < 1970)
  1983. return (time_64t)-1;
  1984. #if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
  1985. #if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
  1986. if (years > TM_YEAR_MAX ||
  1987. (years == TM_YEAR_MAX &&
  1988. (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
  1989. (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
  1990. (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
  1991. (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
  1992. (hours > TM_HOUR_MAX ||
  1993. (hours == TM_HOUR_MAX &&
  1994. (minutes > TM_MIN_MAX ||
  1995. (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
  1996. return (time_64t)-1;
  1997. #endif
  1998. #endif
  1999. return (time_64t)(86400L * (unsigned long)(unsigned)days +
  2000. 3600L * (unsigned long)hours +
  2001. (unsigned long)(60 * minutes + seconds));
  2002. }
  2003. // Get the system timer
  2004. UINT Tick()
  2005. {
  2006. // KS
  2007. KS_INC(KS_GETTICK_COUNT);
  2008. return OSGetTick();
  2009. }
  2010. // Sleep thread
  2011. void SleepThread(UINT time)
  2012. {
  2013. // KS
  2014. KS_INC(KS_SLEEPTHREAD_COUNT);
  2015. OSSleep(time);
  2016. }
  2017. // Yield
  2018. void YieldCpu()
  2019. {
  2020. OSYield();
  2021. }
  2022. // Stop system (abnormal termination)
  2023. void AbortExit()
  2024. {
  2025. #ifdef OS_WIN32
  2026. _exit(1);
  2027. #else // OS_WIN32
  2028. #ifdef RLIMIT_CORE
  2029. UnixSetResourceLimit(RLIMIT_CORE, 0);
  2030. #endif // RLIMIT_CORE
  2031. abort();
  2032. #endif // OS_WIN32
  2033. }
  2034. void AbortExitEx(char *msg)
  2035. {
  2036. FILE *f;
  2037. // Validate arguments
  2038. if (msg == NULL)
  2039. {
  2040. msg = "Unknown Error";
  2041. }
  2042. f = fopen("abort_error_log.txt", "a");
  2043. if (f != NULL)
  2044. {
  2045. SYSTEMTIME time = CLEAN;
  2046. char time_str[128] = CLEAN;
  2047. char* crlf = "\r\n";
  2048. char* tag = "---------";
  2049. LocalTime(&time);
  2050. sprintf(time_str, "%04u-%02u-%02u %02u:%02u:%02u",
  2051. time.wYear, time.wMonth, time.wDay,
  2052. time.wHour, time.wMinute, time.wSecond);
  2053. fwrite(tag, 1, strlen(tag), f);
  2054. fwrite(crlf, 1, strlen(crlf), f);
  2055. fwrite(time_str, 1, strlen(time_str), f);
  2056. fwrite(crlf, 1, strlen(crlf), f);
  2057. fwrite(msg, 1, strlen(msg), f);
  2058. fwrite(crlf, 1, strlen(crlf), f);
  2059. fwrite(crlf, 1, strlen(crlf), f);
  2060. fclose(f);
  2061. }
  2062. fputs("Fatal Error: ", stdout);
  2063. fputs(msg, stdout);
  2064. fputs("\r\n", stdout);
  2065. #ifdef OS_WIN32
  2066. _exit(1);
  2067. #else // OS_WIN32
  2068. #ifdef RLIMIT_CORE
  2069. UnixSetResourceLimit(RLIMIT_CORE, 0);
  2070. #endif // RLIMIT_CORE
  2071. abort();
  2072. #endif // OS_WIN32
  2073. }