1 /*
2   +----------------------------------------------------------------------+
3   | Swoole                                                               |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 2.0 of the Apache license,    |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | http://www.apache.org/licenses/LICENSE-2.0.html                      |
9   | If you did not receive a copy of the Apache2.0 license and are unable|
10   | to obtain it through the world-wide-web, please send a note to       |
11   | license@swoole.com so we can mail you a copy immediately.            |
12   +----------------------------------------------------------------------+
13   | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
14   |         Twosee  <twose@qq.com>                                       |
15   +----------------------------------------------------------------------+
16 */
17 
18 #pragma once
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #elif defined(ENABLE_PHP_SWOOLE)
23 #include "php_config.h"
24 #endif
25 
26 #ifdef __cplusplus
27 #define SW_EXTERN_C_BEGIN extern "C" {
28 #define SW_EXTERN_C_END }
29 #else
30 #define SW_EXTERN_C_BEGIN
31 #define SW_EXTERN_C_END
32 #endif
33 
34 #ifndef _GNU_SOURCE
35 #define _GNU_SOURCE
36 #endif
37 
38 #ifndef _PTHREAD_PSHARED
39 #define _PTHREAD_PSHARED
40 #endif
41 
42 /*--- C standard library ---*/
43 #include <assert.h>
44 #include <ctype.h>
45 #include <errno.h>
46 #include <stdarg.h>
47 #include <stddef.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <limits.h>
52 #include <unistd.h>
53 #include <sched.h> /* sched_yield() */
54 #include <pthread.h>
55 
56 #include <sys/utsname.h>
57 #include <sys/time.h>
58 
59 #include <memory>
60 #include <functional>
61 
62 typedef unsigned long ulong_t;
63 
64 #ifndef PRId64
65 #define PRId64 "lld"
66 #endif
67 
68 #ifndef PRIu64
69 #define PRIu64 "llu"
70 #endif
71 
72 #ifndef PRIx64
73 #define PRIx64 "llx"
74 #endif
75 
76 #if defined(__GNUC__)
77 #if __GNUC__ >= 3
78 #define sw_inline inline __attribute__((always_inline))
79 #else
80 #define sw_inline inline
81 #endif
82 #elif defined(_MSC_VER)
83 #define sw_inline __forceinline
84 #else
85 #define sw_inline inline
86 #endif
87 
88 #if defined(__GNUC__) && __GNUC__ >= 4
89 #define SW_API __attribute__((visibility("default")))
90 #else
91 #define SW_API
92 #endif
93 
94 #if !defined(__GNUC__) || __GNUC__ < 3
95 #define __builtin_expect(x, expected_value) (x)
96 #endif
97 
98 #define sw_likely(x) __builtin_expect(!!(x), 1)
99 #define sw_unlikely(x) __builtin_expect(!!(x), 0)
100 
101 #define SW_START_LINE "-------------------------START----------------------------"
102 #define SW_END_LINE "--------------------------END-----------------------------"
103 #define SW_ECHO_RED "\e[31m%s\e[0m"
104 #define SW_ECHO_GREEN "\e[32m%s\e[0m"
105 #define SW_ECHO_YELLOW "\e[33m%s\e[0m"
106 #define SW_ECHO_BLUE "\e[34m%s\e[0m"
107 #define SW_ECHO_MAGENTA "\e[35m%s\e[0m"
108 #define SW_ECHO_CYAN "\e[36m%s\e[0m"
109 #define SW_ECHO_WHITE "\e[37m%s\e[0m"
110 
111 #define SW_ECHO_LEN_RED "\e[31m%.*s\e[0m"
112 #define SW_ECHO_LEN_GREEN "\e[32m%.*s\e[0m"
113 #define SW_ECHO_LEN_YELLOW "\e[33m%.*s\e[0m"
114 #define SW_ECHO_LEN_BLUE "\e[34m%.*s\e[0m"
115 #define SW_ECHO_LEN_MAGENTA "\e[35m%.*s\e[0m"
116 #define SW_ECHO_LEN_CYAN "\e[36m%.*s\e[0m"
117 #define SW_ECHO_LEN_WHITE "\e[37m%.*s\e[0m"
118 
119 #define SW_COLOR_RED 1
120 #define SW_COLOR_GREEN 2
121 #define SW_COLOR_YELLOW 3
122 #define SW_COLOR_BLUE 4
123 #define SW_COLOR_MAGENTA 5
124 #define SW_COLOR_CYAN 6
125 #define SW_COLOR_WHITE 7
126 
127 #define SW_SPACE ' '
128 #define SW_CRLF "\r\n"
129 #define SW_CRLF_LEN 2
130 #define SW_ASCII_CODE_0 64
131 #define SW_ASCII_CODE_Z 106
132 /*----------------------------------------------------------------------------*/
133 
134 #include "swoole_config.h"
135 #include "swoole_version.h"
136 #include "swoole_log.h"
137 #include "swoole_atomic.h"
138 #include "swoole_error.h"
139 
140 #define SW_MAX(A, B) ((A) > (B) ? (A) : (B))
141 #define SW_MIN(A, B) ((A) < (B) ? (A) : (B))
142 #define SW_LOOP_N(n) for (decltype(n) i = 0; i < n; i++)
143 #define SW_LOOP for (;;)
144 
145 #ifndef MAX
146 #define MAX(A, B) SW_MAX(A, B)
147 #endif
148 #ifndef MIN
149 #define MIN(A, B) SW_MIN(A, B)
150 #endif
151 
152 #define SW_NUM_BILLION (1000 * 1000 * 1000)
153 #define SW_NUM_MILLION (1000 * 1000)
154 
155 #ifdef SW_DEBUG
156 #define SW_ASSERT(e) assert(e)
157 #define SW_ASSERT_1BYTE(v)                                                                                             \
158     do {                                                                                                               \
159         size_t i = 0, n = 0;                                                                                           \
160         for (; i < sizeof(v); i++) {                                                                                   \
161             n += ((v >> i) & 1) ? 1 : 0;                                                                               \
162         }                                                                                                              \
163         assert(n == 1);                                                                                                \
164     } while (0)
165 #else
166 #define SW_ASSERT(e)
167 #define SW_ASSERT_1BYTE(v)
168 #endif
169 #define SW_START_SLEEP usleep(100000)  // sleep 1s,wait fork and pthread_create
170 
171 /*-----------------------------------Memory------------------------------------*/
172 void *sw_malloc(size_t size);
173 void sw_free(void *ptr);
174 void *sw_calloc(size_t nmemb, size_t size);
175 void *sw_realloc(void *ptr, size_t size);
176 
177 // Evaluates to the number of elements in 'array'
178 #define SW_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
179 
180 #define SW_DEFAULT_ALIGNMENT sizeof(unsigned long)
181 #define SW_MEM_ALIGNED_SIZE(size) SW_MEM_ALIGNED_SIZE_EX(size, SW_DEFAULT_ALIGNMENT)
182 #define SW_MEM_ALIGNED_SIZE_EX(size, alignment) (((size) + ((alignment) -1LL)) & ~((alignment) -1LL))
183 
184 /*-------------------------------Declare Struct--------------------------------*/
185 namespace swoole {
186 class MemoryPool;
187 class Reactor;
188 class String;
189 class Timer;
190 struct TimerNode;
191 struct Event;
192 class Pipe;
193 namespace network {
194 struct Socket;
195 struct Address;
196 }  // namespace network
197 class AsyncThreads;
198 namespace async {
199 class ThreadPool;
200 }
201 struct Protocol;
202 struct EventData;
203 struct DataHead;
204 typedef int (*ReactorHandler)(Reactor *reactor, Event *event);
205 typedef std::function<void(void *)> Callback;
206 typedef std::function<void(Timer *, TimerNode *)> TimerCallback;
207 }  // namespace swoole
208 
209 typedef swoole::Reactor swReactor;
210 typedef swoole::String swString;
211 typedef swoole::Timer swTimer;
212 typedef swoole::network::Socket swSocket;
213 typedef swoole::Protocol swProtocol;
214 typedef swoole::EventData swEventData;
215 typedef swoole::DataHead swDataHead;
216 typedef swoole::Event swEvent;
217 
218 /*----------------------------------String-------------------------------------*/
219 
220 #define SW_STRS(s) s, sizeof(s)
221 #define SW_STRL(s) s, sizeof(s) - 1
222 
223 #define SW_STREQ(str, len, const_str) swoole_streq(str, len, SW_STRL(const_str))
224 #define SW_STRCASEEQ(str, len, const_str) swoole_strcaseeq(str, len, SW_STRL(const_str))
225 
226 /* string contain */
227 #define SW_STRCT(str, len, const_sub_str) swoole_strct(str, len, SW_STRL(const_sub_str))
228 #define SW_STRCASECT(str, len, const_sub_str) swoole_strcasect(str, len, SW_STRL(const_sub_str))
229 
230 #if defined(SW_USE_JEMALLOC) || defined(SW_USE_TCMALLOC)
231 #define sw_strdup swoole_strdup
232 #define sw_strndup swoole_strndup
233 #else
234 #define sw_strdup strdup
235 #define sw_strndup strndup
236 #endif
237 
238 /** always return less than size, zero termination  */
239 size_t sw_snprintf(char *buf, size_t size, const char *format, ...) __attribute__((format(printf, 3, 4)));
240 size_t sw_vsnprintf(char *buf, size_t size, const char *format, va_list args);
241 
242 #define sw_memset_zero(s, n) memset(s, '\0', n)
243 
sw_mem_equal(const void * v1,size_t s1,const void * v2,size_t s2)244 static sw_inline int sw_mem_equal(const void *v1, size_t s1, const void *v2, size_t s2) {
245     return s1 == s2 && memcmp(v1, v2, s2) == 0;
246 }
247 
swoole_strlcpy(char * dest,const char * src,size_t size)248 static inline size_t swoole_strlcpy(char *dest, const char *src, size_t size) {
249     const size_t len = strlen(src);
250     if (size != 0) {
251         const size_t n = std::min(len, size - 1);
252         memcpy(dest, src, n);
253         dest[n] = '\0';
254     }
255     return len;
256 }
257 
swoole_strdup(const char * s)258 static inline char *swoole_strdup(const char *s) {
259     size_t l = strlen(s) + 1;
260     char *p = (char *) sw_malloc(l);
261     if (sw_likely(p)) {
262         memcpy(p, s, l);
263     }
264     return p;
265 }
266 
swoole_strndup(const char * s,size_t n)267 static inline char *swoole_strndup(const char *s, size_t n) {
268     char *p = (char *) sw_malloc(n + 1);
269     if (sw_likely(p)) {
270         strncpy(p, s, n)[n] = '\0';
271     }
272     return p;
273 }
274 
275 /* string equal */
swoole_streq(const char * str1,size_t len1,const char * str2,size_t len2)276 static inline unsigned int swoole_streq(const char *str1, size_t len1, const char *str2, size_t len2) {
277     return (len1 == len2) && (strncmp(str1, str2, len1) == 0);
278 }
279 
swoole_strcaseeq(const char * str1,size_t len1,const char * str2,size_t len2)280 static inline unsigned int swoole_strcaseeq(const char *str1, size_t len1, const char *str2, size_t len2) {
281     return (len1 == len2) && (strncasecmp(str1, str2, len1) == 0);
282 }
283 
swoole_strct(const char * pstr,size_t plen,const char * sstr,size_t slen)284 static inline unsigned int swoole_strct(const char *pstr, size_t plen, const char *sstr, size_t slen) {
285     return (plen >= slen) && (strncmp(pstr, sstr, slen) == 0);
286 }
287 
swoole_strcasect(const char * pstr,size_t plen,const char * sstr,size_t slen)288 static inline unsigned int swoole_strcasect(const char *pstr, size_t plen, const char *sstr, size_t slen) {
289     return (plen >= slen) && (strncasecmp(pstr, sstr, slen) == 0);
290 }
291 
swoole_strnstr(const char * haystack,uint32_t haystack_length,const char * needle,uint32_t needle_length)292 static inline const char *swoole_strnstr(const char *haystack,
293                                          uint32_t haystack_length,
294                                          const char *needle,
295                                          uint32_t needle_length) {
296     assert(needle_length > 0);
297     uint32_t i;
298 
299     if (sw_likely(needle_length <= haystack_length)) {
300         for (i = 0; i < haystack_length - needle_length + 1; i++) {
301             if ((haystack[0] == needle[0]) && (0 == memcmp(haystack, needle, needle_length))) {
302                 return haystack;
303             }
304             haystack++;
305         }
306     }
307 
308     return NULL;
309 }
310 
swoole_strnpos(const char * haystack,uint32_t haystack_length,const char * needle,uint32_t needle_length)311 static inline ssize_t swoole_strnpos(const char *haystack,
312                                      uint32_t haystack_length,
313                                      const char *needle,
314                                      uint32_t needle_length) {
315     assert(needle_length > 0);
316     const char *pos;
317 
318     pos = swoole_strnstr(haystack, haystack_length, needle, needle_length);
319     return pos == NULL ? -1 : pos - haystack;
320 }
321 
swoole_strrnpos(const char * haystack,const char * needle,uint32_t length)322 static inline ssize_t swoole_strrnpos(const char *haystack, const char *needle, uint32_t length) {
323     uint32_t needle_length = strlen(needle);
324     assert(needle_length > 0);
325     uint32_t i;
326     haystack += (length - needle_length);
327 
328     for (i = length - needle_length; i > 0; i--) {
329         if ((haystack[0] == needle[0]) && (0 == memcmp(haystack, needle, needle_length))) {
330             return i;
331         }
332         haystack--;
333     }
334 
335     return -1;
336 }
337 
swoole_strtolower(char * str,int length)338 static inline void swoole_strtolower(char *str, int length) {
339     char *c, *e;
340 
341     c = str;
342     e = c + length;
343 
344     while (c < e) {
345         *c = tolower(*c);
346         c++;
347     }
348 }
349 
350 /*--------------------------------Constants------------------------------------*/
351 enum swResultCode {
352     SW_OK = 0,
353     SW_ERR = -1,
354 };
355 
356 enum swReturnCode {
357     SW_CONTINUE = 1,
358     SW_WAIT = 2,
359     SW_CLOSE = 3,
360     SW_ERROR = 4,
361     SW_READY = 5,
362     SW_INVALID = 6,
363 };
364 
365 enum swFdType {
366     SW_FD_SESSION,        // server stream session
367     SW_FD_STREAM_SERVER,  // server stream port
368     SW_FD_DGRAM_SERVER,   // server dgram port
369     SW_FD_PIPE,
370     SW_FD_STREAM,
371     SW_FD_AIO,
372     /**
373      * Coroutine Socket
374      */
375     SW_FD_CO_SOCKET,
376     /**
377      * socket poll fd [coroutine::socket_poll]
378      */
379     SW_FD_CO_POLL,
380     /**
381      * event waiter
382      */
383     SW_FD_CO_EVENT,
384     /**
385      * signalfd
386      */
387     SW_FD_SIGNAL,
388     SW_FD_DNS_RESOLVER,
389     SW_FD_CARES,
390     /**
391      * SW_FD_USER or SW_FD_USER+n: for custom event
392      */
393     SW_FD_USER = 16,
394     SW_FD_STREAM_CLIENT,
395     SW_FD_DGRAM_CLIENT,
396 };
397 
398 enum swSocketFlag {
399     SW_SOCK_NONBLOCK = 1 << 2,
400     SW_SOCK_CLOEXEC = 1 << 3,
401     SW_SOCK_SSL = (1u << 9),
402 };
403 
404 enum swSocketType {
405     SW_SOCK_TCP = 1,
406     SW_SOCK_UDP = 2,
407     SW_SOCK_TCP6 = 3,
408     SW_SOCK_UDP6 = 4,
409     SW_SOCK_UNIX_STREAM = 5,  // unix sock stream
410     SW_SOCK_UNIX_DGRAM = 6,   // unix sock dgram
411     SW_SOCK_RAW = 7,
412 };
413 
414 enum swEventType {
415     SW_EVENT_NULL = 0,
416     SW_EVENT_DEAULT = 1u << 8,
417     SW_EVENT_READ = 1u << 9,
418     SW_EVENT_WRITE = 1u << 10,
419     SW_EVENT_RDWR = SW_EVENT_READ | SW_EVENT_WRITE,
420     SW_EVENT_ERROR = 1u << 11,
421     SW_EVENT_ONCE = 1u << 12,
422 };
423 
424 enum swForkType {
425     SW_FORK_SPAWN = 0,
426     SW_FORK_EXEC = 1 << 1,
427     SW_FORK_DAEMON = 1 << 2,
428     SW_FORK_PRECHECK = 1 << 3,
429 };
430 
431 //-------------------------------------------------------------------------------
432 #define sw_yield() sched_yield()
433 
434 //------------------------------Base--------------------------------
435 #ifndef uchar
436 typedef unsigned char uchar;
437 #endif
438 
439 #define swoole_tolower(c) (uchar)((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
440 #define swoole_toupper(c) (uchar)((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)
441 
442 void swoole_random_string(char *buf, size_t size);
443 size_t swoole_random_bytes(char *buf, size_t size);
444 
swoole_strlchr(char * p,char * last,char c)445 static sw_inline char *swoole_strlchr(char *p, char *last, char c) {
446     while (p < last) {
447         if (*p == c) {
448             return p;
449         }
450         p++;
451     }
452     return NULL;
453 }
454 
swoole_size_align(size_t size,int pagesize)455 static sw_inline size_t swoole_size_align(size_t size, int pagesize) {
456     return size + (pagesize - (size % pagesize));
457 }
458 
459 //------------------------------Base--------------------------------
460 enum swEventDataFlag {
461     SW_EVENT_DATA_NORMAL,
462     SW_EVENT_DATA_PTR = 1u << 1,
463     SW_EVENT_DATA_CHUNK = 1u << 2,
464     SW_EVENT_DATA_BEGIN = 1u << 3,
465     SW_EVENT_DATA_END = 1u << 4,
466     SW_EVENT_DATA_OBJ_PTR = 1u << 5,
467     SW_EVENT_DATA_POP_PTR = 1u << 6,
468 };
469 
470 enum swTaskFlag {
471     SW_TASK_TMPFILE = 1,
472     SW_TASK_SERIALIZE = 1u << 1,
473     SW_TASK_NONBLOCK = 1u << 2,
474     SW_TASK_CALLBACK = 1u << 3,
475     SW_TASK_WAITALL = 1u << 4,
476     SW_TASK_COROUTINE = 1u << 5,
477     SW_TASK_PEEK = 1u << 6,
478     SW_TASK_NOREPLY = 1u << 7,
479 };
480 
481 enum swDNSLookupFlag {
482     SW_DNS_LOOKUP_RANDOM = (1u << 11),
483 };
484 
485 #ifdef __MACH__
486 char *sw_error_();
487 #define sw_error sw_error_()
488 #else
489 extern __thread char sw_error[SW_ERROR_MSG_SIZE];
490 #endif
491 
492 enum swProcessType {
493     SW_PROCESS_MASTER = 1,
494     SW_PROCESS_WORKER = 2,
495     SW_PROCESS_MANAGER = 3,
496     SW_PROCESS_TASKWORKER = 4,
497     SW_PROCESS_USERWORKER = 5,
498 };
499 
500 enum swPipeType {
501     SW_PIPE_WORKER = 0,
502     SW_PIPE_MASTER = 1,
503     SW_PIPE_READ = 0,
504     SW_PIPE_WRITE = 1,
505     SW_PIPE_NONBLOCK = 2,
506 };
507 
508 //----------------------Tool Function---------------------
509 uint32_t swoole_common_multiple(uint32_t u, uint32_t v);
510 uint32_t swoole_common_divisor(uint32_t u, uint32_t v);
511 
512 int swoole_itoa(char *buf, long value);
513 bool swoole_mkdir_recursive(const std::string &dir);
514 
515 int swoole_rand(int min, int max);
516 int swoole_system_random(int min, int max);
517 
518 int swoole_version_compare(const char *version1, const char *version2);
519 void swoole_print_backtrace(void);
520 char *swoole_string_format(size_t n, const char *format, ...);
521 bool swoole_get_env(const char *name, int *value);
522 int swoole_get_systemd_listen_fds();
523 
524 void swoole_init(void);
525 void swoole_clean(void);
526 pid_t swoole_fork(int flags);
527 void swoole_redirect_stdout(int new_fd);
528 int swoole_shell_exec(const char *command, pid_t *pid, bool get_error_stream);
529 int swoole_daemon(int nochdir, int noclose);
530 bool swoole_set_task_tmpdir(const std::string &dir);
531 int swoole_tmpfile(char *filename);
532 
533 #ifdef HAVE_CPU_AFFINITY
534 #ifdef __FreeBSD__
535 #include <sys/types.h>
536 #include <sys/cpuset.h>
537 #include <pthread_np.h>
538 typedef cpuset_t cpu_set_t;
539 #endif
540 #ifdef __DragonFly__
541 #include <pthread_np.h>
542 #endif
543 int swoole_set_cpu_affinity(cpu_set_t *set);
544 #endif
545 
546 #ifdef HAVE_CLOCK_GETTIME
547 #define swoole_clock_gettime clock_gettime
548 #else
549 int swoole_clock_gettime(int which_clock, struct timespec *t);
550 #endif
551 
swoole_time_until(int milliseconds)552 static inline struct timespec swoole_time_until(int milliseconds) {
553     struct timespec t;
554     swoole_clock_gettime(CLOCK_REALTIME, &t);
555 
556     int sec = milliseconds / 1000;
557     int msec = milliseconds - (sec * 1000);
558 
559     t.tv_sec += sec;
560     t.tv_nsec += msec * 1000 * 1000;
561 
562     if (t.tv_nsec > SW_NUM_BILLION) {
563         int _sec = t.tv_nsec / SW_NUM_BILLION;
564         t.tv_sec += _sec;
565         t.tv_nsec -= _sec * SW_NUM_BILLION;
566     }
567 
568     return t;
569 }
570 
571 namespace swoole {
572 
573 typedef long SessionId;
574 typedef long TaskId;
575 typedef uint8_t ReactorId;
576 typedef uint32_t WorkerId;
577 typedef enum swEventType EventType;
578 typedef enum swSocketType SocketType;
579 typedef enum swFdType FdType;
580 typedef enum swReturnCode ReturnCode;
581 typedef enum swResultCode ResultCode;
582 
583 struct Event {
584     int fd;
585     int16_t reactor_id;
586     FdType type;
587     network::Socket *socket;
588 };
589 
590 struct DataHead {
591     SessionId fd;
592     uint64_t msg_id;
593     uint32_t len;
594     int16_t reactor_id;
595     uint8_t type;
596     uint8_t flags;
597     uint16_t server_fd;
598     uint16_t ext_flags;
599     uint32_t reserved;
600     double time;
601     size_t dump(char *buf, size_t len);
602     void print();
603 };
604 
605 struct EventData {
606     DataHead info;
607     char data[SW_IPC_BUFFER_SIZE];
608 };
609 
610 struct SendData {
611     DataHead info;
612     const char *data;
613 };
614 
615 struct RecvData {
616     DataHead info;
617     const char *data;
618 };
619 
620 struct ThreadGlobal {
621     uint16_t id;
622     uint8_t type;
623     String *buffer_stack;
624     Reactor *reactor;
625     Timer *timer;
626     AsyncThreads *async_threads;
627     uint32_t signal_listener_num;
628     uint32_t co_signal_listener_num;
629     int error;
630 };
631 
632 struct Allocator {
633     void *(*malloc)(size_t size);
634     void *(*calloc)(size_t nmemb, size_t size);
635     void *(*realloc)(void *ptr, size_t size);
636     void (*free)(void *ptr);
637 };
638 
639 struct Global {
640     uchar init : 1;
641     uchar running : 1;
642     uchar use_signalfd : 1;
643     uchar wait_signal : 1;
644     uchar enable_signalfd : 1;
645     uchar socket_dontwait : 1;
646     uchar dns_lookup_random : 1;
647     uchar use_async_resolver : 1;
648 
649     int process_type;
650     uint32_t process_id;
651     TaskId current_task_id;
652     pid_t pid;
653 
654     int signal_fd;
655     bool signal_alarm;
656 
657     long trace_flags;
658 
659     void (*fatal_error)(int code, const char *str, ...);
660 
661     //-----------------------[System]--------------------------
662     uint16_t cpu_num;
663     uint32_t pagesize;
664     struct utsname uname;
665     uint32_t max_sockets;
666     //-----------------------[Memory]--------------------------
667     MemoryPool *memory_pool;
668     Allocator std_allocator;
669     std::string task_tmpfile;
670     //-----------------------[DNS]--------------------------
671     std::string dns_server_host;
672     int dns_server_port;
673     double dns_cache_refresh_time;
674     int dns_tries;
675     std::string dns_resolvconf_path;
676     std::string dns_hosts_path;
677     //-----------------------[AIO]--------------------------
678     uint32_t aio_core_worker_num;
679     uint32_t aio_worker_num;
680     double aio_max_wait_time;
681     double aio_max_idle_time;
682     network::Socket *aio_default_socket;
683     //-----------------------[Hook]--------------------------
684     void *hooks[SW_MAX_HOOK_TYPE];
685     std::function<bool(Reactor *reactor, size_t &event_num)> user_exit_condition;
686     // bug report message
687     std::string bug_report_message;
688 };
689 
690 std::string dirname(const std::string &file);
691 int hook_add(void **hooks, int type, const Callback &func, int push_back);
692 void hook_call(void **hooks, int type, void *arg);
693 double microtime(void);
694 }  // namespace swoole
695 
696 extern swoole::Global SwooleG;                  // Local Global Variable
697 extern __thread swoole::ThreadGlobal SwooleTG;  // Thread Global Variable
698 
699 #define SW_CPU_NUM (SwooleG.cpu_num)
700 
swoole_set_last_error(int error)701 static inline void swoole_set_last_error(int error) {
702     SwooleTG.error = error;
703 }
704 
swoole_get_last_error()705 static inline int swoole_get_last_error() {
706     return SwooleTG.error;
707 }
708 
swoole_get_thread_id()709 static inline int swoole_get_thread_id() {
710     return SwooleTG.id;
711 }
712 
swoole_get_process_type()713 static inline int swoole_get_process_type() {
714     return SwooleG.process_type;
715 }
716 
swoole_get_process_id()717 static inline int swoole_get_process_id() {
718     return SwooleG.process_id;
719 }
720 
721 SW_API const char *swoole_strerror(int code);
722 SW_API void swoole_throw_error(int code);
723 SW_API void swoole_ignore_error(int code);
724 SW_API bool swoole_is_ignored_error(int code);
725 SW_API void swoole_set_log_level(int level);
726 SW_API void swoole_set_trace_flags(int flags);
727 SW_API void swoole_set_dns_server(const std::string &server);
728 SW_API void swoole_set_hosts_path(const std::string &hosts_file);
729 SW_API std::pair<std::string, int> swoole_get_dns_server();
730 SW_API bool swoole_load_resolv_conf();
731 
732 //-----------------------------------------------
sw_spinlock(sw_atomic_t * lock)733 static sw_inline void sw_spinlock(sw_atomic_t *lock) {
734     uint32_t i, n;
735     while (1) {
736         if (*lock == 0 && sw_atomic_cmp_set(lock, 0, 1)) {
737             return;
738         }
739         if (SW_CPU_NUM > 1) {
740             for (n = 1; n < SW_SPINLOCK_LOOP_N; n <<= 1) {
741                 for (i = 0; i < n; i++) {
742                     sw_atomic_cpu_pause();
743                 }
744 
745                 if (*lock == 0 && sw_atomic_cmp_set(lock, 0, 1)) {
746                     return;
747                 }
748             }
749         }
750         sw_yield();
751     }
752 }
753 
sw_tg_buffer()754 static sw_inline swoole::String *sw_tg_buffer() {
755     return SwooleTG.buffer_stack;
756 }
757 
sw_mem_pool()758 static sw_inline swoole::MemoryPool *sw_mem_pool() {
759     return SwooleG.memory_pool;
760 }
761 
sw_std_allocator()762 static sw_inline const swoole::Allocator *sw_std_allocator() {
763     return &SwooleG.std_allocator;
764 }
765