summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2016-12-09 09:56:05 +0800
committerruki <[email protected]>2016-12-09 09:56:05 +0800
commit432c1692189911296fecd8779d623cea96141617 (patch)
treec093f2c726a6c4384d608493c50bb4ff3a13d63b
parent2933d72e11d4af052dd3bc804926a53b85a9b4a6 (diff)
update tbox for linux x86_64
-rwxr-xr-xcore/pkg/tbox.pkg/inc/linux/tbox.config.h7
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h3
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/stackless/core.h169
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/stackless/coroutine.h411
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/stackless/lock.h79
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/stackless/prefix.h55
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/stackless/scheduler.h79
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/stackless/semaphore.h102
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/coroutine/stackless/stackless.h36
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/platform/poller.h9
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h6
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/prefix/compiler.h2
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/utils/bits.h11
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h28
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h6
-rwxr-xr-xcore/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.abin922026 -> 922170 bytes
16 files changed, 979 insertions, 24 deletions
diff --git a/core/pkg/tbox.pkg/inc/linux/tbox.config.h b/core/pkg/tbox.pkg/inc/linux/tbox.config.h
index c635166f7..5c05019b9 100755
--- a/core/pkg/tbox.pkg/inc/linux/tbox.config.h
+++ b/core/pkg/tbox.pkg/inc/linux/tbox.config.h
@@ -2,11 +2,11 @@
#define TB_CONFIG_H
// version
-#define TB_CONFIG_VERSION "1.6.1"
+#define TB_CONFIG_VERSION "1.6.2"
#define TB_CONFIG_VERSION_MAJOR 1
#define TB_CONFIG_VERSION_MINOR 6
-#define TB_CONFIG_VERSION_ALTER 1
-#define TB_CONFIG_VERSION_BUILD 201612012304
+#define TB_CONFIG_VERSION_ALTER 2
+#define TB_CONFIG_VERSION_BUILD 201612090948
// defines
#define TB_CONFIG_OS_LINUX 1
@@ -81,6 +81,7 @@
#define TB_CONFIG_LIBM_HAVE_EXP 1
#define TB_CONFIG_LIBM_HAVE_EXPF 1
#define TB_CONFIG_POSIX_HAVE_POLL 1
+#define TB_CONFIG_POSIX_HAVE_SELECT 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_CREATE 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC 1
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h
index 390640f71..15a4ddb64 100755
--- a/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h
@@ -31,6 +31,7 @@
#include "channel.h"
#include "semaphore.h"
#include "scheduler.h"
+#include "stackless/stackless.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
@@ -101,7 +102,7 @@ tb_pointer_t tb_coroutine_sleep(tb_long_t interval);
*
* @return > 0: the events, 0: timeout, -1: failed
*/
-tb_long_t tb_coroutine_wait(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
+tb_long_t tb_coroutine_waitio(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
/*! get the current coroutine
*
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/core.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/core.h
new file mode 100755
index 000000000..298beab04
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/core.h
@@ -0,0 +1,169 @@
+/*!The Treasure Box Library
+ *
+ * TBox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * TBox 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with TBox;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file core.h
+ * @ingroup coroutine
+ *
+ */
+#ifndef TB_COROUTINE_STACKLESS_CORE_H
+#define TB_COROUTINE_STACKLESS_CORE_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+// get core from coroutine
+#define tb_lo_core(co) ((tb_lo_core_ref_t)(co))
+
+// get core state
+#define tb_lo_core_state(co) (tb_lo_core(co)->state)
+
+// set core state
+#define tb_lo_core_state_set(co, val) tb_lo_core(co)->state = (val)
+
+#ifdef TB_COMPILER_IS_GCC
+/*
+ * Implementation of local continuations based on the "Labels as
+ * values" feature of gcc
+ *
+ * @author Adam Dunkels <[email protected]>
+ *
+ * This implementation of local continuations is based on a special
+ * feature of the GCC C compiler called "labels as values". This
+ * feature allows assigning pointers with the address of the code
+ * corresponding to a particular C label.
+ *
+ * For more information, see the GCC documentation:
+ * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+ */
+# define tb_lo_core_init(co) tb_lo_core(co)->branch = tb_null; tb_lo_core(co)->state = TB_STATE_READY
+# define tb_lo_core_resume(co) \
+ if (tb_lo_core(co)->branch) \
+ { \
+ goto *(tb_lo_core(co)->branch); \
+ } \
+ else
+
+# define tb_lo_core_record(co) \
+ do \
+ { \
+ __tb_mconcat_ex__(__tb_lo_core_label, __tb_line__): \
+ tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__); \
+ \
+ } while(0)
+
+# define tb_lo_core_exit(co) tb_lo_core(co)->branch = tb_null, tb_lo_core(co)->state = TB_STATE_END
+
+#else
+
+/*
+ * Implementation of local continuations based on switch() statment
+ *
+ * @author Adam Dunkels <[email protected]>
+ *
+ * This implementation of local continuations uses the C switch()
+ * statement to resume execution of a function somewhere inside the
+ * function's body. The implementation is based on the fact that
+ * switch() statements are able to jump directly into the bodies of
+ * control structures such as if() or while() statmenets.
+ *
+ * This implementation borrows heavily from Simon Tatham's coroutines
+ * implementation in C:
+ * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+ *
+ *
+ *
+ * WARNING! the implementation using switch() does not work if an
+ * core_set() is done within another switch() statement!
+ */
+# define tb_lo_core_init(co) tb_lo_core(co)->branch = 0; tb_lo_core(co)->state = TB_STATE_READY
+# define tb_lo_core_resume(co) switch (tb_lo_core(co)->branch) case 0:
+# define tb_lo_core_record_(co, label) tb_lo_core(co)->branch = (tb_uint16_t)label; case label:
+# define tb_lo_core_exit(co) tb_lo_core(co)->branch = 0, tb_lo_core(co)->state = TB_STATE_END
+# ifdef TB_COMPILER_IS_MSVC
+# define tb_lo_core_record(co) tb_lo_core_record_(co, __COUNTER__ + 1)
+# else
+# define tb_lo_core_record(co) tb_lo_core_record_(co, __tb_line__)
+# endif
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the core branch type
+#ifdef TB_COMPILER_IS_GCC
+typedef tb_pointer_t tb_lo_core_branch_t;
+#else
+typedef tb_uint16_t tb_lo_core_branch_t;
+#endif
+
+// the stackless coroutine core type
+typedef struct __tb_lo_core_t
+{
+ // the code branch
+ tb_lo_core_branch_t branch;
+
+ /* the state
+ *
+ * TB_STATE_READY
+ * TB_STATE_SUSPEND
+ * TB_STATE_END
+ */
+ tb_uint8_t state;
+
+}tb_lo_core_t, *tb_lo_core_ref_t;
+
+
+#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/coroutine.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/coroutine.h
new file mode 100755
index 000000000..c24d3bda0
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/coroutine.h
@@ -0,0 +1,411 @@
+/*!The Treasure Box Library
+ *
+ * TBox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * TBox 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with TBox;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file coroutine.h
+ * @ingroup coroutine
+ *
+ */
+#ifndef TB_COROUTINE_STACKLESS_COROUTINE_H
+#define TB_COROUTINE_STACKLESS_COROUTINE_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "core.h"
+#include "scheduler.h"
+#include "../../libc/libc.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+/// the self coroutine
+#define tb_lo_coroutine_self() (co__)
+
+/* enter coroutine
+ *
+ * @code
+ *
+ // before
+ tb_lo_coroutine_enter(co)
+ {
+ for (i = 0; i < 100; i++)
+ {
+ tb_lo_coroutine_yield();
+ }
+ }
+
+ // after expanding again (init: branch = 0, state = TB_STATE_READY)
+ tb_lo_coroutine_ref_t co__ = co;
+ tb_int_t lo_yield_flag__ = 1;
+ for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0)
+ switch (tb_lo_core(co__)->branch)
+ case 0:
+ {
+ for (i = 0; i < 100; i++)
+ {
+ lo_yield_flag__ = 0;
+ tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:;
+ if (lo_yield_flag__ == 0)
+ return ;
+ }
+ }
+
+ // or ..
+
+ // after expanding again for gcc label (init: branch = tb_null, state = TB_STATE_READY)
+ tb_lo_coroutine_ref_t co__ = co;
+ tb_int_t lo_yield_flag__ = 1;
+ for (; lo_yield_flag__; tb_lo_core(co__)->branch = tb_null, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0)
+ if (tb_lo_core(co)->branch)
+ {
+ goto *(tb_lo_core(co)->branch);
+ }
+ else
+ {
+ for (i = 0; i < 100; i++)
+ {
+ lo_yield_flag__ = 0;
+ do
+ {
+ __tb_mconcat_ex__(__tb_lo_core_label, __tb_line__):
+ tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__);
+
+ } while(0)
+
+ if (lo_yield_flag__ == 0)
+ return ;
+ }
+ }
+
+ * @endcode
+ */
+#define tb_lo_coroutine_enter(co) \
+ tb_lo_coroutine_ref_t co__ = (co); \
+ tb_int_t lo_yield_flag__ = 1; \
+ for ( ; lo_yield_flag__; tb_lo_core_exit(tb_lo_coroutine_self()), lo_yield_flag__ = 0) \
+ tb_lo_core_resume(tb_lo_coroutine_self())
+
+/// yield coroutine
+#define tb_lo_coroutine_yield() \
+do \
+{ \
+ lo_yield_flag__ = 0; \
+ tb_lo_core_record(co__); \
+ if (lo_yield_flag__ == 0) \
+ return ; \
+ \
+} while(0)
+
+/*! suspend current coroutine
+ *
+ * the scheduler will move this coroutine to the suspended coroutines after the function be returned
+ *
+ * @code
+ *
+ // before
+ tb_lo_coroutine_enter(co)
+ {
+ for (i = 0; i < 100; i++)
+ {
+ tb_lo_coroutine_yield();
+ tb_lo_coroutine_suspend();
+ }
+ }
+
+ // after expanding again (init: branch = 0, state = TB_STATE_READY)
+ tb_lo_coroutine_ref_t co__ = co;
+ tb_int_t lo_yield_flag__ = 1;
+ for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0)
+ switch (tb_lo_core(co__)->branch)
+ case 0:
+ {
+ for (i = 0; i < 100; i++)
+ {
+ lo_yield_flag__ = 0;
+ tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:;
+ if (lo_yield_flag__ == 0)
+ return ;
+
+ // suspend coroutine
+ tb_lo_core(co__)->state = TB_STATE_SUSPEND;
+ tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:;
+ if (tb_lo_core(co__)->state == TB_STATE_SUSPEND)
+ return ;
+ }
+ }
+ * @endcode
+ */
+#define tb_lo_coroutine_suspend() \
+do \
+{ \
+ tb_used(&lo_yield_flag__); \
+ tb_lo_core_state_set(tb_lo_coroutine_self(), TB_STATE_SUSPEND); \
+ tb_lo_core_record(tb_lo_coroutine_self()); \
+ if (tb_lo_core_state(tb_lo_coroutine_self()) == TB_STATE_SUSPEND) \
+ return ; \
+ \
+} while(0)
+
+/// sleep some time
+#define tb_lo_coroutine_sleep(interval) \
+do \
+{ \
+ if (interval) \
+ { \
+ tb_lo_coroutine_sleep_(tb_lo_coroutine_self(), interval); \
+ tb_lo_coroutine_suspend(); \
+ } \
+ \
+} while(0)
+
+/// wait io socket events
+#define tb_lo_coroutine_waitio(sock, events, interval) \
+do \
+{ \
+ if (tb_lo_coroutine_waitio_(tb_lo_coroutine_self(), sock, events, interval)) \
+ { \
+ tb_lo_coroutine_suspend(); \
+ } \
+ \
+} while(0)
+
+/// wait until coroutine be true
+#define tb_lo_coroutine_wait_until(cond) \
+do \
+{ \
+ tb_used(&lo_yield_flag__); \
+ tb_lo_core_record(tb_lo_coroutine_self()); \
+ if (!(cond)) \
+ return ; \
+ \
+} while(0)
+
+/// wait while coroutine be true
+#define tb_lo_coroutine_wait_while(pt, cond) tb_lo_coroutine_wait_until(!(cond))
+
+/// get socket events after waiting
+#define tb_lo_coroutine_events() tb_lo_coroutine_events_(tb_lo_coroutine_self())
+
+/*! pass the user private data
+ *
+ * @code
+
+ // start coroutine
+ tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass(tb_xxxx_priv_t));
+
+ * @endcode
+ *
+ * =>
+ *
+ * @code
+
+ // start coroutine
+ tb_lo_coroutine_start(scheduler, coroutine_func, tb_malloc0_type(tb_xxxx_priv_t), tb_lo_coroutine_pass_free_);
+
+ * @endcode
+ */
+#define tb_lo_coroutine_pass(type) tb_malloc0_type(type), tb_lo_coroutine_pass_free_
+
+/*! pass the user private data and init one member
+ *
+ * @code
+
+ typedef struct __tb_xxxx_priv_t
+ {
+ tb_size_t member;
+ tb_size_t others;
+
+ }tb_xxxx_priv_t;
+
+ // start coroutine
+ tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass1(tb_xxxx_priv_t, member, value));
+
+ * @endcode
+ *
+ * =>
+ *
+ * @code
+
+ tb_xxxx_priv_t* priv = tb_malloc0_type(tb_xxxx_priv_t);
+ if (priv)
+ {
+ priv->member = value;
+ }
+
+ // start coroutine
+ tb_lo_coroutine_start(scheduler, coroutine_func, priv, tb_lo_coroutine_pass_free_);
+
+ * @endcode
+ */
+#define tb_lo_coroutine_pass1(type, member, value) tb_lo_coroutine_pass1_make_(sizeof(type), &(value), tb_offsetof(type, member), tb_memsizeof(type, member)), tb_lo_coroutine_pass_free_
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private interfaces
+ */
+
+/* get the scheduler of coroutine
+ *
+ * @param coroutine the coroutine
+ *
+ * @return the scheduler
+ */
+tb_lo_scheduler_ref_t tb_lo_coroutine_scheduler_(tb_lo_coroutine_ref_t coroutine);
+
+/* sleep the current coroutine
+ *
+ * @param coroutine the coroutine
+ * @param interval the interval (ms), infinity: -1
+ */
+tb_void_t tb_lo_coroutine_sleep_(tb_lo_coroutine_ref_t coroutine, tb_long_t interval);
+
+/* wait io events
+ *
+ * @param coroutine the coroutine
+ * @param sock the socket
+ * @param events the waited events
+ * @param timeout the timeout, infinity: -1
+ *
+ * @return suspend coroutine if be tb_true
+ */
+tb_bool_t tb_lo_coroutine_waitio_(tb_lo_coroutine_ref_t coroutine, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
+
+/* get the events after waiting socket
+ *
+ * @param coroutine the coroutine
+ *
+ * @return events: > 0, failed: -1, timeout: 0
+ */
+tb_long_t tb_lo_coroutine_events_(tb_lo_coroutine_ref_t coroutine);
+
+/* free the user private data for pass()
+ *
+ * @note only be a wrapper of free() for tb_lo_coroutine_pass()
+ *
+ * @param priv the user private data
+ */
+tb_void_t tb_lo_coroutine_pass_free_(tb_cpointer_t priv);
+
+/* make the user private data for pass1()
+ *
+ * @param type_size the data type size
+ * @param value the value pointer
+ * @param offset the member offset
+ * @param size the value size
+ *
+ * @return the user private data
+ */
+tb_pointer_t tb_lo_coroutine_pass1_make_(tb_size_t type_size, tb_cpointer_t value, tb_size_t offset, tb_size_t size);
+
+/* make the user private data for pass2()
+ *
+ * @param type_size the data type size
+ * @param value1 the value1 pointer
+ * @param offset1 the member1 offset
+ * @param size1 the value1 size
+ * @param value2 the value2 pointer
+ * @param offset2 the member2 offset
+ * @param size2 the value2 size
+ *
+ * @return the user private data
+ */
+tb_pointer_t tb_lo_coroutine_pass2_make_(tb_size_t type_size, tb_cpointer_t value1, tb_size_t offset1, tb_size_t size1, tb_cpointer_t value2, tb_size_t offset2, tb_size_t size2);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*! start coroutine
+ *
+ * @code
+ static tb_void_t switchtask(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv)
+ {
+ // get count pointer (@note only allow non-status local variables)
+ tb_size_t* count = (tb_size_t*)priv;
+
+ // enter coroutine
+ tb_lo_coroutine_enter(coroutine);
+
+ // @note can not define local variables here
+ // ...
+
+ // loop
+ while ((*count)--)
+ {
+ // yield
+ tb_lo_coroutine_yield();
+ }
+
+ // leave coroutine
+ tb_lo_coroutine_leave();
+ }
+
+ tb_int_t main (tb_int_t argc, tb_char_t** argv)
+ {
+ // init tbox
+ if (!tb_init(tb_null, tb_null)) return -1;
+
+ // init scheduler
+ tb_lo_scheduler_ref_t scheduler = tb_lo_scheduler_init();
+ if (scheduler)
+ {
+ // start coroutine
+ tb_size_t counts[] = {100, 100};
+ tb_lo_coroutine_start(scheduler, switchtask, &counts[0], tb_null);
+ tb_lo_coroutine_start(scheduler, switchtask, &counts[1], tb_null);
+
+ // run scheduler
+ tb_lo_scheduler_loop(scheduler);
+
+ // exit scheduler
+ tb_lo_scheduler_exit(scheduler);
+ }
+
+ // exit tbox
+ tb_exit();
+ }
+
+ * @endcode
+ *
+ * @param scheduler the scheduler (can not be null, we can get scheduler of the current coroutine from tb_lo_scheduler_self())
+ * @param func the coroutine function
+ * @param priv the passed user private data as the argument of function
+ * @param free the user private free function
+ *
+ * @return tb_true or tb_false
+ */
+tb_bool_t tb_lo_coroutine_start(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free);
+
+/*! resume the given coroutine
+ *
+ * @param coroutine the coroutine
+ */
+tb_void_t tb_lo_coroutine_resume(tb_lo_coroutine_ref_t coroutine);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/lock.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/lock.h
new file mode 100755
index 000000000..ceae8e0b1
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/lock.h
@@ -0,0 +1,79 @@
+/*!The Treasure Box Library
+ *
+ * TBox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * TBox 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with TBox;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file lock.h
+ * @ingroup coroutine
+ *
+ */
+#ifndef TB_COROUTINE_STACKLESS_LOCK_H
+#define TB_COROUTINE_STACKLESS_LOCK_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "semaphore.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+/*! init lock
+ *
+ * @param lock the lock pointer
+ */
+#define tb_lo_lock_init(lock) tb_lo_semaphore_init(lock, 1)
+
+/*! exit lock
+ *
+ * @param lock the lock pointer
+ */
+#define tb_lo_lock_exit(lock) tb_lo_semaphore_exit(lock)
+
+/*! enter lock
+ *
+ * @param lock the lock pointer
+ */
+#define tb_lo_lock_enter(lock) tb_lo_semaphore_wait(lock)
+
+/*! try to enter lock
+ *
+ * @param lock the lock pointer
+ *
+ * @return tb_true or tb_false
+ */
+#define tb_lo_lock_enter_try(lock) tb_lo_semaphore_wait_try(lock)
+
+/*! leave lock
+ *
+ * @param lock the lock pointer
+ */
+#define tb_lo_lock_leave(lock) tb_lo_semaphore_post(lock, 1)
+
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+/// the stackless lock type
+typedef tb_lo_semaphore_t tb_lo_lock_t;
+
+/// the stackless lock ref type
+typedef tb_lo_semaphore_ref_t tb_lo_lock_ref_t;
+
+#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/prefix.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/prefix.h
new file mode 100755
index 000000000..288f8ebd8
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/prefix.h
@@ -0,0 +1,55 @@
+/*!The Treasure Box Library
+ *
+ * TBox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * TBox 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with TBox;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file prefix.h
+ *
+ */
+#ifndef TB_COROUTINE_STACKLESS_PREFIX_H
+#define TB_COROUTINE_STACKLESS_PREFIX_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "../prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+/// the stackless coroutine ref type
+typedef __tb_typeref__(lo_coroutine);
+
+/// the stackless scheduler ref type
+typedef __tb_typeref__(lo_scheduler);
+
+/*! the coroutine function type
+ *
+ * @param coroutine the coroutine self
+ * @param priv the user private data from start(.., priv)
+ */
+typedef tb_void_t (*tb_lo_coroutine_func_t)(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv);
+
+/*! the user private data free function type
+ *
+ * @param priv the user private data from start(.., priv)
+ */
+typedef tb_void_t (*tb_lo_coroutine_free_t)(tb_cpointer_t priv);
+
+
+#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/scheduler.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/scheduler.h
new file mode 100755
index 000000000..f1b607a49
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/scheduler.h
@@ -0,0 +1,79 @@
+/*!The Treasure Box Library
+ *
+ * TBox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * TBox 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with TBox;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file scheduler.h
+ * @ingroup coroutine
+ *
+ */
+#ifndef TB_COROUTINE_STACKLESS_SCHEDULER_H
+#define TB_COROUTINE_STACKLESS_SCHEDULER_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+/// the self scheduler
+#define tb_lo_scheduler_self() tb_lo_coroutine_scheduler_(co__)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*! init scheduler
+ *
+ * @return the scheduler
+ */
+tb_lo_scheduler_ref_t tb_lo_scheduler_init(tb_noarg_t);
+
+/*! exit scheduler
+ *
+ * @param scheduler the scheduler
+ */
+tb_void_t tb_lo_scheduler_exit(tb_lo_scheduler_ref_t scheduler);
+
+/* kill the scheduler
+ *
+ * @param scheduler the scheduler
+ */
+tb_void_t tb_lo_scheduler_kill(tb_lo_scheduler_ref_t scheduler);
+
+/*! run the scheduler loop
+ *
+ * @param scheduler the scheduler
+ * @param exclusive enable exclusive mode, we need ensure only one loop() be called at the same time,
+ * but it will be faster using thr global scheduler instead of TLS storage
+ */
+tb_void_t tb_lo_scheduler_loop(tb_lo_scheduler_ref_t scheduler, tb_bool_t exclusive);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/semaphore.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/semaphore.h
new file mode 100755
index 000000000..32d7c6518
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/semaphore.h
@@ -0,0 +1,102 @@
+/*!The Treasure Box Library
+ *
+ * TBox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * TBox 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with TBox;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file semaphore.h
+ * @ingroup coroutine
+ *
+ */
+#ifndef TB_COROUTINE_STACKLESS_SEMAPHORE_H
+#define TB_COROUTINE_STACKLESS_SEMAPHORE_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "coroutine.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+/*! init semaphore
+ *
+ * @param sem the semaphore pointer
+ * @param val the initial semaphore value
+ */
+#define tb_lo_semaphore_init(sem, val) (sem)->value = val
+
+/*! exit semaphore
+ *
+ * @param sem the semaphore pointer
+ */
+#define tb_lo_semaphore_exit(sem) (sem)->value = 0
+
+/*! get semaphore value
+ *
+ * @param sem the semaphore pointer
+ *
+ * @return the semaphore value
+ */
+#define tb_lo_semaphore_value(sem) ((sem)->value)
+
+/*! post semaphore
+ *
+ * @param sem the semaphore pointer
+ * @param post the post semaphore value
+ */
+#define tb_lo_semaphore_post(sem, post) \
+do \
+{ \
+ (sem)->value += (post); \
+ tb_lo_coroutine_yield(); \
+ \
+} while (0)
+
+/*! wait semaphore
+ *
+ * @param sem the semaphore pointer
+ */
+#define tb_lo_semaphore_wait(sem) \
+do \
+{ \
+ tb_lo_coroutine_wait_until((sem)->value > 0); \
+ (sem)->value--; \
+ \
+} while(0)
+
+/*! try to wait semaphore
+ *
+ * @param sem the semaphore pointer
+ *
+ * @return tb_true or tb_false
+ */
+#define tb_lo_semaphore_wait_try(sem) (((sem)->value > 0)? (sem)->value-- : 0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+/// the stackless semaphore type
+typedef struct __tb_lo_semaphore_t
+{
+ // the semaphore value
+ tb_long_t value;
+
+}tb_lo_semaphore_t, *tb_lo_semaphore_ref_t;
+
+#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/stackless.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/stackless.h
new file mode 100755
index 000000000..c898c8ff6
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/stackless.h
@@ -0,0 +1,36 @@
+/*!The Treasure Box Library
+ *
+ * TBox is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * TBox 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with TBox;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file stackless.h
+ * @ingroup coroutine
+ *
+ */
+#ifndef TB_COROUTINE_STACKLESS_H
+#define TB_COROUTINE_STACKLESS_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "coroutine.h"
+#include "scheduler.h"
+#include "semaphore.h"
+#include "lock.h"
+
+
+#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/platform/poller.h b/core/pkg/tbox.pkg/inc/tbox/platform/poller.h
index 76e1bd083..c746bff57 100755
--- a/core/pkg/tbox.pkg/inc/tbox/platform/poller.h
+++ b/core/pkg/tbox.pkg/inc/tbox/platform/poller.h
@@ -41,16 +41,23 @@ __tb_extern_c_enter__
/// the poller event enum, only for sock
typedef enum __tb_poller_event_e
{
+ // the waited events
TB_POLLER_EVENT_NONE = TB_SOCKET_EVENT_NONE
, TB_POLLER_EVENT_CONN = TB_SOCKET_EVENT_CONN
, TB_POLLER_EVENT_ACPT = TB_SOCKET_EVENT_ACPT
, TB_POLLER_EVENT_RECV = TB_SOCKET_EVENT_RECV
, TB_POLLER_EVENT_SEND = TB_SOCKET_EVENT_SEND
+, TB_POLLER_EVENT_EALL = TB_SOCKET_EVENT_EALL
+ // the event flags after waiting
, TB_POLLER_EVENT_CLEAR = 0x0010 //!< edge trigger. after the event is retrieved by the user, its state is reset
, TB_POLLER_EVENT_ONESHOT = 0x0020 //!< causes the event to return only the first occurrence of the filter being triggered
-, TB_POLLER_EVENT_EALL = TB_SOCKET_EVENT_EALL
+ /*! the event flag will be marked if the connection be closed in the edge trigger (TB_POLLER_EVENT_CLEAR)
+ *
+ * be similar to epoll.EPOLLRDHUP and kqueue.EV_EOF
+ */
+, TB_POLLER_EVENT_EOF = 0x0100
}tb_poller_event_e;
diff --git a/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h b/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h
index 8ac1d5e92..7c3c48ba4 100755
--- a/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h
+++ b/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h
@@ -118,6 +118,9 @@ typedef tb_int_t (WSAAPI* tb_ws2_32___WSAFDIsSet_t)(SOCKET fd, fd_set* set);
// the getaddrinfo func type
typedef tb_int_t (WSAAPI* tb_ws2_32_getaddrinfo_t)(PCSTR pNodeName, PCSTR pServiceName, ADDRINFOA *pHints, PADDRINFOA *ppResult);
+// the freeaddrinfo func type
+typedef tb_void_t (WSAAPI* tb_ws2_32_freeaddrinfo_t)(struct addrinfo* ai);
+
// the getnameinfo func type
typedef tb_int_t (WSAAPI* tb_ws2_32_getnameinfo_t)(const struct sockaddr FAR *sa, socklen_t salen, tb_char_t FAR *host, DWORD hostlen, tb_char_t FAR *serv, DWORD servlen, tb_int_t flags);
@@ -207,6 +210,9 @@ typedef struct __tb_ws2_32_t
// getaddrinfo
tb_ws2_32_getaddrinfo_t getaddrinfo;
+
+ // freeaddrinfo
+ tb_ws2_32_freeaddrinfo_t freeaddrinfo;
// getnameinfo
tb_ws2_32_getnameinfo_t getnameinfo;
diff --git a/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h b/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h
index cbda980cf..18b8c3fb6 100755
--- a/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h
+++ b/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h
@@ -286,6 +286,8 @@
# define TB_COMPILER_VERSION_STRING "visual c++ .net 2013 (12.0)"
# elif (_MSC_VER == 1900)
# define TB_COMPILER_VERSION_STRING "visual c++ .net 2015 (14.0)"
+# elif (_MSC_VER == 2000)
+# define TB_COMPILER_VERSION_STRING "visual c++ .net 2017 (15.0)"
# else
# error Unknown visual c++ Compiler Version
# endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/utils/bits.h b/core/pkg/tbox.pkg/inc/tbox/utils/bits.h
index d5f97adff..dc05316ac 100755
--- a/core/pkg/tbox.pkg/inc/tbox/utils/bits.h
+++ b/core/pkg/tbox.pkg/inc/tbox/utils/bits.h
@@ -29,8 +29,7 @@
*/
#include "prefix.h"
#include "../libm/libm.h"
-#if defined(TB_COMPILER_IS_GCC) \
- && TB_COMPILER_VERSION_BE(4, 1)
+#if defined(TB_COMPILER_IS_GCC)
# include "impl/bits_gcc.h"
#endif
#if defined(TB_ARCH_x86) || defined(TB_ARCH_x64)
@@ -658,22 +657,22 @@ static __tb_inline__ tb_void_t tb_bits_set_u64_be_inline(tb_byte_t* p, tb_uint64
*/
// swap
-static __tb_inline__ tb_uint16_t const tb_bits_swap_u16_inline(tb_uint16_t x)
+static __tb_inline__ tb_uint16_t tb_bits_swap_u16_inline(tb_uint16_t x)
{
x = (x >> 8) | (x << 8);
return x;
}
-static __tb_inline__ tb_uint32_t const tb_bits_swap_u24_inline(tb_uint32_t x)
+static __tb_inline__ tb_uint32_t tb_bits_swap_u24_inline(tb_uint32_t x)
{
return (x >> 16) | (x & 0x0000ff00) | (x << 16);
}
-static __tb_inline__ tb_uint32_t const tb_bits_swap_u32_inline(tb_uint32_t x)
+static __tb_inline__ tb_uint32_t tb_bits_swap_u32_inline(tb_uint32_t x)
{
x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff);
x = (x >> 16) | (x << 16);
return x;
}
-static __tb_inline__ tb_hize_t const tb_bits_swap_u64_inline(tb_hize_t x)
+static __tb_inline__ tb_hize_t tb_bits_swap_u64_inline(tb_hize_t x)
{
union
{
diff --git a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h
index df853e693..0d96249a1 100755
--- a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h
+++ b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h
@@ -32,22 +32,30 @@
* macros
*/
// swap
-#define tb_bits_swap_u32(x) __builtin_bswap32(x)
-#define tb_bits_swap_u64(x) __builtin_bswap64(x)
+#if TB_COMPILER_VERSION_BE(4, 3)
+# define tb_bits_swap_u32(x) __builtin_bswap32(x)
+# define tb_bits_swap_u64(x) __builtin_bswap64(x)
+#endif
// cl0
-#define tb_bits_cl0_u32_be(x) ((x)? (tb_size_t)__builtin_clz((tb_uint32_t)(x)) : 32)
-#define tb_bits_cl0_u32_le(x) ((x)? (tb_size_t)__builtin_ctz((tb_uint32_t)(x)) : 32)
-#define tb_bits_cl0_u64_be(x) ((x)? (tb_size_t)__builtin_clzll((tb_uint64_t)(x)) : 64)
-#define tb_bits_cl0_u64_le(x) ((x)? (tb_size_t)__builtin_ctzll((tb_uint64_t)(x)) : 64)
+#if TB_COMPILER_VERSION_BE(4, 1)
+# define tb_bits_cl0_u32_be(x) ((x)? (tb_size_t)__builtin_clz((tb_uint32_t)(x)) : 32)
+# define tb_bits_cl0_u32_le(x) ((x)? (tb_size_t)__builtin_ctz((tb_uint32_t)(x)) : 32)
+# define tb_bits_cl0_u64_be(x) ((x)? (tb_size_t)__builtin_clzll((tb_uint64_t)(x)) : 64)
+# define tb_bits_cl0_u64_le(x) ((x)? (tb_size_t)__builtin_ctzll((tb_uint64_t)(x)) : 64)
+#endif
// cb1
-#define tb_bits_cb1_u32(x) ((x)? (tb_size_t)__builtin_popcount((tb_uint32_t)(x)) : 0)
-#define tb_bits_cb1_u64(x) ((x)? (tb_size_t)__builtin_popcountll((tb_uint64_t)(x)) : 0)
+#if TB_COMPILER_VERSION_BE(4, 1)
+# define tb_bits_cb1_u32(x) ((x)? (tb_size_t)__builtin_popcount((tb_uint32_t)(x)) : 0)
+# define tb_bits_cb1_u64(x) ((x)? (tb_size_t)__builtin_popcountll((tb_uint64_t)(x)) : 0)
+#endif
// fb1
-#define tb_bits_fb1_u32_le(x) ((x)? (tb_size_t)__builtin_ffs((tb_uint32_t)(x)) - 1 : 32)
-#define tb_bits_fb1_u64_le(x) ((x)? (tb_size_t)__builtin_ffsll((tb_uint64_t)(x)) - 1 : 64)
+#if TB_COMPILER_VERSION_BE(4, 1)
+# define tb_bits_fb1_u32_le(x) ((x)? (tb_size_t)__builtin_ffs((tb_uint32_t)(x)) - 1 : 32)
+# define tb_bits_fb1_u64_le(x) ((x)? (tb_size_t)__builtin_ffsll((tb_uint64_t)(x)) - 1 : 64)
+#endif
#endif
diff --git a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h
index 76fc8010f..5c4fb7330 100755
--- a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h
+++ b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h
@@ -53,13 +53,13 @@
#ifdef TB_ASSEMBLER_IS_GAS
// swap
-static __tb_inline__ tb_uint16_t const tb_bits_swap_u16_asm(tb_uint16_t x)
+static __tb_inline__ tb_uint16_t tb_bits_swap_u16_asm(tb_uint16_t x)
{
__tb_asm__ __tb_volatile__("rorw $8, %w0" : "+r"(x));
return x;
}
-static __tb_inline__ tb_uint32_t const tb_bits_swap_u32_asm(tb_uint32_t x)
+static __tb_inline__ tb_uint32_t tb_bits_swap_u32_asm(tb_uint32_t x)
{
#if 1
__tb_asm__ __tb_volatile__("bswap %0" : "+r" (x));
@@ -76,7 +76,7 @@ static __tb_inline__ tb_uint32_t const tb_bits_swap_u32_asm(tb_uint32_t x)
return x;
}
-static __tb_inline__ tb_hize_t const tb_bits_swap_u64_asm(tb_hize_t x)
+static __tb_inline__ tb_hize_t tb_bits_swap_u64_asm(tb_hize_t x)
{
__tb_register__ tb_size_t esi, edi;
__tb_asm__ __tb_volatile__
diff --git a/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a b/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a
index ab777bf42..bd64b5a94 100755
--- a/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a
+++ b/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a
Binary files differ