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