source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/Kernel.c @ 072e48b

trunk
Last change on this file since 072e48b was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100644
File size: 40.5 KB
Line 
1// SoftEther UT-VPN SourceCode
2//
3// Copyright (C) 2004-2010 SoftEther Corporation.
4// Copyright (C) 2004-2010 University of Tsukuba, Japan.
5// Copyright (C) 2003-2010 Daiyuu Nobori.
6// All Rights Reserved.
7//
8// http://utvpn.tsukuba.ac.jp/
9//
10// This program is free software; you can redistribute it and/or
11// modify it under the terms of the GNU General Public License
12// version 2 as published by the Free Software Foundation.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License version 2
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22//
23// このファイルは GPL バージョン 2 ライセンスで公開されています。
24// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
25// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
26// を除去することはできません。改変した著作物を配布する場合は、改変実施者の
27// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
28//
29// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
30// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
31// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
32// ホストされています。
33// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
34// および、試験または研究のために利用が行われることを想定して配布
35// しています。
36// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
37// あります。
38// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
39// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
40// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
41// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
42// に組み込みさせていただきます。
43//
44// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
45// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
46//
47// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
48// (SoftEther Corporation) およびその他の著作権保持者が保有しています。
49// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
50// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
51// ください。
52//
53// お願い: どのような通信ソフトウェアにも通常は必ず未発見の
54// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
55// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
56// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
57// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
58// 公益保護にご協力いただきますようお願い申し上げます。
59//
60// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
61// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
62// を保護するための努力を行います。
63//
64// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
65// 日本国内の脆弱性情報届出受付公的機関:
66//         独立行政法人 情報処理推進機構
67//         http://www.ipa.go.jp/security/vuln/report/
68//
69// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
70// 連絡先: http://www.softether.co.jp/jp/contact/
71
72// -----------------------------------------------
73// [ChangeLog]
74// 2010.05.20
75//  新規リリース by SoftEther
76// -----------------------------------------------
77
78// Kernel.c
79// システムサービス処理ルーチン
80
81#include <stdio.h>
82#include <stdlib.h>
83#include <string.h>
84#include <wchar.h>
85#include <stdarg.h>
86#include <time.h>
87#include <errno.h>
88#include <Mayaqua/Mayaqua.h>
89
90#ifndef TM_YEAR_MAX
91#define TM_YEAR_MAX         2106
92#endif
93#ifndef TM_MON_MAX
94#define TM_MON_MAX          1
95#endif
96#ifndef TM_MDAY_MAX
97#define TM_MDAY_MAX         7
98#endif
99#ifndef TM_HOUR_MAX
100#define TM_HOUR_MAX         6
101#endif
102#ifndef TM_MIN_MAX
103#define TM_MIN_MAX          28
104#endif
105#ifndef TM_SEC_MAX
106#define TM_SEC_MAX          14
107#endif
108
109/* free mktime function
110   Copyright 1988, 1989 by David MacKenzie <djm@ai.mit.edu>
111   and Michael Haertel <mike@ai.mit.edu>
112   Unlimited distribution permitted provided this copyright notice is
113   retained and any functional modifications are prominently identified.  */
114#define ADJUST_TM(tm_member, tm_carry, modulus) \
115    if ((tm_member) < 0){ \
116        tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
117        tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
118    } else if ((tm_member) >= (modulus)) { \
119        tm_carry += (tm_member) / (modulus); \
120        tm_member = (tm_member) % (modulus); \
121    }
122#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
123#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
124#define leapday(m, y) ((m) == 1 && leap (y))
125#define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
126static int ydays[] =
127{
128    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
129};
130
131
132static wchar_t *default_locale_str =
133L"- - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)";
134
135static LOCALE current_locale;
136LOCK *tick_manual_lock = NULL;
137UINT g_zero = 0;
138
139// リアルタイムシステムタイマの取得
140UINT TickRealtime()
141{
142#if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
143    return Tick() + 1;
144#else
145    return TickRealtimeManual() + 1;
146#endif
147}
148
149#ifndef OS_WIN32
150
151static UINT64 last_manual_tick = 0;
152static UINT64 manual_tick_add_value = 0;
153
154// clock_gettime が無いシステム向け (MacOS X など)
155UINT TickRealtimeManual()
156{
157    UINT64 ret;
158    Lock(tick_manual_lock);
159    {
160        ret = TickGetRealtimeTickValue64();
161
162        if (last_manual_tick != 0 && (last_manual_tick > ret))
163        {
164            manual_tick_add_value += (last_manual_tick - ret);
165        }
166
167        last_manual_tick = ret;
168    }
169    Unlock(tick_manual_lock);
170
171    return (UINT)(ret + manual_tick_add_value);
172}
173
174// 現在時刻から適当な値を返す
175UINT64 TickGetRealtimeTickValue64()
176{
177    struct timeval tv;
178    struct timezone tz;
179    UINT64 ret;
180
181    memset(&tv, 0, sizeof(tv));
182    memset(&tz, 0, sizeof(tz));
183
184    gettimeofday(&tv, &tz);
185
186    ret = (UINT64)tv.tv_sec * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
187
188    return ret;
189}
190
191#endif  // OS_WIN32
192
193// ホームディレクトリを取得
194void GetHomeDirW(wchar_t *path, UINT size)
195{
196    // 引数チェック
197    if (path == NULL)
198    {
199        return;
200    }
201
202    if (GetEnvW(L"HOME", path, size) == false)
203    {
204        wchar_t drive[MAX_SIZE];
205        wchar_t hpath[MAX_SIZE];
206        if (GetEnvW(L"HOMEDRIVE", drive, sizeof(drive)) &&
207            GetEnvW(L"HOMEPATH", hpath, sizeof(hpath)))
208        {
209            UniFormat(path, sizeof(path), L"%s%s", drive, hpath);
210        }
211        else
212        {
213#ifdef  OS_WIN32
214            Win32GetCurrentDirW(path, size);
215#else   // OS_WIN32
216            UnixGetCurrentDirW(path, size);
217#endif  // OS_WIN32
218        }
219    }
220}
221void GetHomeDir(char *path, UINT size)
222{
223    // 引数チェック
224    if (path == NULL)
225    {
226        return;
227    }
228
229    if (GetEnv("HOME", path, size) == false)
230    {
231        char drive[MAX_SIZE];
232        char hpath[MAX_SIZE];
233        if (GetEnv("HOMEDRIVE", drive, sizeof(drive)) &&
234            GetEnv("HOMEPATH", hpath, sizeof(hpath)))
235        {
236            Format(path, sizeof(path), "%s%s", drive, hpath);
237        }
238        else
239        {
240#ifdef  OS_WIN32
241            Win32GetCurrentDir(path, size);
242#else   // OS_WIN32
243            UnixGetCurrentDir(path, size);
244#endif  // OS_WIN32
245        }
246    }
247}
248
249// 環境変数文字列を取得
250bool GetEnv(char *name, char *data, UINT size)
251{
252    char *ret;
253    // 引数チェック
254    if (name == NULL || data == NULL)
255    {
256        return false;
257    }
258
259    StrCpy(data, size, "");
260
261    ret = getenv(name);
262    if (ret == NULL)
263    {
264        return false;
265    }
266
267    StrCpy(data, size, ret);
268
269    return true;
270}
271bool GetEnvW(wchar_t *name, wchar_t *data, UINT size)
272{
273#ifdef  OS_WIN32
274    return GetEnvW_ForWin32(name, data, size);
275#else   // OS_WIN32
276    return GetEnvW_ForUnix(name, data, size);
277#endif  // OS_WIN32
278}
279
280#ifdef  OS_WIN32
281bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size)
282{
283    wchar_t *ret;
284    // 引数チェック
285    if (name == NULL || data == NULL)
286    {
287        return false;
288    }
289
290    if (IsNt() == false)
291    {
292        bool ret;
293        char *name_a = CopyUniToStr(name);
294        char data_a[MAX_SIZE];
295
296        ret = GetEnv(name_a, data_a, sizeof(data_a));
297
298        if (ret)
299        {
300            StrToUni(data, size, data_a);
301        }
302
303        Free(name_a);
304
305        return ret;
306    }
307
308    UniStrCpy(data, size, L"");
309
310    ret = _wgetenv(name);
311    if (ret == NULL)
312    {
313        return false;
314    }
315
316    UniStrCpy(data, size, ret);
317
318    return true;
319}
320
321#endif  // OS_WIN32
322
323#ifdef  OS_UNIX
324
325bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size)
326{
327    char *name_a;
328    bool ret;
329    char data_a[MAX_SIZE];
330    // 引数チェック
331    if (name == NULL || data == NULL)
332    {
333        return false;
334    }
335
336    name_a = CopyUniToUtf(name);
337
338    ret = GetEnv(name_a, data_a, sizeof(data_a));
339
340    if (ret)
341    {
342        UtfToUni(data, size, data_a);
343    }
344
345    Free(name_a);
346
347    return ret;
348}
349
350#endif  // OS_UNIX
351
352// メモリ情報取得
353void GetMemInfo(MEMINFO *info)
354{
355    OSGetMemInfo(info);
356}
357
358// シングルインスタンスの開始
359INSTANCE *NewSingleInstance(char *instance_name)
360{
361    return NewSingleInstanceEx(instance_name, false);
362}
363INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local)
364{
365    char name[MAX_SIZE];
366    INSTANCE *ret;
367    void *data;
368
369    if (instance_name != NULL)
370    {
371        if (user_local == false)
372        {
373            HashInstanceName(name, sizeof(name), instance_name);
374        }
375        else
376        {
377            HashInstanceNameLocal(name, sizeof(name), instance_name);
378        }
379
380        data = OSNewSingleInstance(name);
381    }
382    else
383    {
384        data = OSNewSingleInstance(NULL);
385    }
386
387    if (data == NULL)
388    {
389        return NULL;
390    }
391
392    ret = ZeroMalloc(sizeof(INSTANCE));
393    if (instance_name != NULL)
394    {
395        ret->Name = CopyStr(instance_name);
396    }
397
398    ret->pData = data;
399
400    return ret;
401}
402
403// シングルインスタンスの解放
404void FreeSingleInstance(INSTANCE *inst)
405{
406    // 引数チェック
407    if (inst == NULL)
408    {
409        return;
410    }
411
412    OSFreeSingleInstance(inst->pData);
413
414    if (inst->Name != NULL)
415    {
416        Free(inst->Name);
417    }
418    Free(inst);
419}
420
421// インスタンス名をハッシュする
422void HashInstanceName(char *name, UINT size, char *instance_name)
423{
424    char tmp[MAX_SIZE];
425    UCHAR hash[SHA1_SIZE];
426    char key[11];
427    // 引数チェック
428    if (name == NULL || instance_name == NULL)
429    {
430        return;
431    }
432
433    StrCpy(tmp, sizeof(tmp), instance_name);
434    Trim(tmp);
435    StrUpper(tmp);
436
437    Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
438    BinToStr(key, sizeof(key), hash, 5);
439    key[10] = 0;
440
441    Format(name, size, "VPN-%s", key);
442
443    if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
444    {
445        if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
446            GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
447        {
448            StrCpy(tmp, sizeof(tmp), name);
449            Format(name, size, "Global\\%s", tmp);
450        }
451    }
452}
453void HashInstanceNameLocal(char *name, UINT size, char *instance_name)
454{
455    char tmp[MAX_SIZE];
456    UCHAR hash[SHA1_SIZE];
457    char key[11];
458    // 引数チェック
459    if (name == NULL || instance_name == NULL)
460    {
461        return;
462    }
463
464    StrCpy(tmp, sizeof(tmp), instance_name);
465    Trim(tmp);
466    StrUpper(tmp);
467
468    Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
469    BinToStr(key, sizeof(key), hash, 5);
470    key[10] = 0;
471
472    Format(name, size, "VPN-%s", key);
473
474    if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
475    {
476        if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
477            GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
478        {
479            StrCpy(tmp, sizeof(tmp), name);
480            Format(name, size, "Local\\%s", tmp);
481        }
482    }
483}
484
485// プロセスの起動
486bool Run(char *filename, char *arg, bool hide, bool wait)
487{
488    // 引数チェック
489    if (filename == NULL)
490    {
491        return false;
492    }
493
494    return OSRun(filename, arg, hide, wait);
495}
496bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
497{
498    // 引数チェック
499    if (filename == NULL)
500    {
501        return false;
502    }
503
504    return OSRunW(filename, arg, hide, wait);
505}
506
507// 日付・時刻関係の関数
508void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64)
509{
510    char tmp[MAX_SIZE];
511    if (str == NULL)
512    {
513        return;
514    }
515
516    GetDateTimeStr64(tmp, sizeof(tmp), sec64);
517    StrToUni(str, size, tmp);
518}
519void GetDateTimeStr64(char *str, UINT size, UINT64 sec64)
520{
521    SYSTEMTIME st;
522    UINT64ToSystem(&st, sec64);
523    GetDateTimeStr(str, size, &st);
524}
525void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64)
526{
527    SYSTEMTIME st;
528    UINT64ToSystem(&st, sec64);
529    GetDateTimeStrMilli(str, size, &st);
530}
531void GetDateStr64(char *str, UINT size, UINT64 sec64)
532{
533    SYSTEMTIME st;
534    if (sec64 == 0)
535    {
536        StrCpy(str, size, "(Unknown)");
537        return;
538    }
539    UINT64ToSystem(&st, sec64);
540    GetDateStr(str, size, &st);
541}
542void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
543{
544    SYSTEMTIME st;
545    if (locale == NULL)
546    {
547        locale = &current_locale;
548    }
549    if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
550    {
551        UniStrCpy(str, size, locale->Unknown);
552        return;
553    }
554    UINT64ToSystem(&st, sec64);
555    GetDateTimeStrEx(str, size, &st, locale);
556}
557void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
558{
559    SYSTEMTIME st;
560    if (locale == NULL)
561    {
562        locale = &current_locale;
563    }
564    if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
565    {
566        UniStrCpy(str, size, locale->Unknown);
567        return;
568    }
569    UINT64ToSystem(&st, sec64);
570    GetTimeStrEx(str, size, &st, locale);
571}
572void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
573{
574    SYSTEMTIME st;
575    if (locale == NULL)
576    {
577        locale = &current_locale;
578    }
579    if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
580    {
581        UniStrCpy(str, size, locale->Unknown);
582        return;
583    }
584    UINT64ToSystem(&st, sec64);
585    GetDateStrEx(str, size, &st, locale);
586}
587void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64)
588{
589    SYSTEMTIME st;
590    if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
591    {
592        StrCpy(str, size, "(Unknown)");
593        return;
594    }
595    UINT64ToSystem(&st, sec64);
596    GetTimeStrMilli(str, size, &st);
597}
598void GetTimeStr64(char *str, UINT size, UINT64 sec64)
599{
600    SYSTEMTIME st;
601    if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
602    {
603        StrCpy(str, size, "(Unknown)");
604        return;
605    }
606    UINT64ToSystem(&st, sec64);
607    GetTimeStr(str, size, &st);
608}
609
610// 現在の POSIX 実装で使用しても安全な時刻に変換する
611UINT64 SafeTime64(UINT64 sec64)
612{
613    return MAKESURE(sec64, 0, 2115947647000ULL);
614}
615
616// スレッドプール
617static SK *thread_pool = NULL;
618static COUNTER *thread_count = NULL;
619
620// スレッドプールの初期化
621void InitThreading()
622{
623    thread_pool = NewSk();
624    thread_count = NewCounter();
625}
626
627// スレッドプールの解放
628void FreeThreading()
629{
630    while (true)
631    {
632        if (Count(thread_count) == 0)
633        {
634            break;
635        }
636
637        SleepThread(25);
638    }
639
640    while (true)
641    {
642        THREAD_POOL_DATA *pd;
643        THREAD *t = Pop(thread_pool);
644
645        if (t == NULL)
646        {
647            break;
648        }
649
650        pd = (THREAD_POOL_DATA *)t->param;
651
652        pd->ThreadProc = NULL;
653        Set(pd->Event);
654
655        WaitThreadInternal(t);
656
657        pd = (THREAD_POOL_DATA *)t->param;
658        ReleaseEvent(pd->Event);
659        ReleaseEvent(pd->InitFinishEvent);
660
661        ReleaseThreadInternal(t);
662
663        Free(pd);
664    }
665
666    ReleaseSk(thread_pool);
667
668    DeleteCounter(thread_count);
669    thread_count = NULL;
670}
671
672// スレッドプールプロシージャ
673void ThreadPoolProc(THREAD *t, void *param)
674{
675    THREAD_POOL_DATA *pd;
676    // 引数チェック
677    if (t == NULL)
678    {
679        return;
680    }
681
682    pd = (THREAD_POOL_DATA *)param;
683
684    NoticeThreadInitInternal(t);
685
686    while (true)
687    {
688        THREAD *thread;
689        UINT i, num;
690        EVENT **ee;
691
692        // 次の仕事を待つ
693        Wait(pd->Event, INFINITE);
694
695        if (pd->ThreadProc == NULL)
696        {
697            // プールスレッドの動作停止
698            break;
699        }
700
701        thread = pd->Thread;
702        thread->ThreadId = ThreadId();
703
704        // 初期化完了
705        Set(pd->InitFinishEvent);
706
707        // スレッドプロシージャの実行
708        pd->ThreadProc(pd->Thread, thread->param);
709
710        thread->PoolHalting = true;
711
712        // 待機イベントリストを叩く
713        LockList(thread->PoolWaitList);
714        {
715            num = LIST_NUM(thread->PoolWaitList);
716            ee = ToArray(thread->PoolWaitList);
717
718            DeleteAll(thread->PoolWaitList);
719        }
720        UnlockList(thread->PoolWaitList);
721
722        for (i = 0;i < num;i++)
723        {
724            EVENT *e = ee[i];
725
726            Set(e);
727            ReleaseEvent(e);
728        }
729
730        Free(ee);
731
732        while (true)
733        {
734            if (Count(thread->ref->c) <= 1)
735            {
736                break;
737            }
738
739            Wait(thread->release_event, 256);
740        }
741
742        ReleaseThread(thread);
743
744#ifdef  OS_WIN32
745        // Win32 の場合: スレッドの優先順位を元に戻す
746        MsRestoreThreadPriority();
747#endif  // OS_WIN32
748
749        // スレッドプールに自分自身を登録する
750        LockSk(thread_pool);
751        {
752            Push(thread_pool, t);
753        }
754        UnlockSk(thread_pool);
755
756        Dec(thread_count);
757    }
758}
759
760// 何もしない
761UINT DoNothing()
762{
763    return g_zero;
764}
765
766// スレッド作成 (プール)
767THREAD *NewThread(THREAD_PROC *thread_proc, void *param)
768{
769    THREAD *host = NULL;
770    THREAD_POOL_DATA *pd = NULL;
771    THREAD *ret;
772    bool new_thread = false;
773    // 引数チェック
774    if (thread_proc == NULL)
775    {
776        return NULL;
777    }
778
779    if (IsTrackingEnabled() == false)
780    {
781        DoNothing();
782    }
783
784    Inc(thread_count);
785
786    LockSk(thread_pool);
787    {
788        // 現在プールに空いているスレッドがあるかどうか調べる
789        host = Pop(thread_pool);
790    }
791    UnlockSk(thread_pool);
792
793    if (host == NULL)
794    {
795        // 空いているスレッドが見つからなかったので新しいスレッドを作成する
796        pd = ZeroMalloc(sizeof(THREAD_POOL_DATA));
797        pd->Event = NewEvent();
798        pd->InitFinishEvent = NewEvent();
799        host = NewThreadInternal(ThreadPoolProc, pd);
800        WaitThreadInitInternal(host);
801
802        new_thread = true;
803    }
804    else
805    {
806        pd = (THREAD_POOL_DATA *)host->param;
807    }
808
809    // プールスレッドの作成
810    ret = ZeroMalloc(sizeof(THREAD));
811    ret->ref = NewRef();
812    ret->thread_proc = thread_proc;
813    ret->param = param;
814    ret->pData = NULL;
815    ret->init_finished_event = NewEvent();
816    ret->PoolThread = true;
817    ret->PoolWaitList = NewList(NULL);
818    ret->PoolHostThread = host;
819    ret->release_event = NewEvent();
820
821    // 実行
822    pd->ThreadProc = thread_proc;
823    pd->Thread = ret;
824    AddRef(ret->ref);
825
826    Set(pd->Event);
827
828    Wait(pd->InitFinishEvent, INFINITE);
829
830    return ret;
831}
832
833// スレッドのクリーンアップ (プール)
834void CleanupThread(THREAD *t)
835{
836    // 引数チェック
837    if (t == NULL)
838    {
839        return;
840    }
841
842    ReleaseEvent(t->init_finished_event);
843    ReleaseEvent(t->release_event);
844    ReleaseList(t->PoolWaitList);
845
846    Free(t);
847}
848
849// スレッド解放 (プール)
850void ReleaseThread(THREAD *t)
851{
852    UINT ret;
853    EVENT *e;
854    // 引数チェック
855    if (t == NULL)
856    {
857        return;
858    }
859
860    e = t->release_event;
861    if (e != NULL)
862    {
863        AddRef(e->ref);
864    }
865
866    ret = Release(t->ref);
867    Set(e);
868
869    ReleaseEvent(e);
870
871    if (ret == 0)
872    {
873        CleanupThread(t);
874    }
875}
876
877// スレッドの初期化完了を通知 (プール)
878void NoticeThreadInit(THREAD *t)
879{
880    // 引数チェック
881    if (t == NULL)
882    {
883        return;
884    }
885
886    // 通知
887    Set(t->init_finished_event);
888}
889
890// スレッドの初期化完了を待機 (プール)
891void WaitThreadInit(THREAD *t)
892{
893    // 引数チェック
894    if (t == NULL)
895    {
896        return;
897    }
898
899    // KS
900    KS_INC(KS_WAITFORTHREAD_COUNT);
901
902    // 待機
903    Wait(t->init_finished_event, INFINITE);
904}
905
906// スレッドの終了を待機 (プール)
907bool WaitThread(THREAD *t, UINT timeout)
908{
909    bool ret = false;
910    EVENT *e = NULL;
911    // 引数チェック
912    if (t == NULL)
913    {
914        return false;
915    }
916
917    LockList(t->PoolWaitList);
918    {
919        if (t->PoolHalting)
920        {
921            // 既に停止済み
922            ret = true;
923        }
924        else
925        {
926            // 終了時通知イベントをリストに登録する
927            e = NewEvent();
928            AddRef(e->ref);
929            Insert(t->PoolWaitList, e);
930        }
931    }
932    UnlockList(t->PoolWaitList);
933
934    if (e != NULL)
935    {
936        // イベント待機
937        ret = Wait(e, timeout);
938
939        LockList(t->PoolWaitList);
940        {
941            if (Delete(t->PoolWaitList, e))
942            {
943                ReleaseEvent(e);
944            }
945        }
946        UnlockList(t->PoolWaitList);
947
948        ReleaseEvent(e);
949    }
950
951    return ret;
952}
953
954// スレッド ID の取得
955UINT ThreadId()
956{
957    return OSThreadId();
958}
959
960// スレッドの作成
961THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param)
962{
963    THREAD *t;
964    UINT retry = 0;
965    // 引数チェック
966    if (thread_proc == NULL)
967    {
968        return NULL;
969    }
970
971    // スレッドオブジェクト初期化
972    t = ZeroMalloc(sizeof(THREAD));
973    t->init_finished_event = NewEvent();
974
975    t->param = param;
976    t->ref = NewRef();
977    t->thread_proc = thread_proc;
978
979    // OS がスレッドを初期化するまで待機
980    while (true)
981    {
982        if ((retry++) > 60)
983        {
984            printf("\n\n*** error: new thread create failed.\n\n");
985            AbortExit();
986        }
987        if (OSInitThread(t))
988        {
989            break;
990        }
991        SleepThread(500);
992    }
993
994    // KS
995    KS_INC(KS_NEWTHREAD_COUNT);
996
997    return t;
998}
999
1000// スレッドの解放
1001void ReleaseThreadInternal(THREAD *t)
1002{
1003    // 引数チェック
1004    if (t == NULL)
1005    {
1006        return;
1007    }
1008
1009    if (Release(t->ref) == 0)
1010    {
1011        CleanupThreadInternal(t);
1012    }
1013}
1014
1015// スレッドのクリーンアップ
1016void CleanupThreadInternal(THREAD *t)
1017{
1018    // 引数チェック
1019    if (t == NULL)
1020    {
1021        return;
1022    }
1023
1024    // スレッドの解放
1025    OSFreeThread(t);
1026
1027    // イベント解放
1028    ReleaseEvent(t->init_finished_event);
1029    // メモリ解放
1030    Free(t);
1031
1032    // KS
1033    KS_INC(KS_FREETHREAD_COUNT);
1034}
1035
1036// スレッドの終了を待機する
1037bool WaitThreadInternal(THREAD *t)
1038{
1039    // 引数チェック
1040    if (t == NULL)
1041    {
1042        return false;
1043    }
1044
1045    return OSWaitThread(t);
1046}
1047
1048// スレッドの初期化が完了したことを通知する
1049void NoticeThreadInitInternal(THREAD *t)
1050{
1051    // 引数チェック
1052    if (t == NULL)
1053    {
1054        return;
1055    }
1056
1057    // 通知
1058    Set(t->init_finished_event);
1059}
1060
1061// スレッドの初期化が完了するまで待機する
1062void WaitThreadInitInternal(THREAD *t)
1063{
1064    // 引数チェック
1065    if (t == NULL)
1066    {
1067        return;
1068    }
1069
1070    // KS
1071    KS_INC(KS_WAITFORTHREAD_COUNT);
1072
1073    // 待機
1074    Wait(t->init_finished_event, INFINITE);
1075}
1076
1077// 日時文字列をロケール情報を使用して取得
1078void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
1079{
1080    wchar_t tmp1[MAX_SIZE];
1081    wchar_t tmp2[MAX_SIZE];
1082    // 引数チェック
1083    if (str == NULL || st == NULL)
1084    {
1085        return;
1086    }
1087
1088    GetDateStrEx(tmp1, sizeof(tmp1), st, locale);
1089    GetTimeStrEx(tmp2, sizeof(tmp2), st, locale);
1090    UniFormat(str, size, L"%s %s", tmp1, tmp2);
1091}
1092
1093// 時刻文字列をロケール情報を使用して取得
1094void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
1095{
1096    wchar_t *tag = L"%02u%s%02u%s%02u%s";
1097    // 引数チェック
1098    if (str == NULL || st == NULL)
1099    {
1100        return;
1101    }
1102
1103    if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
1104    {
1105        tag = L"%2u%s%2u%s%2u%s";
1106    }
1107
1108    locale = (locale != NULL ? locale : &current_locale);
1109    UniFormat(str, size,
1110        tag,
1111        st->wHour, locale->HourStr,
1112        st->wMinute, locale->MinuteStr,
1113        st->wSecond, locale->SecondStr);
1114}
1115
1116// 日付文字列をロケール情報を使用して取得
1117void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
1118{
1119    wchar_t *tag = L"%04u%s%02u%s%02u%s (%s)";
1120    // 引数チェック
1121    if (str == NULL || st == NULL)
1122    {
1123        return;
1124    }
1125
1126    if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
1127    {
1128        tag = L"%4u%s%2u%s%2u%s(%s)";
1129    }
1130
1131    locale = (locale != NULL ? locale : &current_locale);
1132    UniFormat(str, size,
1133        tag,
1134        st->wYear, locale->YearStr,
1135        st->wMonth, locale->MonthStr,
1136        st->wDay, locale->DayStr,
1137        locale->DayOfWeek[st->wDayOfWeek]);
1138}
1139
1140// 時刻文字列をミリ秒単位で取得 (例: 12:34:56.789)
1141void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
1142{
1143    // 引数チェック
1144    if (st == NULL || str == NULL)
1145    {
1146        return;
1147    }
1148
1149    Format(str, size, "%02u:%02u:%02u.%03u",
1150        st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
1151}
1152
1153// 時刻文字列を取得 (例: 12:34:56)
1154void GetTimeStr(char *str, UINT size, SYSTEMTIME *st)
1155{
1156    // 引数チェック
1157    if (str == NULL || st == NULL)
1158    {
1159        return;
1160    }
1161
1162    Format(str, size, "%02u:%02u:%02u",
1163        st->wHour, st->wMinute, st->wSecond);
1164}
1165
1166// 日付文字列を取得 (例: 2004/07/23)
1167void GetDateStr(char *str, UINT size, SYSTEMTIME *st)
1168{
1169    // 引数チェック
1170    if (str == NULL || st == NULL)
1171    {
1172        return;
1173    }
1174
1175    Format(str, size, "%04u-%02u-%02u",
1176        st->wYear, st->wMonth, st->wDay);
1177}
1178
1179// 日時文字列を取得 (例: 2004/07/23 12:34:56)
1180void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st)
1181{
1182    // 引数チェック
1183    if (str == NULL || st == NULL)
1184    {
1185        return;
1186    }
1187
1188    Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u",
1189        st->wYear, st->wMonth, st->wDay,
1190        st->wHour, st->wMinute, st->wSecond);
1191}
1192
1193// 日時文字列をミリ秒単位で取得 (例: 2004/07/23 12:34:56.789)
1194void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
1195{
1196    // 引数チェック
1197    if (str == NULL || st == NULL)
1198    {
1199        return;
1200    }
1201
1202    Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
1203        st->wYear, st->wMonth, st->wDay,
1204        st->wHour, st->wMinute, st->wSecond,
1205        st->wMilliseconds);
1206}
1207
1208// 時間文字列の取得
1209void GetSpanStr(char *str, UINT size, UINT64 sec64)
1210{
1211    char tmp[MAX_SIZE];
1212    // 引数チェック
1213    if (str == NULL)
1214    {
1215        return;
1216    }
1217
1218    StrCpy(tmp, sizeof(tmp), "");
1219    if (sec64 >= (UINT64)(1000 * 3600 * 24))
1220    {
1221        Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
1222    }
1223
1224    Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u", tmp,
1225        (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
1226        (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
1227        (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000);
1228
1229    Trim(tmp);
1230    StrCpy(str, size, tmp);
1231}
1232
1233// 時間文字列の取得 (ミリ秒単位)
1234void GetSpanStrMilli(char *str, UINT size, UINT64 sec64)
1235{
1236    char tmp[MAX_SIZE];
1237    // 引数チェック
1238    if (str == NULL)
1239    {
1240        return;
1241    }
1242
1243    StrCpy(tmp, sizeof(tmp), "");
1244    if (sec64 >= (UINT64)(1000 * 3600 * 24))
1245    {
1246        Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
1247    }
1248
1249    Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u.%03u", tmp,
1250        (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
1251        (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
1252        (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
1253        (UINT)(sec64 % (UINT64)(1000)));
1254
1255    Trim(tmp);
1256    StrCpy(str, size, tmp);
1257}
1258
1259// 時間文字列の取得 (拡張)
1260void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
1261{
1262    wchar_t tmp[MAX_SIZE];
1263    // 引数チェック
1264    if (str == NULL)
1265    {
1266        return;
1267    }
1268
1269    locale = (locale != NULL ? locale : &current_locale);
1270
1271    UniStrCpy(tmp, sizeof(tmp), L"");
1272    if (sec64 >= (UINT64)(1000 * 3600 * 24))
1273    {
1274        UniFormat(tmp, sizeof(tmp), L"%u%s ", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)),
1275            locale->SpanDay);
1276    }
1277
1278    UniFormat(tmp, sizeof(tmp), L"%s%u%s %02u%s %02u%s", tmp,
1279        (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
1280        locale->SpanHour,
1281        (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
1282        locale->SpanMinute,
1283        (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
1284        locale->SpanSecond);
1285
1286    UniTrim(tmp);
1287    UniStrCpy(str, size, tmp);
1288}
1289
1290// 現在のロケール情報を取得
1291void GetCurrentLocale(LOCALE *locale)
1292{
1293    // 引数チェック
1294    if (locale == NULL)
1295    {
1296        return;
1297    }
1298
1299    Copy(locale, &current_locale, sizeof(LOCALE));
1300}
1301
1302// ロケール情報を設定
1303void SetLocale(wchar_t *str)
1304{
1305    wchar_t *set_locale_str;
1306    LOCALE tmp;
1307
1308    if (str != NULL)
1309    {
1310        set_locale_str = str;
1311    }
1312    else
1313    {
1314        set_locale_str = default_locale_str;
1315    }
1316
1317    if (LoadLocale(&tmp, set_locale_str) == false)
1318    {
1319        if (LoadLocale(&tmp, default_locale_str) == false)
1320        {
1321            return;
1322        }
1323    }
1324
1325    Copy(&current_locale, &tmp, sizeof(LOCALE));
1326}
1327
1328#define COPY_LOCALE_STR(dest, size, src)    UniStrCpy(dest, size, UniStrCmp(src, L"$") == 0 ? L"" : src)
1329
1330// ロケール情報の読み込み
1331bool LoadLocale(LOCALE *locale, wchar_t *str)
1332{
1333    UNI_TOKEN_LIST *tokens;
1334    UINT i;
1335    // 引数チェック
1336    if (locale == NULL || str == NULL)
1337    {
1338        return false;
1339    }
1340
1341    // トークンの解析
1342    tokens = UniParseToken(str, L" ");
1343    if (tokens->NumTokens != 18)
1344    {
1345        UniFreeToken(tokens);
1346        return false;
1347    }
1348
1349    // 構造体にセット
1350    Zero(locale, sizeof(LOCALE));
1351    COPY_LOCALE_STR(locale->YearStr, sizeof(locale->YearStr), tokens->Token[0]);
1352    COPY_LOCALE_STR(locale->MonthStr, sizeof(locale->MonthStr), tokens->Token[1]);
1353    COPY_LOCALE_STR(locale->DayStr, sizeof(locale->DayStr), tokens->Token[2]);
1354    COPY_LOCALE_STR(locale->HourStr, sizeof(locale->HourStr), tokens->Token[3]);
1355    COPY_LOCALE_STR(locale->MinuteStr, sizeof(locale->MinuteStr), tokens->Token[4]);
1356    COPY_LOCALE_STR(locale->SecondStr, sizeof(locale->SecondStr), tokens->Token[5]);
1357
1358    for (i = 0;i < 7;i++)
1359    {
1360        COPY_LOCALE_STR(locale->DayOfWeek[i], sizeof(locale->DayOfWeek[i]),
1361            tokens->Token[6 + i]);
1362    }
1363
1364    COPY_LOCALE_STR(locale->SpanDay, sizeof(locale->SpanDay), tokens->Token[13]);
1365    COPY_LOCALE_STR(locale->SpanHour, sizeof(locale->SpanHour), tokens->Token[14]);
1366    COPY_LOCALE_STR(locale->SpanMinute, sizeof(locale->SpanMinute), tokens->Token[15]);
1367    COPY_LOCALE_STR(locale->SpanSecond, sizeof(locale->SpanSecond), tokens->Token[16]);
1368
1369    COPY_LOCALE_STR(locale->Unknown, sizeof(locale->Unknown), tokens->Token[17]);
1370
1371    UniFreeToken(tokens);
1372    return true;
1373}
1374
1375// tm を SYSTEMTIME に変換
1376void TmToSystem(SYSTEMTIME *st, struct tm *t)
1377{
1378    struct tm tmp;
1379    // 引数チェック
1380    if (st == NULL || t == NULL)
1381    {
1382        return;
1383    }
1384
1385    Copy(&tmp, t, sizeof(struct tm));
1386    NormalizeTm(&tmp);
1387
1388    Zero(st, sizeof(SYSTEMTIME));
1389    st->wYear = MAKESURE(tmp.tm_year + 1900, 1970, 2037);
1390    st->wMonth = MAKESURE(tmp.tm_mon + 1, 1, 12);
1391    st->wDay = MAKESURE(tmp.tm_mday, 1, 31);
1392    st->wDayOfWeek = MAKESURE(tmp.tm_wday, 0, 6);
1393    st->wHour = MAKESURE(tmp.tm_hour, 0, 23);
1394    st->wMinute = MAKESURE(tmp.tm_min, 0, 59);
1395    st->wSecond = MAKESURE(tmp.tm_sec, 0, 59);
1396    st->wMilliseconds = 0;
1397}
1398
1399// SYSTEMTIME を tm に変換
1400void SystemToTm(struct tm *t, SYSTEMTIME *st)
1401{
1402    // 引数チェック
1403    if (t == NULL || st == NULL)
1404    {
1405        return;
1406    }
1407
1408    Zero(t, sizeof(struct tm));
1409    t->tm_year = MAKESURE(st->wYear, 1970, 2037) - 1900;
1410    t->tm_mon = MAKESURE(st->wMonth, 1, 12) - 1;
1411    t->tm_mday = MAKESURE(st->wDay, 1, 31);
1412    t->tm_hour = MAKESURE(st->wHour, 0, 23);
1413    t->tm_min = MAKESURE(st->wMinute, 0, 59);
1414    t->tm_sec = MAKESURE(st->wSecond, 0, 59);
1415
1416    t->tm_isdst = -1;
1417    NormalizeTm(t);
1418}
1419
1420// time_t を SYSTEMTIME に変換
1421void TimeToSystem(SYSTEMTIME *st, time_t t)
1422{
1423    struct tm tmp;
1424    // 引数チェック
1425    if (st == NULL)
1426    {
1427        return;
1428    }
1429
1430    TimeToTm(&tmp, t);
1431    TmToSystem(st, &tmp);
1432}
1433
1434// SYSTEMTIME を time_t に変換
1435time_t SystemToTime(SYSTEMTIME *st)
1436{
1437    struct tm t;
1438    // 引数チェック
1439    if (st == NULL)
1440    {
1441        return 0;
1442    }
1443
1444    SystemToTm(&t, st);
1445    return TmToTime(&t);
1446}
1447
1448// tm を time_t に変換
1449time_t TmToTime(struct tm *t)
1450{
1451    time_t tmp;
1452    // 引数チェック
1453    if (t == NULL)
1454    {
1455        return 0;
1456    }
1457
1458    tmp = c_mkgmtime(t);
1459    if (tmp == (time_t)-1)
1460    {
1461        return 0;
1462    }
1463    return tmp;
1464}
1465
1466// time_t を tm に変換
1467void TimeToTm(struct tm *t, time_t time)
1468{
1469    struct tm *ret;
1470    // 引数チェック
1471    if (t == NULL)
1472    {
1473        return;
1474    }
1475
1476#ifndef OS_UNIX
1477    ret = gmtime(&time);
1478#else   // OS_UNIX
1479    ret = malloc(sizeof(struct tm));
1480    memset(ret, 0, sizeof(ret));
1481    gmtime_r(&time, ret);
1482#endif  // OS_UNIX
1483
1484    if (ret == NULL)
1485    {
1486        Zero(t, sizeof(struct tm));
1487    }
1488    else
1489    {
1490        Copy(t, ret, sizeof(struct tm));
1491    }
1492
1493#ifdef  OS_UNIX
1494    free(ret);
1495#endif  // OS_UNIX
1496}
1497
1498// tm を正規化
1499void NormalizeTm(struct tm *t)
1500{
1501    struct tm *ret;
1502    time_t tmp;
1503    // 引数チェック
1504    if (t == NULL)
1505    {
1506        return;
1507    }
1508
1509    tmp = c_mkgmtime(t);
1510    if (tmp == (time_t)-1)
1511    {
1512        return;
1513    }
1514
1515#ifndef OS_UNIX
1516    ret = gmtime(&tmp);
1517#else   // OS_UNIX
1518    ret = malloc(sizeof(struct tm));
1519    memset(ret, 0, sizeof(ret));
1520    gmtime_r(&tmp, ret);
1521#endif  // OS_UNIX
1522
1523    if (ret == NULL)
1524    {
1525        Zero(t, sizeof(struct tm));
1526    }
1527    else
1528    {
1529        Copy(t, ret, sizeof(struct tm));
1530    }
1531
1532#ifdef  OS_UNIX
1533    free(ret);
1534#endif  // OS_UNIX
1535}
1536
1537// SYSTEMTIME を正規化
1538void NormalizeSystem(SYSTEMTIME *st)
1539{
1540    UINT64 sec64;
1541    // 引数チェック
1542    if (st == NULL)
1543    {
1544        return;
1545    }
1546
1547    sec64 = SystemToUINT64(st);
1548    UINT64ToSystem(st, sec64);
1549}
1550
1551// 64bit ローカル時刻をシステム時刻に変換
1552UINT64 LocalToSystem64(UINT64 t)
1553{
1554    SYSTEMTIME st;
1555    UINT64ToSystem(&st, t);
1556    LocalToSystem(&st, &st);
1557    return SystemToUINT64(&st);
1558}
1559
1560// 64bit システム時刻をローカル時刻に変換
1561UINT64 SystemToLocal64(UINT64 t)
1562{
1563    SYSTEMTIME st;
1564    UINT64ToSystem(&st, t);
1565    SystemToLocal(&st, &st);
1566    return SystemToUINT64(&st);
1567}
1568
1569// ローカル時刻をシステム時刻に変換
1570void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local)
1571{
1572    UINT64 sec64;
1573    // 引数チェック
1574    if (local == NULL || system == NULL)
1575    {
1576        return;
1577    }
1578
1579    sec64 = (UINT64)((INT64)SystemToUINT64(local) - GetTimeDiffEx(local, true));
1580    UINT64ToSystem(system, sec64);
1581}
1582
1583// システム時刻をローカル時刻に変換
1584void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system)
1585{
1586    UINT64 sec64;
1587    // 引数チェック
1588    if (local == NULL || system == NULL)
1589    {
1590        return;
1591    }
1592
1593    sec64 = (UINT64)((INT64)SystemToUINT64(system) + GetTimeDiffEx(system, false));
1594    UINT64ToSystem(local, sec64);
1595}
1596
1597// 指定時刻をベースにしてシステム時刻とローカル時刻との間の時差を取得
1598INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
1599{
1600    time_t tmp;
1601    struct tm t1, t2;
1602    SYSTEMTIME snow;
1603    struct tm now;
1604    SYSTEMTIME s1, s2;
1605    INT64 ret;
1606
1607    Copy(&snow, basetime, sizeof(SYSTEMTIME));
1608
1609    SystemToTm(&now, &snow);
1610    if (local_time == false)
1611    {
1612        tmp = c_mkgmtime(&now);
1613    }
1614    else
1615    {
1616        tmp = mktime(&now);
1617    }
1618
1619    if (tmp == (time_t)-1)
1620    {
1621        return 0;
1622    }
1623
1624    Copy(&t1, localtime(&tmp), sizeof(struct tm));
1625    Copy(&t2, gmtime(&tmp), sizeof(struct tm));
1626    TmToSystem(&s1, &t1);
1627    TmToSystem(&s2, &t2);
1628
1629    ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
1630
1631    return ret;
1632}
1633
1634// システム時刻とローカル時刻との間の時差を取得
1635INT64 GetTimeDiff()
1636{
1637    time_t tmp;
1638    struct tm t1, t2;
1639    SYSTEMTIME snow;
1640    struct tm now;
1641    SYSTEMTIME s1, s2;
1642    INT64 ret;
1643
1644    static INT64 cache = INFINITE;
1645
1646    if (cache != INFINITE)
1647    {
1648        // 1 度測定したらキャッシュデータを返す
1649        return cache;
1650    }
1651
1652    SystemTime(&snow);
1653    SystemToTm(&now, &snow);
1654    tmp = c_mkgmtime(&now);
1655    if (tmp == (time_t)-1)
1656    {
1657        return 0;
1658    }
1659
1660    Copy(&t1, localtime(&tmp), sizeof(struct tm));
1661    Copy(&t2, gmtime(&tmp), sizeof(struct tm));
1662    TmToSystem(&s1, &t1);
1663    TmToSystem(&s2, &t2);
1664
1665    cache = ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
1666
1667    return ret;
1668}
1669
1670// UINT64 を SYSTEMTIME に変換
1671void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64)
1672{
1673    UINT64 tmp64;
1674    UINT sec, millisec;
1675    time_t time;
1676    // 引数チェック
1677    if (st == NULL)
1678    {
1679        return;
1680    }
1681
1682    sec64 = SafeTime64(sec64 + 32400000ULL);
1683    tmp64 = sec64 / (UINT64)1000;
1684    millisec = (UINT)(sec64 - tmp64 * (UINT64)1000);
1685    sec = (UINT)tmp64;
1686    time = (time_t)sec;
1687    TimeToSystem(st, time);
1688    st->wMilliseconds = (WORD)millisec;
1689}
1690
1691// SYSTEMTIME を UINT64 に変換
1692UINT64 SystemToUINT64(SYSTEMTIME *st)
1693{
1694    UINT64 sec64;
1695    time_t time;
1696    // 引数チェック
1697    if (st == NULL)
1698    {
1699        return 0;
1700    }
1701
1702    time = SystemToTime(st);
1703    sec64 = (UINT64)time * (UINT64)1000;
1704    sec64 += st->wMilliseconds;
1705
1706    return sec64 - 32400000ULL;
1707}
1708
1709// ローカル時刻を UINT64 で取得
1710UINT64 LocalTime64()
1711{
1712    SYSTEMTIME s;
1713    LocalTime(&s);
1714    return SystemToUINT64(&s);
1715}
1716
1717// システム時刻を UINT64 で取得
1718UINT64 SystemTime64()
1719{
1720    SYSTEMTIME s;
1721    SystemTime(&s);
1722    return SystemToUINT64(&s);
1723}
1724
1725// ローカル時刻の取得
1726void LocalTime(SYSTEMTIME *st)
1727{
1728    SYSTEMTIME tmp;
1729    // 引数チェック
1730    if (st == NULL)
1731    {
1732        return;
1733    }
1734
1735    SystemTime(&tmp);
1736    SystemToLocal(st, &tmp);
1737}
1738
1739// システム時刻の取得
1740void SystemTime(SYSTEMTIME *st)
1741{
1742    // 引数チェック
1743    if (st == NULL)
1744    {
1745        return;
1746    }
1747
1748    OSGetSystemTime(st);
1749
1750    // KS
1751    KS_INC(KS_GETTIME_COUNT);
1752}
1753
1754/* free mktime function
1755   Copyright 1988, 1989 by David MacKenzie <djm@ai.mit.edu>
1756   and Michael Haertel <mike@ai.mit.edu>
1757   Unlimited distribution permitted provided this copyright notice is
1758   retained and any functional modifications are prominently identified.  */
1759time_t c_mkgmtime(struct tm *tm)
1760{
1761    int years, months, days, hours, minutes, seconds;
1762
1763    years = tm->tm_year + 1900;   /* year - 1900 -> year */
1764    months = tm->tm_mon;          /* 0..11 */
1765    days = tm->tm_mday - 1;       /* 1..31 -> 0..30 */
1766    hours = tm->tm_hour;          /* 0..23 */
1767    minutes = tm->tm_min;         /* 0..59 */
1768    seconds = tm->tm_sec;         /* 0..61 in ANSI C. */
1769
1770    ADJUST_TM(seconds, minutes, 60);
1771    ADJUST_TM(minutes, hours, 60);
1772    ADJUST_TM(hours, days, 24);
1773    ADJUST_TM(months, years, 12);
1774    if (days < 0)
1775        do {
1776            if (--months < 0) {
1777                --years;
1778                months = 11;
1779            }
1780            days += monthlen(months, years);
1781        } while (days < 0);
1782    else
1783        while (days >= monthlen(months, years)) {
1784            days -= monthlen(months, years);
1785            if (++months >= 12) {
1786                ++years;
1787                months = 0;
1788            }
1789        }
1790
1791        /* Restore adjusted values in tm structure */
1792        tm->tm_year = years - 1900;
1793        tm->tm_mon = months;
1794        tm->tm_mday = days + 1;
1795        tm->tm_hour = hours;
1796        tm->tm_min = minutes;
1797        tm->tm_sec = seconds;
1798
1799        /* Set `days' to the number of days into the year. */
1800        days += ydays[months] + (months > 1 && leap (years));
1801        tm->tm_yday = days;
1802
1803        /* Now calculate `days' to the number of days since Jan 1, 1970. */
1804        days = (unsigned)days + 365 * (unsigned)(years - 1970) +
1805            (unsigned)(nleap (years));
1806        tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
1807        tm->tm_isdst = 0;
1808
1809        if (years < 1970)
1810            return (time_t)-1;
1811
1812#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
1813#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
1814        if (years > TM_YEAR_MAX ||
1815            (years == TM_YEAR_MAX &&
1816            (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
1817            (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
1818            (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
1819            (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
1820            (hours > TM_HOUR_MAX ||
1821            (hours == TM_HOUR_MAX &&
1822            (minutes > TM_MIN_MAX ||
1823            (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
1824            return (time_t)-1;
1825#endif
1826#endif
1827
1828        return (time_t)(86400L * (unsigned long)(unsigned)days +
1829            3600L * (unsigned long)hours +
1830            (unsigned long)(60 * minutes + seconds));
1831}
1832
1833// システムタイマの取得
1834UINT Tick()
1835{
1836    // KS
1837    KS_INC(KS_GETTICK_COUNT);
1838    return OSGetTick();
1839}
1840
1841// スレッドのスリープ
1842void SleepThread(UINT time)
1843{
1844    // KS
1845    KS_INC(KS_SLEEPTHREAD_COUNT);
1846
1847    OSSleep(time);
1848}
1849
1850// イールド
1851void YieldCpu()
1852{
1853    OSYield();
1854}
1855
1856// システム停止 (異常終了)
1857void AbortExit()
1858{
1859#ifdef  OS_WIN32
1860    _exit(1);
1861#else   // OS_WIN32
1862
1863#ifdef  RLIMIT_CORE
1864    UnixSetResourceLimit(RLIMIT_CORE, 0);
1865#endif  // RLIMIT_CORE
1866
1867    abort();
1868#endif  // OS_WIN32
1869}
1870
1871
1872void AbortExitEx(char *msg)
1873{
1874    FILE *f;
1875    // 引数チェック
1876    if (msg == NULL)
1877    {
1878        msg = "Unknown Error";
1879    }
1880
1881    f = fopen("abort_error_log.txt", "w");
1882    if (f != NULL)
1883    {
1884        fwrite(msg, 1, strlen(msg), f);
1885        fclose(f);
1886    }
1887
1888    fputs("Fatal Error: ", stdout);
1889    fputs(msg, stdout);
1890    fputs("\r\n", stdout);
1891
1892#ifdef  OS_WIN32
1893    _exit(1);
1894#else   // OS_WIN32
1895
1896#ifdef  RLIMIT_CORE
1897    UnixSetResourceLimit(RLIMIT_CORE, 0);
1898#endif  // RLIMIT_CORE
1899
1900    abort();
1901#endif  // OS_WIN32
1902}
1903
Note: See TracBrowser for help on using the repository browser.