diff --git a/docs/en/13-operation/01-pkg-install.md b/docs/en/13-operation/01-pkg-install.md
index 53da672daa..d7713b943f 100644
--- a/docs/en/13-operation/01-pkg-install.md
+++ b/docs/en/13-operation/01-pkg-install.md
@@ -1,12 +1,12 @@
---
-title: Install & Uninstall
+title: Install and Uninstall
description: Install, Uninstall, Start, Stop and Upgrade
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
-TDengine community version provides deb and rpm packages for users to choose from, based on their system environment. The deb package supports Debian, Ubuntu and derivative systems. The rpm package supports CentOS, RHEL, SUSE and derivative systems. Furthermore, a tar.gz package is provided for TDengine Enterprise customers.
+This document gives more information about installing, uninstalling, and upgrading TDengine.
## Install
@@ -56,7 +56,7 @@ Removing taostools (2.1.2) ...
Deb package of TDengine can be uninstalled as below:
-```bash
+```
$ sudo dpkg -r tdengine
(Reading database ... 137504 files and directories currently installed.)
Removing tdengine (3.0.0.0) ...
@@ -110,109 +110,57 @@ Start to uninstall taos tools ...
taos tools is uninstalled successfully!
```
+
+
+Run C:\TDengine\unins000.exe to uninstall TDengine on a Windows system.
-:::note
+:::info
-- We strongly recommend not to use multiple kinds of installation packages on a single host TDengine.
-- After deb package is installed, if the installation directory is removed manually, uninstall or reinstall will not work. This issue can be resolved by using the command below which cleans up TDengine package information. You can then reinstall if needed.
+- We strongly recommend not to use multiple kinds of installation packages on a single host TDengine. The packages may affect each other and cause errors.
-```bash
- $ sudo rm -f /var/lib/dpkg/info/tdengine*
-```
+- After deb package is installed, if the installation directory is removed manually, uninstall or reinstall will not work. This issue can be resolved by using the command below which cleans up TDengine package information.
-- After rpm package is installed, if the installation directory is removed manually, uninstall or reinstall will not work. This issue can be resolved by using the command below which cleans up TDengine package information. You can then reinstall if needed.
+ ```
+ $ sudo rm -f /var/lib/dpkg/info/tdengine*
+ ```
-```bash
- $ sudo rpm -e --noscripts tdengine
-```
+You can then reinstall if needed.
+
+- After rpm package is installed, if the installation directory is removed manually, uninstall or reinstall will not work. This issue can be resolved by using the command below which cleans up TDengine package information.
+
+ ```
+ $ sudo rpm -e --noscripts tdengine
+ ```
+
+You can then reinstall if needed.
:::
-## Installation Directory
-
-TDengine is installed at /usr/local/taos if successful.
-
-```bash
-$ cd /usr/local/taos
-$ ll
-$ ll
-total 28
-drwxr-xr-x 7 root root 4096 Feb 22 09:34 ./
-drwxr-xr-x 12 root root 4096 Feb 22 09:34 ../
-drwxr-xr-x 2 root root 4096 Feb 22 09:34 bin/
-drwxr-xr-x 2 root root 4096 Feb 22 09:34 cfg/
-lrwxrwxrwx 1 root root 13 Feb 22 09:34 data -> /var/lib/taos/
-drwxr-xr-x 2 root root 4096 Feb 22 09:34 driver/
-drwxr-xr-x 10 root root 4096 Feb 22 09:34 examples/
-drwxr-xr-x 2 root root 4096 Feb 22 09:34 include/
-lrwxrwxrwx 1 root root 13 Feb 22 09:34 log -> /var/log/taos/
-```
-
-During the installation process:
-
-- Configuration directory, data directory, and log directory are created automatically if they don't exist
-- The default configuration file is located at /etc/taos/taos.cfg, which is a copy of /usr/local/taos/cfg/taos.cfg
-- The default data directory is /var/lib/taos, which is a soft link to /usr/local/taos/data
-- The default log directory is /var/log/taos, which is a soft link to /usr/local/taos/log
-- The executables at /usr/local/taos/bin are linked to /usr/bin
-- The DLL files at /usr/local/taos/driver are linked to /usr/lib
-- The header files at /usr/local/taos/include are linked to /usr/include
-
-:::note
+Uninstalling and Modifying Files
- When TDengine is uninstalled, the configuration /etc/taos/taos.cfg, data directory /var/lib/taos, log directory /var/log/taos are kept. They can be deleted manually with caution, because data can't be recovered. Please follow data integrity, security, backup or relevant SOPs before deleting any data.
+
- When reinstalling TDengine, if the default configuration file /etc/taos/taos.cfg exists, it will be kept and the configuration file in the installation package will be renamed to taos.cfg.orig and stored at /usr/local/taos/cfg to be used as configuration sample. Otherwise the configuration file in the installation package will be installed to /etc/taos/taos.cfg and used.
-## Start and Stop
-
-Linux system services `systemd`, `systemctl` or `service` are used to start, stop and restart TDengine. The server process of TDengine is `taosd`, which is started automatically after the Linux system is started. System operators can use `systemd`, `systemctl` or `service` to start, stop or restart TDengine server.
-
-For example, if using `systemctl` , the commands to start, stop, restart and check TDengine server are below:
-
-- Start server:`systemctl start taosd`
-
-- Stop server:`systemctl stop taosd`
-
-- Restart server:`systemctl restart taosd`
-
-- Check server status:`systemctl status taosd`
-
-Another component named as `taosAdapter` is to provide HTTP service for TDengine, it should be started and stopped using `systemctl`.
-
-If the server process is OK, the output of `systemctl status` is like below:
-
-```
-Active: active (running)
-```
-
-Otherwise, the output is as below:
-
-```
-Active: inactive (dead)
-```
## Upgrade
-
There are two aspects in upgrade operation: upgrade installation package and upgrade a running server.
To upgrade a package, follow the steps mentioned previously to first uninstall the old version then install the new version.
Upgrading a running server is much more complex. First please check the version number of the old version and the new version. The version number of TDengine consists of 4 sections, only if the first 3 sections match can the old version be upgraded to the new version. The steps of upgrading a running server are as below:
-
- Stop inserting data
- Make sure all data is persisted to disk
-- Make some simple queries (Such as total rows in stables, tables and so on. Note down the values. Follow best practices and relevant SOPs.)
- Stop the cluster of TDengine
- Uninstall old version and install new version
- Start the cluster of TDengine
-- Execute simple queries, such as the ones executed prior to installing the new package, to make sure there is no data loss
+- Execute simple queries, such as the ones executed prior to installing the new package, to make sure there is no data loss
- Run some simple data insertion statements to make sure the cluster works well
- Restore business services
:::warning
-
TDengine doesn't guarantee any lower version is compatible with the data generated by a higher version, so it's never recommended to downgrade the version.
:::
diff --git a/docs/en/14-reference/12-config/index.md b/docs/en/14-reference/12-config/index.md
index 9cb2ef5125..02921c3f6a 100644
--- a/docs/en/14-reference/12-config/index.md
+++ b/docs/en/14-reference/12-config/index.md
@@ -380,6 +380,35 @@ The charset that takes effect is UTF-8.
| Unit | bytes |
| Value Range | 0: always compress; >0: only compress when the size of any column data exceeds the threshold; -1: always uncompress |
| Default Value | -1 |
+| Default Value | -1 |
+| Note | available from version 2.3.0.0 | |
+
+## Continuous Query Parameters |
+
+### minSlidingTime
+
+| Attribute | Description |
+| ------------- | -------------------------------------------------------- |
+| Applicable | Server Only |
+| Meaning | Minimum sliding time of time window |
+| Unit | millisecond or microsecond , depending on time precision |
+| Value Range | 10-1000000 |
+| Default Value | 10 |
+
+### minIntervalTime
+
+| Attribute | Description |
+| ------------- | --------------------------- |
+| Applicable | Server Only |
+| Meaning | Minimum size of time window |
+| Unit | millisecond |
+| Value Range | 1-1000000 |
+| Default Value | 10 |
+
+:::info
+To prevent system resource from being exhausted by multiple concurrent streams, a random delay is applied on each stream automatically. `maxFirstStreamCompDelay` is the maximum delay time before a continuous query is started the first time. `streamCompDelayRatio` is the ratio for calculating delay time, with the size of the time window as base. `maxStreamCompDelay` is the maximum delay time. The actual delay time is a random time not bigger than `maxStreamCompDelay`. If a continuous query fails, `retryStreamComDelay` is the delay time before retrying it, also not bigger than `maxStreamCompDelay`.
+
+:::
## Log Parameters
diff --git a/include/os/osSemaphore.h b/include/os/osSemaphore.h
index 2a3a2e64b6..e52da96f01 100644
--- a/include/os/osSemaphore.h
+++ b/include/os/osSemaphore.h
@@ -1,74 +1,74 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#ifndef _TD_OS_SEMPHONE_H_
-#define _TD_OS_SEMPHONE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include
-
-#if defined(_TD_DARWIN_64)
-#include
-// typedef struct tsem_s *tsem_t;
-typedef dispatch_semaphore_t tsem_t;
-
-int tsem_init(tsem_t *sem, int pshared, unsigned int value);
-int tsem_wait(tsem_t *sem);
-int tsem_timewait(tsem_t *sim, int64_t nanosecs);
-int tsem_post(tsem_t *sem);
-int tsem_destroy(tsem_t *sem);
-
-#else
-
-#define tsem_t sem_t
-#define tsem_init sem_init
-int tsem_wait(tsem_t *sem);
-int tsem_timewait(tsem_t *sim, int64_t nanosecs);
-#define tsem_post sem_post
-#define tsem_destroy sem_destroy
-
-#endif
-
-#if defined(_TD_DARWIN_64)
-// #define TdThreadRwlock TdThreadMutex
-// #define taosThreadRwlockInit(lock, NULL) taosThreadMutexInit(lock, NULL)
-// #define taosThreadRwlockDestroy(lock) taosThreadMutexDestroy(lock)
-// #define taosThreadRwlockWrlock(lock) taosThreadMutexLock(lock)
-// #define taosThreadRwlockRdlock(lock) taosThreadMutexLock(lock)
-// #define taosThreadRwlockUnlock(lock) taosThreadMutexUnlock(lock)
-
-// #define TdThreadSpinlock TdThreadMutex
-// #define taosThreadSpinInit(lock, NULL) taosThreadMutexInit(lock, NULL)
-// #define taosThreadSpinDestroy(lock) taosThreadMutexDestroy(lock)
-// #define taosThreadSpinLock(lock) taosThreadMutexLock(lock)
-// #define taosThreadSpinUnlock(lock) taosThreadMutexUnlock(lock)
-#endif
-
-bool taosCheckPthreadValid(TdThread thread);
-int64_t taosGetSelfPthreadId();
-int64_t taosGetPthreadId(TdThread thread);
-void taosResetPthread(TdThread *thread);
-bool taosComparePthread(TdThread first, TdThread second);
-int32_t taosGetPId();
-int32_t taosGetAppName(char *name, int32_t *len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*_TD_OS_SEMPHONE_H_*/
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _TD_OS_SEMPHONE_H_
+#define _TD_OS_SEMPHONE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+#if defined(_TD_DARWIN_64)
+#include
+// typedef struct tsem_s *tsem_t;
+typedef dispatch_semaphore_t tsem_t;
+
+int tsem_init(tsem_t *sem, int pshared, unsigned int value);
+int tsem_wait(tsem_t *sem);
+int tsem_timewait(tsem_t *sim, int64_t nanosecs);
+int tsem_post(tsem_t *sem);
+int tsem_destroy(tsem_t *sem);
+
+#else
+
+#define tsem_t sem_t
+#define tsem_init sem_init
+int tsem_wait(tsem_t *sem);
+int tsem_timewait(tsem_t *sim, int64_t nanosecs);
+#define tsem_post sem_post
+#define tsem_destroy sem_destroy
+
+#endif
+
+#if defined(_TD_DARWIN_64)
+// #define TdThreadRwlock TdThreadMutex
+// #define taosThreadRwlockInit(lock, NULL) taosThreadMutexInit(lock, NULL)
+// #define taosThreadRwlockDestroy(lock) taosThreadMutexDestroy(lock)
+// #define taosThreadRwlockWrlock(lock) taosThreadMutexLock(lock)
+// #define taosThreadRwlockRdlock(lock) taosThreadMutexLock(lock)
+// #define taosThreadRwlockUnlock(lock) taosThreadMutexUnlock(lock)
+
+// #define TdThreadSpinlock TdThreadMutex
+// #define taosThreadSpinInit(lock, NULL) taosThreadMutexInit(lock, NULL)
+// #define taosThreadSpinDestroy(lock) taosThreadMutexDestroy(lock)
+// #define taosThreadSpinLock(lock) taosThreadMutexLock(lock)
+// #define taosThreadSpinUnlock(lock) taosThreadMutexUnlock(lock)
+#endif
+
+bool taosCheckPthreadValid(TdThread thread);
+int64_t taosGetSelfPthreadId();
+int64_t taosGetPthreadId(TdThread thread);
+void taosResetPthread(TdThread *thread);
+bool taosComparePthread(TdThread first, TdThread second);
+int32_t taosGetPId();
+int32_t taosGetAppName(char *name, int32_t *len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TD_OS_SEMPHONE_H_*/
diff --git a/source/os/src/osSemaphore.c b/source/os/src/osSemaphore.c
index a95503b5e5..8cc6f0ef2e 100644
--- a/source/os/src/osSemaphore.c
+++ b/source/os/src/osSemaphore.c
@@ -1,531 +1,531 @@
-/*
- * Copyright (c) 2019 TAOS Data, Inc.
- *
- * This program is free software: you can use, redistribute, and/or modify
- * it under the terms of the GNU Affero General Public License, version 3
- * or later ("AGPL"), as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-#define ALLOW_FORBID_FUNC
-#define _DEFAULT_SOURCE
-#include "os.h"
-#include "pthread.h"
-#include "tdef.h"
-
-#ifdef WINDOWS
-
-/*
- * windows implementation
- */
-
-#include
-
-bool taosCheckPthreadValid(TdThread thread) { return thread.p != NULL; }
-
-void taosResetPthread(TdThread* thread) { thread->p = 0; }
-
-int64_t taosGetPthreadId(TdThread thread) {
-#ifdef PTW32_VERSION
- return pthread_getw32threadid_np(thread);
-#else
- return (int64_t)thread;
-#endif
-}
-
-int64_t taosGetSelfPthreadId() { return GetCurrentThreadId(); }
-
-bool taosComparePthread(TdThread first, TdThread second) { return first.p == second.p; }
-
-int32_t taosGetPId() { return GetCurrentProcessId(); }
-
-int32_t taosGetAppName(char* name, int32_t* len) {
- char filepath[1024] = {0};
-
- GetModuleFileName(NULL, filepath, MAX_PATH);
- char* sub = strrchr(filepath, '.');
- if (sub != NULL) {
- *sub = '\0';
- }
- char* end = strrchr(filepath, TD_DIRSEP[0]);
- if (end == NULL) {
- end = filepath;
- }
-
- tstrncpy(name, end, TSDB_APP_NAME_LEN);
-
- if (len != NULL) {
- *len = (int32_t)strlen(end);
- }
-
- return 0;
-}
-
-int32_t tsem_wait(tsem_t* sem) {
- int ret = 0;
- do {
- ret = sem_wait(sem);
- } while (ret != 0 && errno == EINTR);
- return ret;
-}
-
-int32_t tsem_timewait(tsem_t* sem, int64_t nanosecs) {
- struct timespec ts, rel;
- FILETIME ft_before, ft_after;
- int rc;
-
- rel.tv_sec = 0;
- rel.tv_nsec = nanosecs;
-
- GetSystemTimeAsFileTime(&ft_before);
- // errno = 0;
- rc = sem_timedwait(sem, pthread_win32_getabstime_np(&ts, &rel));
-
- /* This should have timed out */
- // assert(errno == ETIMEDOUT);
- // assert(rc != 0);
- // GetSystemTimeAsFileTime(&ft_after);
- // // We specified a non-zero wait. Time must advance.
- // if (ft_before.dwLowDateTime == ft_after.dwLowDateTime && ft_before.dwHighDateTime == ft_after.dwHighDateTime)
- // {
- // printf("nanoseconds: %d, rc: %d, code:0x%x. before filetime: %d, %d; after filetime: %d, %d\n",
- // nanosecs, rc, errno,
- // (int)ft_before.dwLowDateTime, (int)ft_before.dwHighDateTime,
- // (int)ft_after.dwLowDateTime, (int)ft_after.dwHighDateTime);
- // printf("time must advance during sem_timedwait.");
- // return 1;
- // }
- return rc;
-}
-
-#elif defined(_TD_DARWIN_64)
-
-/*
- * darwin implementation
- */
-
-#include
-
-// #define SEM_USE_PTHREAD
-// #define SEM_USE_POSIX
-// #define SEM_USE_SEM
-
-// #ifdef SEM_USE_SEM
-// #include
-// #include
-// #include
-// #include
-
-// static TdThread sem_thread;
-// static TdThreadOnce sem_once;
-// static task_t sem_port;
-// static volatile int sem_inited = 0;
-// static semaphore_t sem_exit;
-
-// static void *sem_thread_routine(void *arg) {
-// (void)arg;
-// setThreadName("sem_thrd");
-
-// sem_port = mach_task_self();
-// kern_return_t ret = semaphore_create(sem_port, &sem_exit, SYNC_POLICY_FIFO, 0);
-// if (ret != KERN_SUCCESS) {
-// fprintf(stderr, "==%s[%d]%s()==failed to create sem_exit\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__);
-// sem_inited = -1;
-// return NULL;
-// }
-// sem_inited = 1;
-// semaphore_wait(sem_exit);
-// return NULL;
-// }
-
-// static void once_init(void) {
-// int r = 0;
-// r = taosThreadCreate(&sem_thread, NULL, sem_thread_routine, NULL);
-// if (r) {
-// fprintf(stderr, "==%s[%d]%s()==failed to create thread\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__);
-// return;
-// }
-// while (sem_inited == 0) {
-// ;
-// }
-// }
-// #endif
-
-// struct tsem_s {
-// #ifdef SEM_USE_PTHREAD
-// TdThreadMutex lock;
-// TdThreadCond cond;
-// volatile int64_t val;
-// #elif defined(SEM_USE_POSIX)
-// size_t id;
-// sem_t *sem;
-// #elif defined(SEM_USE_SEM)
-// semaphore_t sem;
-// #else // SEM_USE_PTHREAD
-// dispatch_semaphore_t sem;
-// #endif // SEM_USE_PTHREAD
-
-// volatile unsigned int valid : 1;
-// };
-
-// int tsem_init(tsem_t *sem, int pshared, unsigned int value) {
-// // fprintf(stderr, "==%s[%d]%s():[%p]==creating\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
-// if (*sem) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==already initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// struct tsem_s *p = (struct tsem_s *)taosMemoryCalloc(1, sizeof(*p));
-// if (!p) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==out of memory\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
-// abort();
-// }
-
-// #ifdef SEM_USE_PTHREAD
-// int r = taosThreadMutexInit(&p->lock, NULL);
-// do {
-// if (r) break;
-// r = taosThreadCondInit(&p->cond, NULL);
-// if (r) {
-// taosThreadMutexDestroy(&p->lock);
-// break;
-// }
-// p->val = value;
-// } while (0);
-// if (r) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
-// abort();
-// }
-// #elif defined(SEM_USE_POSIX)
-// static size_t tick = 0;
-// do {
-// size_t id = atomic_add_fetch_64(&tick, 1);
-// if (id == SEM_VALUE_MAX) {
-// atomic_store_64(&tick, 0);
-// id = 0;
-// }
-// char name[NAME_MAX - 4];
-// snprintf(name, sizeof(name), "/t" PRId64, id);
-// p->sem = sem_open(name, O_CREAT | O_EXCL, pshared, value);
-// p->id = id;
-// if (p->sem != SEM_FAILED) break;
-// int e = errno;
-// if (e == EEXIST) continue;
-// if (e == EINTR) continue;
-// fprintf(stderr, "==%s[%d]%s():[%p]==not created[%d]%s\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem,
-// e, strerror(e));
-// abort();
-// } while (p->sem == SEM_FAILED);
-// #elif defined(SEM_USE_SEM)
-// taosThreadOnce(&sem_once, once_init);
-// if (sem_inited != 1) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal resource init failed\n", taosDirEntryBaseName(__FILE__), __LINE__,
-// __func__, sem);
-// errno = ENOMEM;
-// return -1;
-// }
-// kern_return_t ret = semaphore_create(sem_port, &p->sem, SYNC_POLICY_FIFO, value);
-// if (ret != KERN_SUCCESS) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==semophore_create failed\n", taosDirEntryBaseName(__FILE__), __LINE__,
-// __func__,
-// sem);
-// // we fail-fast here, because we have less-doc about semaphore_create for the moment
-// abort();
-// }
-// #else // SEM_USE_PTHREAD
-// p->sem = dispatch_semaphore_create(value);
-// if (p->sem == NULL) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
-// abort();
-// }
-// #endif // SEM_USE_PTHREAD
-
-// p->valid = 1;
-
-// *sem = p;
-
-// return 0;
-// }
-
-// int tsem_wait(tsem_t *sem) {
-// if (!*sem) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
-// abort();
-// }
-// struct tsem_s *p = *sem;
-// if (!p->valid) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem); abort();
-// }
-// #ifdef SEM_USE_PTHREAD
-// if (taosThreadMutexLock(&p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// p->val -= 1;
-// if (p->val < 0) {
-// if (taosThreadCondWait(&p->cond, &p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__,
-// __func__,
-// sem);
-// abort();
-// }
-// }
-// if (taosThreadMutexUnlock(&p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// return 0;
-// #elif defined(SEM_USE_POSIX)
-// return sem_wait(p->sem);
-// #elif defined(SEM_USE_SEM)
-// return semaphore_wait(p->sem);
-// #else // SEM_USE_PTHREAD
-// return dispatch_semaphore_wait(p->sem, DISPATCH_TIME_FOREVER);
-// #endif // SEM_USE_PTHREAD
-// }
-
-// int tsem_post(tsem_t *sem) {
-// if (!*sem) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
-// abort();
-// }
-// struct tsem_s *p = *sem;
-// if (!p->valid) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem); abort();
-// }
-// #ifdef SEM_USE_PTHREAD
-// if (taosThreadMutexLock(&p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// p->val += 1;
-// if (p->val <= 0) {
-// if (taosThreadCondSignal(&p->cond)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__,
-// __func__,
-// sem);
-// abort();
-// }
-// }
-// if (taosThreadMutexUnlock(&p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// return 0;
-// #elif defined(SEM_USE_POSIX)
-// return sem_post(p->sem);
-// #elif defined(SEM_USE_SEM)
-// return semaphore_signal(p->sem);
-// #else // SEM_USE_PTHREAD
-// return dispatch_semaphore_signal(p->sem);
-// #endif // SEM_USE_PTHREAD
-// }
-
-// int tsem_destroy(tsem_t *sem) {
-// // fprintf(stderr, "==%s[%d]%s():[%p]==destroying\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
-// if (!*sem) {
-// // fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// // abort();
-// return 0;
-// }
-// struct tsem_s *p = *sem;
-// if (!p->valid) {
-// // fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// // sem); abort();
-// return 0;
-// }
-// #ifdef SEM_USE_PTHREAD
-// if (taosThreadMutexLock(&p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// p->valid = 0;
-// if (taosThreadCondDestroy(&p->cond)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// if (taosThreadMutexUnlock(&p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// if (taosThreadMutexDestroy(&p->lock)) {
-// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem);
-// abort();
-// }
-// #elif defined(SEM_USE_POSIX)
-// char name[NAME_MAX - 4];
-// snprintf(name, sizeof(name), "/t" PRId64, p->id);
-// int r = sem_unlink(name);
-// if (r) {
-// int e = errno;
-// fprintf(stderr, "==%s[%d]%s():[%p]==unlink failed[%d]%s\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
-// sem,
-// e, strerror(e));
-// abort();
-// }
-// #elif defined(SEM_USE_SEM)
-// semaphore_destroy(sem_port, p->sem);
-// #else // SEM_USE_PTHREAD
-// #endif // SEM_USE_PTHREAD
-
-// p->valid = 0;
-// taosMemoryFree(p);
-
-// *sem = NULL;
-// return 0;
-// }
-
-int tsem_init(tsem_t *psem, int flags, unsigned int count) {
- *psem = dispatch_semaphore_create(count);
- if (*psem == NULL) return -1;
- return 0;
-}
-
-int tsem_destroy(tsem_t *psem) {
- return 0;
-}
-
-int tsem_post(tsem_t *psem) {
- if (psem == NULL || *psem == NULL) return -1;
- dispatch_semaphore_signal(*psem);
- return 0;
-}
-
-int tsem_wait(tsem_t *psem) {
- if (psem == NULL || *psem == NULL) return -1;
- dispatch_semaphore_wait(*psem, DISPATCH_TIME_FOREVER);
- return 0;
-}
-
-int tsem_timewait(tsem_t *psem, int64_t nanosecs) {
- if (psem == NULL || *psem == NULL) return -1;
- dispatch_semaphore_wait(*psem, nanosecs);
- return 0;
-}
-
-bool taosCheckPthreadValid(TdThread thread) {
- int32_t ret = taosThreadKill(thread, 0);
- if (ret == ESRCH) return false;
- if (ret == EINVAL) return false;
- // alive
- return true;
-}
-
-int64_t taosGetSelfPthreadId() {
- TdThread thread = taosThreadSelf();
- return (int64_t)thread;
-}
-
-int64_t taosGetPthreadId(TdThread thread) { return (int64_t)thread; }
-
-void taosResetPthread(TdThread *thread) { *thread = NULL; }
-
-bool taosComparePthread(TdThread first, TdThread second) { return taosThreadEqual(first, second) ? true : false; }
-
-int32_t taosGetPId() { return (int32_t)getpid(); }
-
-int32_t taosGetAppName(char *name, int32_t *len) {
- char buf[PATH_MAX + 1];
- buf[0] = '\0';
- proc_name(getpid(), buf, sizeof(buf) - 1);
- buf[PATH_MAX] = '\0';
- size_t n = strlen(buf);
- if (len) *len = n;
- if (name) tstrncpy(name, buf, TSDB_APP_NAME_LEN);
- return 0;
-}
-
-#else
-
-/*
- * linux implementation
- */
-
-#include
-#include
-
-bool taosCheckPthreadValid(TdThread thread) { return thread != 0; }
-
-int64_t taosGetSelfPthreadId() {
- static __thread int id = 0;
- if (id != 0) return id;
- id = syscall(SYS_gettid);
- return id;
-}
-
-int64_t taosGetPthreadId(TdThread thread) { return (int64_t)thread; }
-void taosResetPthread(TdThread* thread) { *thread = 0; }
-bool taosComparePthread(TdThread first, TdThread second) { return first == second; }
-
-int32_t taosGetPId() {
- static int32_t pid;
- if (pid != 0) return pid;
- pid = getpid();
- return pid;
-}
-
-int32_t taosGetAppName(char* name, int32_t* len) {
- const char* self = "/proc/self/exe";
- char path[PATH_MAX] = {0};
-
- if (readlink(self, path, PATH_MAX) <= 0) {
- return -1;
- }
-
- path[PATH_MAX - 1] = 0;
- char* end = strrchr(path, '/');
- if (end == NULL) {
- return -1;
- }
-
- ++end;
-
- tstrncpy(name, end, TSDB_APP_NAME_LEN);
-
- if (len != NULL) {
- *len = strlen(name);
- }
-
- return 0;
-}
-
-int32_t tsem_wait(tsem_t* sem) {
- int ret = 0;
- do {
- ret = sem_wait(sem);
- } while (ret != 0 && errno == EINTR);
- return ret;
-}
-
-int32_t tsem_timewait(tsem_t* sem, int64_t nanosecs) {
- int ret = 0;
-
- struct timespec tv = {
- .tv_sec = 0,
- .tv_nsec = nanosecs,
- };
-
- while ((ret = sem_timedwait(sem, &tv)) == -1 && errno == EINTR) continue;
-
- return ret;
-}
-
-#endif
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#define ALLOW_FORBID_FUNC
+#define _DEFAULT_SOURCE
+#include "os.h"
+#include "pthread.h"
+#include "tdef.h"
+
+#ifdef WINDOWS
+
+/*
+ * windows implementation
+ */
+
+#include
+
+bool taosCheckPthreadValid(TdThread thread) { return thread.p != NULL; }
+
+void taosResetPthread(TdThread* thread) { thread->p = 0; }
+
+int64_t taosGetPthreadId(TdThread thread) {
+#ifdef PTW32_VERSION
+ return pthread_getw32threadid_np(thread);
+#else
+ return (int64_t)thread;
+#endif
+}
+
+int64_t taosGetSelfPthreadId() { return GetCurrentThreadId(); }
+
+bool taosComparePthread(TdThread first, TdThread second) { return first.p == second.p; }
+
+int32_t taosGetPId() { return GetCurrentProcessId(); }
+
+int32_t taosGetAppName(char* name, int32_t* len) {
+ char filepath[1024] = {0};
+
+ GetModuleFileName(NULL, filepath, MAX_PATH);
+ char* sub = strrchr(filepath, '.');
+ if (sub != NULL) {
+ *sub = '\0';
+ }
+ char* end = strrchr(filepath, TD_DIRSEP[0]);
+ if (end == NULL) {
+ end = filepath;
+ }
+
+ tstrncpy(name, end, TSDB_APP_NAME_LEN);
+
+ if (len != NULL) {
+ *len = (int32_t)strlen(end);
+ }
+
+ return 0;
+}
+
+int32_t tsem_wait(tsem_t* sem) {
+ int ret = 0;
+ do {
+ ret = sem_wait(sem);
+ } while (ret != 0 && errno == EINTR);
+ return ret;
+}
+
+int32_t tsem_timewait(tsem_t* sem, int64_t nanosecs) {
+ struct timespec ts, rel;
+ FILETIME ft_before, ft_after;
+ int rc;
+
+ rel.tv_sec = 0;
+ rel.tv_nsec = nanosecs;
+
+ GetSystemTimeAsFileTime(&ft_before);
+ // errno = 0;
+ rc = sem_timedwait(sem, pthread_win32_getabstime_np(&ts, &rel));
+
+ /* This should have timed out */
+ // assert(errno == ETIMEDOUT);
+ // assert(rc != 0);
+ // GetSystemTimeAsFileTime(&ft_after);
+ // // We specified a non-zero wait. Time must advance.
+ // if (ft_before.dwLowDateTime == ft_after.dwLowDateTime && ft_before.dwHighDateTime == ft_after.dwHighDateTime)
+ // {
+ // printf("nanoseconds: %d, rc: %d, code:0x%x. before filetime: %d, %d; after filetime: %d, %d\n",
+ // nanosecs, rc, errno,
+ // (int)ft_before.dwLowDateTime, (int)ft_before.dwHighDateTime,
+ // (int)ft_after.dwLowDateTime, (int)ft_after.dwHighDateTime);
+ // printf("time must advance during sem_timedwait.");
+ // return 1;
+ // }
+ return rc;
+}
+
+#elif defined(_TD_DARWIN_64)
+
+/*
+ * darwin implementation
+ */
+
+#include
+
+// #define SEM_USE_PTHREAD
+// #define SEM_USE_POSIX
+// #define SEM_USE_SEM
+
+// #ifdef SEM_USE_SEM
+// #include
+// #include
+// #include
+// #include
+
+// static TdThread sem_thread;
+// static TdThreadOnce sem_once;
+// static task_t sem_port;
+// static volatile int sem_inited = 0;
+// static semaphore_t sem_exit;
+
+// static void *sem_thread_routine(void *arg) {
+// (void)arg;
+// setThreadName("sem_thrd");
+
+// sem_port = mach_task_self();
+// kern_return_t ret = semaphore_create(sem_port, &sem_exit, SYNC_POLICY_FIFO, 0);
+// if (ret != KERN_SUCCESS) {
+// fprintf(stderr, "==%s[%d]%s()==failed to create sem_exit\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__);
+// sem_inited = -1;
+// return NULL;
+// }
+// sem_inited = 1;
+// semaphore_wait(sem_exit);
+// return NULL;
+// }
+
+// static void once_init(void) {
+// int r = 0;
+// r = taosThreadCreate(&sem_thread, NULL, sem_thread_routine, NULL);
+// if (r) {
+// fprintf(stderr, "==%s[%d]%s()==failed to create thread\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__);
+// return;
+// }
+// while (sem_inited == 0) {
+// ;
+// }
+// }
+// #endif
+
+// struct tsem_s {
+// #ifdef SEM_USE_PTHREAD
+// TdThreadMutex lock;
+// TdThreadCond cond;
+// volatile int64_t val;
+// #elif defined(SEM_USE_POSIX)
+// size_t id;
+// sem_t *sem;
+// #elif defined(SEM_USE_SEM)
+// semaphore_t sem;
+// #else // SEM_USE_PTHREAD
+// dispatch_semaphore_t sem;
+// #endif // SEM_USE_PTHREAD
+
+// volatile unsigned int valid : 1;
+// };
+
+// int tsem_init(tsem_t *sem, int pshared, unsigned int value) {
+// // fprintf(stderr, "==%s[%d]%s():[%p]==creating\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
+// if (*sem) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==already initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// struct tsem_s *p = (struct tsem_s *)taosMemoryCalloc(1, sizeof(*p));
+// if (!p) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==out of memory\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
+// abort();
+// }
+
+// #ifdef SEM_USE_PTHREAD
+// int r = taosThreadMutexInit(&p->lock, NULL);
+// do {
+// if (r) break;
+// r = taosThreadCondInit(&p->cond, NULL);
+// if (r) {
+// taosThreadMutexDestroy(&p->lock);
+// break;
+// }
+// p->val = value;
+// } while (0);
+// if (r) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
+// abort();
+// }
+// #elif defined(SEM_USE_POSIX)
+// static size_t tick = 0;
+// do {
+// size_t id = atomic_add_fetch_64(&tick, 1);
+// if (id == SEM_VALUE_MAX) {
+// atomic_store_64(&tick, 0);
+// id = 0;
+// }
+// char name[NAME_MAX - 4];
+// snprintf(name, sizeof(name), "/t" PRId64, id);
+// p->sem = sem_open(name, O_CREAT | O_EXCL, pshared, value);
+// p->id = id;
+// if (p->sem != SEM_FAILED) break;
+// int e = errno;
+// if (e == EEXIST) continue;
+// if (e == EINTR) continue;
+// fprintf(stderr, "==%s[%d]%s():[%p]==not created[%d]%s\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem,
+// e, strerror(e));
+// abort();
+// } while (p->sem == SEM_FAILED);
+// #elif defined(SEM_USE_SEM)
+// taosThreadOnce(&sem_once, once_init);
+// if (sem_inited != 1) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal resource init failed\n", taosDirEntryBaseName(__FILE__), __LINE__,
+// __func__, sem);
+// errno = ENOMEM;
+// return -1;
+// }
+// kern_return_t ret = semaphore_create(sem_port, &p->sem, SYNC_POLICY_FIFO, value);
+// if (ret != KERN_SUCCESS) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==semophore_create failed\n", taosDirEntryBaseName(__FILE__), __LINE__,
+// __func__,
+// sem);
+// // we fail-fast here, because we have less-doc about semaphore_create for the moment
+// abort();
+// }
+// #else // SEM_USE_PTHREAD
+// p->sem = dispatch_semaphore_create(value);
+// if (p->sem == NULL) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==not created\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
+// abort();
+// }
+// #endif // SEM_USE_PTHREAD
+
+// p->valid = 1;
+
+// *sem = p;
+
+// return 0;
+// }
+
+// int tsem_wait(tsem_t *sem) {
+// if (!*sem) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
+// abort();
+// }
+// struct tsem_s *p = *sem;
+// if (!p->valid) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem); abort();
+// }
+// #ifdef SEM_USE_PTHREAD
+// if (taosThreadMutexLock(&p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// p->val -= 1;
+// if (p->val < 0) {
+// if (taosThreadCondWait(&p->cond, &p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__,
+// __func__,
+// sem);
+// abort();
+// }
+// }
+// if (taosThreadMutexUnlock(&p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// return 0;
+// #elif defined(SEM_USE_POSIX)
+// return sem_wait(p->sem);
+// #elif defined(SEM_USE_SEM)
+// return semaphore_wait(p->sem);
+// #else // SEM_USE_PTHREAD
+// return dispatch_semaphore_wait(p->sem, DISPATCH_TIME_FOREVER);
+// #endif // SEM_USE_PTHREAD
+// }
+
+// int tsem_post(tsem_t *sem) {
+// if (!*sem) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
+// abort();
+// }
+// struct tsem_s *p = *sem;
+// if (!p->valid) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem); abort();
+// }
+// #ifdef SEM_USE_PTHREAD
+// if (taosThreadMutexLock(&p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// p->val += 1;
+// if (p->val <= 0) {
+// if (taosThreadCondSignal(&p->cond)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__,
+// __func__,
+// sem);
+// abort();
+// }
+// }
+// if (taosThreadMutexUnlock(&p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// return 0;
+// #elif defined(SEM_USE_POSIX)
+// return sem_post(p->sem);
+// #elif defined(SEM_USE_SEM)
+// return semaphore_signal(p->sem);
+// #else // SEM_USE_PTHREAD
+// return dispatch_semaphore_signal(p->sem);
+// #endif // SEM_USE_PTHREAD
+// }
+
+// int tsem_destroy(tsem_t *sem) {
+// // fprintf(stderr, "==%s[%d]%s():[%p]==destroying\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__, sem);
+// if (!*sem) {
+// // fprintf(stderr, "==%s[%d]%s():[%p]==not initialized\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// // abort();
+// return 0;
+// }
+// struct tsem_s *p = *sem;
+// if (!p->valid) {
+// // fprintf(stderr, "==%s[%d]%s():[%p]==already destroyed\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// // sem); abort();
+// return 0;
+// }
+// #ifdef SEM_USE_PTHREAD
+// if (taosThreadMutexLock(&p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// p->valid = 0;
+// if (taosThreadCondDestroy(&p->cond)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// if (taosThreadMutexUnlock(&p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// if (taosThreadMutexDestroy(&p->lock)) {
+// fprintf(stderr, "==%s[%d]%s():[%p]==internal logic error\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem);
+// abort();
+// }
+// #elif defined(SEM_USE_POSIX)
+// char name[NAME_MAX - 4];
+// snprintf(name, sizeof(name), "/t" PRId64, p->id);
+// int r = sem_unlink(name);
+// if (r) {
+// int e = errno;
+// fprintf(stderr, "==%s[%d]%s():[%p]==unlink failed[%d]%s\n", taosDirEntryBaseName(__FILE__), __LINE__, __func__,
+// sem,
+// e, strerror(e));
+// abort();
+// }
+// #elif defined(SEM_USE_SEM)
+// semaphore_destroy(sem_port, p->sem);
+// #else // SEM_USE_PTHREAD
+// #endif // SEM_USE_PTHREAD
+
+// p->valid = 0;
+// taosMemoryFree(p);
+
+// *sem = NULL;
+// return 0;
+// }
+
+int tsem_init(tsem_t *psem, int flags, unsigned int count) {
+ *psem = dispatch_semaphore_create(count);
+ if (*psem == NULL) return -1;
+ return 0;
+}
+
+int tsem_destroy(tsem_t *psem) {
+ return 0;
+}
+
+int tsem_post(tsem_t *psem) {
+ if (psem == NULL || *psem == NULL) return -1;
+ dispatch_semaphore_signal(*psem);
+ return 0;
+}
+
+int tsem_wait(tsem_t *psem) {
+ if (psem == NULL || *psem == NULL) return -1;
+ dispatch_semaphore_wait(*psem, DISPATCH_TIME_FOREVER);
+ return 0;
+}
+
+int tsem_timewait(tsem_t *psem, int64_t nanosecs) {
+ if (psem == NULL || *psem == NULL) return -1;
+ dispatch_semaphore_wait(*psem, nanosecs);
+ return 0;
+}
+
+bool taosCheckPthreadValid(TdThread thread) {
+ int32_t ret = taosThreadKill(thread, 0);
+ if (ret == ESRCH) return false;
+ if (ret == EINVAL) return false;
+ // alive
+ return true;
+}
+
+int64_t taosGetSelfPthreadId() {
+ TdThread thread = taosThreadSelf();
+ return (int64_t)thread;
+}
+
+int64_t taosGetPthreadId(TdThread thread) { return (int64_t)thread; }
+
+void taosResetPthread(TdThread *thread) { *thread = NULL; }
+
+bool taosComparePthread(TdThread first, TdThread second) { return taosThreadEqual(first, second) ? true : false; }
+
+int32_t taosGetPId() { return (int32_t)getpid(); }
+
+int32_t taosGetAppName(char *name, int32_t *len) {
+ char buf[PATH_MAX + 1];
+ buf[0] = '\0';
+ proc_name(getpid(), buf, sizeof(buf) - 1);
+ buf[PATH_MAX] = '\0';
+ size_t n = strlen(buf);
+ if (len) *len = n;
+ if (name) tstrncpy(name, buf, TSDB_APP_NAME_LEN);
+ return 0;
+}
+
+#else
+
+/*
+ * linux implementation
+ */
+
+#include
+#include
+
+bool taosCheckPthreadValid(TdThread thread) { return thread != 0; }
+
+int64_t taosGetSelfPthreadId() {
+ static __thread int id = 0;
+ if (id != 0) return id;
+ id = syscall(SYS_gettid);
+ return id;
+}
+
+int64_t taosGetPthreadId(TdThread thread) { return (int64_t)thread; }
+void taosResetPthread(TdThread* thread) { *thread = 0; }
+bool taosComparePthread(TdThread first, TdThread second) { return first == second; }
+
+int32_t taosGetPId() {
+ static int32_t pid;
+ if (pid != 0) return pid;
+ pid = getpid();
+ return pid;
+}
+
+int32_t taosGetAppName(char* name, int32_t* len) {
+ const char* self = "/proc/self/exe";
+ char path[PATH_MAX] = {0};
+
+ if (readlink(self, path, PATH_MAX) <= 0) {
+ return -1;
+ }
+
+ path[PATH_MAX - 1] = 0;
+ char* end = strrchr(path, '/');
+ if (end == NULL) {
+ return -1;
+ }
+
+ ++end;
+
+ tstrncpy(name, end, TSDB_APP_NAME_LEN);
+
+ if (len != NULL) {
+ *len = strlen(name);
+ }
+
+ return 0;
+}
+
+int32_t tsem_wait(tsem_t* sem) {
+ int ret = 0;
+ do {
+ ret = sem_wait(sem);
+ } while (ret != 0 && errno == EINTR);
+ return ret;
+}
+
+int32_t tsem_timewait(tsem_t* sem, int64_t nanosecs) {
+ int ret = 0;
+
+ struct timespec tv = {
+ .tv_sec = 0,
+ .tv_nsec = nanosecs,
+ };
+
+ while ((ret = sem_timedwait(sem, &tv)) == -1 && errno == EINTR) continue;
+
+ return ret;
+}
+
+#endif