You've already forked qlg.tsgz.moe
Init Repo
This commit is contained in:
676
vendor/swoole/src/os/base.c
vendored
Executable file
676
vendor/swoole/src/os/base.c
vendored
Executable file
@ -0,0 +1,676 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2012-2018 The Swoole Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include "async.h"
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
swAsyncIO SwooleAIO;
|
||||
swPipe swoole_aio_pipe;
|
||||
|
||||
static void swAioBase_destroy();
|
||||
static int swAioBase_read(int fd, void *inbuf, size_t size, off_t offset);
|
||||
static int swAioBase_write(int fd, void *inbuf, size_t size, off_t offset);
|
||||
static int swAioBase_thread_onTask(swThreadPool *pool, void *task, int task_len);
|
||||
static int swAioBase_onFinish(swReactor *reactor, swEvent *event);
|
||||
|
||||
static void swAio_handler_read(swAio_event *event);
|
||||
static void swAio_handler_write(swAio_event *event);
|
||||
static void swAio_handler_gethostbyname(swAio_event *event);
|
||||
static void swAio_handler_getaddrinfo(swAio_event *event);
|
||||
static void swAio_handler_stream_get_line(swAio_event *event);
|
||||
static void swAio_handler_read_file(swAio_event *event);
|
||||
static void swAio_handler_write_file(swAio_event *event);
|
||||
|
||||
static swThreadPool swAioBase_thread_pool;
|
||||
static int swAioBase_pipe_read;
|
||||
static int swAioBase_pipe_write;
|
||||
|
||||
int swAio_init(void)
|
||||
{
|
||||
if (SwooleAIO.init)
|
||||
{
|
||||
swWarn("AIO has already been initialized");
|
||||
return SW_ERR;
|
||||
}
|
||||
if (!SwooleG.main_reactor)
|
||||
{
|
||||
swWarn("No eventloop, cannot initialized");
|
||||
return SW_ERR;
|
||||
}
|
||||
return swAioBase_init(SW_AIO_EVENT_NUM);
|
||||
}
|
||||
|
||||
void swAio_free(void)
|
||||
{
|
||||
if (!SwooleAIO.init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SwooleAIO.destroy();
|
||||
SwooleAIO.init = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* for test
|
||||
*/
|
||||
void swAio_callback_test(swAio_event *aio_event)
|
||||
{
|
||||
printf("content=%s\n", (char *)aio_event->buf);
|
||||
printf("fd: %d, request_type: %s, offset: %ld, length: %lu\n", aio_event->fd,
|
||||
(aio_event == SW_AIO_READ) ? "READ" : "WRITE", (long)aio_event->offset, aio_event->nbytes);
|
||||
SwooleG.running = 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_DAEMON
|
||||
int daemon(int nochdir, int noclose)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
if (!nochdir && chdir("/") != 0)
|
||||
{
|
||||
swWarn("chdir() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!noclose)
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
swWarn("open() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dup2(fd, 0) < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0)
|
||||
{
|
||||
close(fd);
|
||||
swWarn("dup2() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
{
|
||||
swWarn("fork() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
if (pid > 0)
|
||||
{
|
||||
_exit(0);
|
||||
}
|
||||
if (setsid() < 0)
|
||||
{
|
||||
swWarn("setsid() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int swAioBase_onFinish(swReactor *reactor, swEvent *event)
|
||||
{
|
||||
int i;
|
||||
swAio_event *events[SW_AIO_EVENT_NUM];
|
||||
int n = read(event->fd, events, sizeof(swAio_event*) * SW_AIO_EVENT_NUM);
|
||||
if (n < 0)
|
||||
{
|
||||
swWarn("read() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
for (i = 0; i < n / sizeof(swAio_event*); i++)
|
||||
{
|
||||
if (events[i]->callback)
|
||||
{
|
||||
events[i]->callback(events[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
SwooleAIO.callback(events[i]);
|
||||
}
|
||||
SwooleAIO.task_num--;
|
||||
sw_free(events[i]);
|
||||
}
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
int swAioBase_init(int max_aio_events)
|
||||
{
|
||||
if (swPipeBase_create(&swoole_aio_pipe, 0) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
if (swMutex_create(&SwooleAIO.lock, 0) < 0)
|
||||
{
|
||||
swWarn("create mutex lock error.");
|
||||
return SW_ERR;
|
||||
}
|
||||
if (SwooleAIO.thread_num <= 0)
|
||||
{
|
||||
SwooleAIO.thread_num = SW_AIO_THREAD_NUM_DEFAULT;
|
||||
}
|
||||
if (swThreadPool_create(&swAioBase_thread_pool, SwooleAIO.thread_num) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
swAioBase_thread_pool.onTask = swAioBase_thread_onTask;
|
||||
|
||||
swAioBase_pipe_read = swoole_aio_pipe.getFd(&swoole_aio_pipe, 0);
|
||||
swAioBase_pipe_write = swoole_aio_pipe.getFd(&swoole_aio_pipe, 1);
|
||||
|
||||
SwooleAIO.handlers[SW_AIO_READ] = swAio_handler_read;
|
||||
SwooleAIO.handlers[SW_AIO_WRITE] = swAio_handler_write;
|
||||
SwooleAIO.handlers[SW_AIO_GETHOSTBYNAME] = swAio_handler_gethostbyname;
|
||||
SwooleAIO.handlers[SW_AIO_GETADDRINFO] = swAio_handler_getaddrinfo;
|
||||
SwooleAIO.handlers[SW_AIO_STREAM_GET_LINE] = swAio_handler_stream_get_line;
|
||||
SwooleAIO.handlers[SW_AIO_READ_FILE] = swAio_handler_read_file;
|
||||
SwooleAIO.handlers[SW_AIO_WRITE_FILE] = swAio_handler_write_file;
|
||||
|
||||
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_AIO, swAioBase_onFinish);
|
||||
SwooleG.main_reactor->add(SwooleG.main_reactor, swAioBase_pipe_read, SW_FD_AIO);
|
||||
|
||||
if (swThreadPool_run(&swAioBase_thread_pool) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
SwooleAIO.destroy = swAioBase_destroy;
|
||||
SwooleAIO.read = swAioBase_read;
|
||||
SwooleAIO.write = swAioBase_write;
|
||||
SwooleAIO.init = 1;
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static void swAio_handler_read(swAio_event *event)
|
||||
{
|
||||
int ret = -1;
|
||||
if (flock(event->fd, LOCK_SH) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_SH) failed.", event->fd);
|
||||
event->ret = -1;
|
||||
event->error = errno;
|
||||
return;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
ret = pread(event->fd, event->buf, event->nbytes, event->offset);
|
||||
if (ret < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (flock(event->fd, LOCK_UN) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
|
||||
}
|
||||
event->ret = ret;
|
||||
}
|
||||
|
||||
static inline char* find_eol(char *buf, size_t size)
|
||||
{
|
||||
char *eol = memchr(buf, '\n', size);
|
||||
if (!eol)
|
||||
{
|
||||
eol = memchr(buf, '\r', size);
|
||||
}
|
||||
return eol;
|
||||
}
|
||||
|
||||
static void swAio_handler_stream_get_line(swAio_event *event)
|
||||
{
|
||||
int ret = -1;
|
||||
if (flock(event->fd, LOCK_SH) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_SH) failed.", event->fd);
|
||||
event->ret = -1;
|
||||
event->error = errno;
|
||||
return;
|
||||
}
|
||||
|
||||
off_t readpos = event->offset;
|
||||
off_t writepos = (long) event->req;
|
||||
size_t avail = 0;
|
||||
char *eol;
|
||||
char *tmp;
|
||||
|
||||
char *read_buf = event->buf;
|
||||
int read_n = event->nbytes;
|
||||
|
||||
while (1)
|
||||
{
|
||||
avail = writepos - readpos;
|
||||
|
||||
swTraceLog(SW_TRACE_AIO, "readpos=%ld, writepos=%ld", (long)readpos, (long)writepos);
|
||||
|
||||
if (avail > 0)
|
||||
{
|
||||
tmp = event->buf + readpos;
|
||||
eol = find_eol(tmp, avail);
|
||||
if (eol)
|
||||
{
|
||||
event->buf = tmp;
|
||||
event->ret = (eol - tmp) + 1;
|
||||
readpos += event->ret;
|
||||
goto _return;
|
||||
}
|
||||
else if (readpos == 0)
|
||||
{
|
||||
if (writepos == event->nbytes)
|
||||
{
|
||||
writepos = 0;
|
||||
event->ret = event->nbytes;
|
||||
goto _return;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->flags = SW_AIO_EOF;
|
||||
((char*) event->buf)[writepos] = '\0';
|
||||
event->ret = writepos;
|
||||
writepos = 0;
|
||||
goto _return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(event->buf, event->buf + readpos, avail);
|
||||
writepos = avail;
|
||||
read_buf = event->buf + writepos;
|
||||
read_n = event->nbytes - writepos;
|
||||
readpos = 0;
|
||||
goto _readfile;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_readfile: while (1)
|
||||
{
|
||||
ret = read(event->fd, read_buf, read_n);
|
||||
if (ret < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ret > 0)
|
||||
{
|
||||
writepos += ret;
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
event->flags = SW_AIO_EOF;
|
||||
if (writepos > 0)
|
||||
{
|
||||
event->ret = writepos;
|
||||
}
|
||||
else
|
||||
{
|
||||
((char*) event->buf)[0] = '\0';
|
||||
event->ret = 0;
|
||||
}
|
||||
readpos = writepos = 0;
|
||||
goto _return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_return:
|
||||
if (flock(event->fd, LOCK_UN) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
|
||||
}
|
||||
event->offset = readpos;
|
||||
event->req = (void *) (long) writepos;
|
||||
}
|
||||
|
||||
static void swAio_handler_read_file(swAio_event *event)
|
||||
{
|
||||
int ret = -1;
|
||||
int fd = open(event->req, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
swSysError("open(%s, O_RDONLY) failed.", (char * )event->req);
|
||||
event->ret = ret;
|
||||
event->error = errno;
|
||||
return;
|
||||
}
|
||||
struct stat file_stat;
|
||||
if (fstat(fd, &file_stat) < 0)
|
||||
{
|
||||
swSysError("fstat(%s) failed.", (char * )event->req);
|
||||
_error: close(fd);
|
||||
event->ret = ret;
|
||||
event->error = errno;
|
||||
return;
|
||||
}
|
||||
if ((file_stat.st_mode & S_IFMT) != S_IFREG)
|
||||
{
|
||||
errno = EISDIR;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
long filesize = file_stat.st_size;
|
||||
if (filesize == 0)
|
||||
{
|
||||
errno = SW_ERROR_FILE_EMPTY;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
if (flock(fd, LOCK_SH) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_SH) failed.", event->fd);
|
||||
goto _error;
|
||||
}
|
||||
|
||||
event->buf = sw_malloc(filesize);
|
||||
if (event->buf == NULL)
|
||||
{
|
||||
goto _error;
|
||||
}
|
||||
int readn = swoole_sync_readfile(fd, event->buf, (int) filesize);
|
||||
if (flock(fd, LOCK_UN) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
|
||||
}
|
||||
close(fd);
|
||||
event->ret = readn;
|
||||
event->error = 0;
|
||||
}
|
||||
|
||||
static void swAio_handler_write_file(swAio_event *event)
|
||||
{
|
||||
int ret = -1;
|
||||
int fd = open(event->req, event->flags, 0644);
|
||||
if (fd < 0)
|
||||
{
|
||||
swSysError("open(%s, %d) failed.", (char * )event->req, event->flags);
|
||||
event->ret = ret;
|
||||
event->error = errno;
|
||||
return;
|
||||
}
|
||||
if (flock(fd, LOCK_EX) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_EX) failed.", event->fd);
|
||||
event->ret = ret;
|
||||
event->error = errno;
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
int written = swoole_sync_writefile(fd, event->buf, event->nbytes);
|
||||
if (event->flags & SW_AIO_WRITE_FSYNC)
|
||||
{
|
||||
if (fsync(fd) < 0)
|
||||
{
|
||||
swSysError("fsync(%d) failed.", event->fd);
|
||||
}
|
||||
}
|
||||
if (flock(fd, LOCK_UN) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
|
||||
}
|
||||
close(fd);
|
||||
event->ret = written;
|
||||
event->error = 0;
|
||||
}
|
||||
|
||||
static void swAio_handler_write(swAio_event *event)
|
||||
{
|
||||
int ret = -1;
|
||||
if (flock(event->fd, LOCK_EX) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_EX) failed.", event->fd);
|
||||
return;
|
||||
}
|
||||
if (event->offset == 0)
|
||||
{
|
||||
ret = write(event->fd, event->buf, event->nbytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = pwrite(event->fd, event->buf, event->nbytes, event->offset);
|
||||
}
|
||||
if (event->flags & SW_AIO_WRITE_FSYNC)
|
||||
{
|
||||
if (fsync(event->fd) < 0)
|
||||
{
|
||||
swSysError("fsync(%d) failed.", event->fd);
|
||||
}
|
||||
}
|
||||
if (flock(event->fd, LOCK_UN) < 0)
|
||||
{
|
||||
swSysError("flock(%d, LOCK_UN) failed.", event->fd);
|
||||
}
|
||||
event->ret = ret;
|
||||
}
|
||||
|
||||
static void swAio_handler_gethostbyname(swAio_event *event)
|
||||
{
|
||||
struct in_addr addr_v4;
|
||||
struct in6_addr addr_v6;
|
||||
int ret;
|
||||
|
||||
#ifndef HAVE_GETHOSTBYNAME2_R
|
||||
SwooleAIO.lock.lock(&SwooleAIO.lock);
|
||||
#endif
|
||||
if (event->flags == AF_INET6)
|
||||
{
|
||||
ret = swoole_gethostbyname(AF_INET6, event->buf, (char *) &addr_v6);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = swoole_gethostbyname(AF_INET, event->buf, (char *) &addr_v4);
|
||||
}
|
||||
bzero(event->buf, event->nbytes);
|
||||
#ifndef HAVE_GETHOSTBYNAME2_R
|
||||
SwooleAIO.lock.unlock(&SwooleAIO.lock);
|
||||
#endif
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
event->error = h_errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inet_ntop(event->flags == AF_INET6 ? AF_INET6 : AF_INET,
|
||||
event->flags == AF_INET6 ? (void *) &addr_v6 : (void *) &addr_v4, event->buf, event->nbytes) == NULL)
|
||||
{
|
||||
ret = -1;
|
||||
event->error = SW_ERROR_BAD_IPV6_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->error = 0;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
event->ret = ret;
|
||||
}
|
||||
|
||||
static void swAio_handler_getaddrinfo(swAio_event *event)
|
||||
{
|
||||
swRequest_getaddrinfo *req = (swRequest_getaddrinfo *) event->req;
|
||||
event->ret = swoole_getaddrinfo(req);
|
||||
event->error = req->error;
|
||||
}
|
||||
|
||||
static int swAioBase_thread_onTask(swThreadPool *pool, void *task, int task_len)
|
||||
{
|
||||
swAio_event *event = task;
|
||||
if (event->type >= SW_AIO_HANDLER_MAX_SIZE || SwooleAIO.handlers[event->type] == NULL)
|
||||
{
|
||||
event->error = SW_ERROR_AIO_BAD_REQUEST;
|
||||
event->ret = -1;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
SwooleAIO.handlers[event->type](event);
|
||||
|
||||
swTrace("aio_thread ok. ret=%d, error=%d", event->ret, event->error);
|
||||
|
||||
_error: do
|
||||
{
|
||||
SwooleAIO.lock.lock(&SwooleAIO.lock);
|
||||
int ret = write(swAioBase_pipe_write, &task, sizeof(task));
|
||||
SwooleAIO.lock.unlock(&SwooleAIO.lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
swYield();
|
||||
continue;
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
swSysError("sendto swoole_aio_pipe_write failed.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
static int swAioBase_write(int fd, void *inbuf, size_t size, off_t offset)
|
||||
{
|
||||
swAio_event *aio_ev = (swAio_event *) sw_malloc(sizeof(swAio_event));
|
||||
if (aio_ev == NULL)
|
||||
{
|
||||
swWarn("malloc failed.");
|
||||
return SW_ERR;
|
||||
}
|
||||
bzero(aio_ev, sizeof(swAio_event));
|
||||
aio_ev->fd = fd;
|
||||
aio_ev->buf = inbuf;
|
||||
aio_ev->type = SW_AIO_WRITE;
|
||||
aio_ev->nbytes = size;
|
||||
aio_ev->offset = offset;
|
||||
aio_ev->task_id = SwooleAIO.current_id++;
|
||||
|
||||
if (swThreadPool_dispatch(&swAioBase_thread_pool, aio_ev, sizeof(aio_ev)) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
SwooleAIO.task_num++;
|
||||
return aio_ev->task_id;
|
||||
}
|
||||
}
|
||||
|
||||
int swAio_dns_lookup(void *hostname, void *ip_addr, size_t size)
|
||||
{
|
||||
swAio_event *aio_ev = (swAio_event *) sw_malloc(sizeof(swAio_event));
|
||||
if (aio_ev == NULL)
|
||||
{
|
||||
swWarn("malloc failed.");
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
bzero(aio_ev, sizeof(swAio_event));
|
||||
aio_ev->buf = ip_addr;
|
||||
aio_ev->req = hostname;
|
||||
aio_ev->type = SW_AIO_GETHOSTBYNAME;
|
||||
aio_ev->nbytes = size;
|
||||
aio_ev->task_id = SwooleAIO.current_id++;
|
||||
|
||||
if (swThreadPool_dispatch(&swAioBase_thread_pool, aio_ev, sizeof(aio_ev)) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
SwooleAIO.task_num++;
|
||||
return aio_ev->task_id;
|
||||
}
|
||||
}
|
||||
|
||||
int swAio_dispatch(swAio_event *_event)
|
||||
{
|
||||
if (SwooleAIO.init == 0)
|
||||
{
|
||||
swAio_init();
|
||||
}
|
||||
|
||||
_event->task_id = SwooleAIO.current_id++;
|
||||
|
||||
swAio_event *event = (swAio_event *) sw_malloc(sizeof(swAio_event));
|
||||
if (event == NULL)
|
||||
{
|
||||
swWarn("malloc failed.");
|
||||
return SW_ERR;
|
||||
}
|
||||
memcpy(event, _event, sizeof(swAio_event));
|
||||
|
||||
if (swThreadPool_dispatch(&swAioBase_thread_pool, event, sizeof(event)) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
SwooleAIO.task_num++;
|
||||
return _event->task_id;
|
||||
}
|
||||
}
|
||||
|
||||
static int swAioBase_read(int fd, void *inbuf, size_t size, off_t offset)
|
||||
{
|
||||
swAio_event *aio_ev = (swAio_event *) sw_malloc(sizeof(swAio_event));
|
||||
if (aio_ev == NULL)
|
||||
{
|
||||
swWarn("malloc failed.");
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
bzero(aio_ev, sizeof(swAio_event));
|
||||
aio_ev->fd = fd;
|
||||
aio_ev->buf = inbuf;
|
||||
aio_ev->type = SW_AIO_READ;
|
||||
aio_ev->nbytes = size;
|
||||
aio_ev->offset = offset;
|
||||
aio_ev->task_id = SwooleAIO.current_id++;
|
||||
|
||||
if (swThreadPool_dispatch(&swAioBase_thread_pool, aio_ev, sizeof(aio_ev)) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
SwooleAIO.task_num++;
|
||||
return aio_ev->task_id;
|
||||
}
|
||||
}
|
||||
|
||||
void swAioBase_destroy()
|
||||
{
|
||||
swThreadPool_free(&swAioBase_thread_pool);
|
||||
if (SwooleG.main_reactor)
|
||||
{
|
||||
SwooleG.main_reactor->del(SwooleG.main_reactor, swAioBase_pipe_read);
|
||||
}
|
||||
swoole_aio_pipe.close(&swoole_aio_pipe);
|
||||
}
|
127
vendor/swoole/src/os/msg_queue.c
vendored
Executable file
127
vendor/swoole/src/os/msg_queue.c
vendored
Executable file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
|
||||
int swMsgQueue_free(swMsgQueue *q)
|
||||
{
|
||||
if (msgctl(q->msg_id, IPC_RMID, 0) < 0)
|
||||
{
|
||||
swSysError("msgctl(%d, IPC_RMID) failed.", q->msg_id);
|
||||
return SW_ERR;
|
||||
}
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
void swMsgQueue_set_blocking(swMsgQueue *q, uint8_t blocking)
|
||||
{
|
||||
if (blocking == 0)
|
||||
{
|
||||
q->flags = q->flags | IPC_NOWAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
q->flags = q->flags & (~IPC_NOWAIT);
|
||||
}
|
||||
}
|
||||
|
||||
int swMsgQueue_create(swMsgQueue *q, int blocking, key_t msg_key, int perms)
|
||||
{
|
||||
if (perms <= 0 || perms >= 01000)
|
||||
{
|
||||
perms = 0666;
|
||||
}
|
||||
int msg_id;
|
||||
msg_id = msgget(msg_key, IPC_CREAT | perms);
|
||||
if (msg_id < 0)
|
||||
{
|
||||
swSysError("msgget() failed.");
|
||||
return SW_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
bzero(q, sizeof(swMsgQueue));
|
||||
q->msg_id = msg_id;
|
||||
q->perms = perms;
|
||||
q->blocking = blocking;
|
||||
swMsgQueue_set_blocking(q, blocking);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int swMsgQueue_pop(swMsgQueue *q, swQueue_data *data, int length)
|
||||
{
|
||||
int ret = msgrcv(q->msg_id, data, length, data->mtype, q->flags);
|
||||
if (ret < 0)
|
||||
{
|
||||
SwooleG.error = errno;
|
||||
if (errno != ENOMSG && errno != EINTR)
|
||||
{
|
||||
swSysError("msgrcv(%d, %d, %ld) failed.", q->msg_id, length, data->mtype);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int swMsgQueue_push(swMsgQueue *q, swQueue_data *in, int length)
|
||||
{
|
||||
int ret;
|
||||
|
||||
while (1)
|
||||
{
|
||||
ret = msgsnd(q->msg_id, in, length, q->flags);
|
||||
if (ret < 0)
|
||||
{
|
||||
SwooleG.error = errno;
|
||||
if (errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (errno == EAGAIN)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
swSysError("msgsnd(%d, %d, %ld) failed.", q->msg_id, length, in->mtype);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int swMsgQueue_stat(swMsgQueue *q, int *queue_num, int *queue_bytes)
|
||||
{
|
||||
struct msqid_ds __stat;
|
||||
if (msgctl(q->msg_id, IPC_STAT, &__stat) == 0)
|
||||
{
|
||||
*queue_num = __stat.msg_qnum;
|
||||
*queue_bytes = __stat.msg_cbytes;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
101
vendor/swoole/src/os/sendfile.c
vendored
Executable file
101
vendor/swoole/src/os/sendfile.c
vendored
Executable file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
|
||||
#ifdef HAVE_KQUEUE
|
||||
|
||||
#include <sys/uio.h>
|
||||
|
||||
int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size)
|
||||
{
|
||||
off_t sent_bytes = 0;
|
||||
int ret;
|
||||
|
||||
#ifdef __MACH__
|
||||
struct sf_hdtr hdtr;
|
||||
hdtr.headers = NULL;
|
||||
hdtr.hdr_cnt = 0;
|
||||
hdtr.trailers = NULL;
|
||||
hdtr.trl_cnt = 0;
|
||||
#endif
|
||||
|
||||
//sent_bytes = (off_t)size;
|
||||
swTrace("send file, out_fd:%d, in_fd:%d, offset:%ld, size:%ld", out_fd, in_fd, (long)*offset, (long)size);
|
||||
|
||||
do_sendfile:
|
||||
#ifdef __MACH__
|
||||
ret = sendfile(in_fd, out_fd, *offset, (long long *) &size, &hdtr, 0);
|
||||
#else
|
||||
ret = sendfile(in_fd, out_fd, *offset, size, 0, &sent_bytes, 0);
|
||||
#endif
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
*offset += sent_bytes;
|
||||
return sent_bytes;
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
{
|
||||
goto do_sendfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
*offset += size;
|
||||
return size;
|
||||
}
|
||||
else
|
||||
{
|
||||
swWarn("sendfile failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
return SW_OK;
|
||||
}
|
||||
#elif !defined(HAVE_SENDFILE)
|
||||
int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size)
|
||||
{
|
||||
char buf[SW_BUFFER_SIZE_BIG];
|
||||
int readn = size > sizeof(buf) ? sizeof(buf) : size;
|
||||
|
||||
int ret;
|
||||
int n = pread(in_fd, buf, readn, *offset);
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
ret = write(out_fd, buf, n);
|
||||
if (ret < 0)
|
||||
{
|
||||
swSysError("write() failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
*offset += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
swSysError("pread() failed.");
|
||||
return SW_ERR;
|
||||
}
|
||||
}
|
||||
#endif
|
262
vendor/swoole/src/os/signal.c
vendored
Executable file
262
vendor/swoole/src/os/signal.c
vendored
Executable file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
|
||||
#ifdef HAVE_SIGNALFD
|
||||
#include <sys/signalfd.h>
|
||||
static void swSignalfd_set(int signo, swSignalHander callback);
|
||||
static void swSignalfd_clear();
|
||||
static int swSignalfd_onSignal(swReactor *reactor, swEvent *event);
|
||||
|
||||
static sigset_t signalfd_mask;
|
||||
static int signal_fd = 0;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
swSignalHander callback;
|
||||
uint16_t signo;
|
||||
uint16_t active;
|
||||
} swSignal;
|
||||
|
||||
static swSignal signals[SW_SIGNO_MAX];
|
||||
static int _lock = 0;
|
||||
|
||||
static void swSignal_async_handler(int signo);
|
||||
|
||||
/**
|
||||
* clear all singal
|
||||
*/
|
||||
void swSignal_none(void)
|
||||
{
|
||||
sigset_t mask;
|
||||
sigfillset(&mask);
|
||||
int ret = pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
swWarn("pthread_sigmask() failed. Error: %s[%d]", strerror(ret), ret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setup signal
|
||||
*/
|
||||
swSignalHander swSignal_set(int sig, swSignalHander func, int restart, int mask)
|
||||
{
|
||||
//ignore
|
||||
if (func == NULL)
|
||||
{
|
||||
func = SIG_IGN;
|
||||
}
|
||||
//clear
|
||||
else if ((long) func == -1)
|
||||
{
|
||||
func = SIG_DFL;
|
||||
}
|
||||
|
||||
struct sigaction act, oact;
|
||||
act.sa_handler = func;
|
||||
if (mask)
|
||||
{
|
||||
sigfillset(&act.sa_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
sigemptyset(&act.sa_mask);
|
||||
}
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(sig, &act, &oact) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return oact.sa_handler;
|
||||
}
|
||||
|
||||
void swSignal_add(int signo, swSignalHander func)
|
||||
{
|
||||
#ifdef HAVE_SIGNALFD
|
||||
if (SwooleG.use_signalfd)
|
||||
{
|
||||
swSignalfd_set(signo, func);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
signals[signo].callback = func;
|
||||
signals[signo].active = 1;
|
||||
signals[signo].signo = signo;
|
||||
swSignal_set(signo, swSignal_async_handler, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void swSignal_async_handler(int signo)
|
||||
{
|
||||
if (SwooleG.main_reactor)
|
||||
{
|
||||
SwooleG.main_reactor->singal_no = signo;
|
||||
}
|
||||
else
|
||||
{
|
||||
//discard signal
|
||||
if (_lock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_lock = 1;
|
||||
swSignal_callback(signo);
|
||||
_lock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void swSignal_callback(int signo)
|
||||
{
|
||||
if (signo >= SW_SIGNO_MAX)
|
||||
{
|
||||
swWarn("signal[%d] numberis invalid.", signo);
|
||||
return;
|
||||
}
|
||||
swSignalHander callback = signals[signo].callback;
|
||||
if (!callback)
|
||||
{
|
||||
swWarn("signal[%d] callback is null.", signo);
|
||||
return;
|
||||
}
|
||||
callback(signo);
|
||||
}
|
||||
|
||||
void swSignal_clear(void)
|
||||
{
|
||||
#ifdef HAVE_SIGNALFD
|
||||
if (SwooleG.use_signalfd)
|
||||
{
|
||||
swSignalfd_clear();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SW_SIGNO_MAX; i++)
|
||||
{
|
||||
if (signals[i].active)
|
||||
{
|
||||
swSignal_set(signals[i].signo, (swSignalHander) -1, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
bzero(&signals, sizeof(signals));
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIGNALFD
|
||||
void swSignalfd_init()
|
||||
{
|
||||
sigemptyset(&signalfd_mask);
|
||||
bzero(&signals, sizeof(signals));
|
||||
}
|
||||
|
||||
static void swSignalfd_set(int signo, swSignalHander callback)
|
||||
{
|
||||
if (callback == NULL && signals[signo].active)
|
||||
{
|
||||
sigdelset(&signalfd_mask, signo);
|
||||
bzero(&signals[signo], sizeof(swSignal));
|
||||
}
|
||||
else
|
||||
{
|
||||
sigaddset(&signalfd_mask, signo);
|
||||
signals[signo].callback = callback;
|
||||
signals[signo].signo = signo;
|
||||
signals[signo].active = 1;
|
||||
}
|
||||
if (signal_fd > 0)
|
||||
{
|
||||
sigprocmask(SIG_BLOCK, &signalfd_mask, NULL);
|
||||
signalfd(signal_fd, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC);
|
||||
}
|
||||
}
|
||||
|
||||
int swSignalfd_setup(swReactor *reactor)
|
||||
{
|
||||
if (signal_fd == 0)
|
||||
{
|
||||
signal_fd = signalfd(-1, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC);
|
||||
if (signal_fd < 0)
|
||||
{
|
||||
swWarn("signalfd() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
SwooleG.signal_fd = signal_fd;
|
||||
if (sigprocmask(SIG_BLOCK, &signalfd_mask, NULL) == -1)
|
||||
{
|
||||
swWarn("sigprocmask() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
reactor->setHandle(reactor, SW_FD_SIGNAL, swSignalfd_onSignal);
|
||||
reactor->add(reactor, signal_fd, SW_FD_SIGNAL);
|
||||
return SW_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
swWarn("signalfd has been created");
|
||||
return SW_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
static void swSignalfd_clear()
|
||||
{
|
||||
if (signal_fd)
|
||||
{
|
||||
if (sigprocmask(SIG_UNBLOCK, &signalfd_mask, NULL) < 0)
|
||||
{
|
||||
swSysError("sigprocmask(SIG_UNBLOCK) failed.");
|
||||
}
|
||||
close(signal_fd);
|
||||
bzero(&signalfd_mask, sizeof(signalfd_mask));
|
||||
}
|
||||
signal_fd = 0;
|
||||
}
|
||||
|
||||
static int swSignalfd_onSignal(swReactor *reactor, swEvent *event)
|
||||
{
|
||||
int n;
|
||||
struct signalfd_siginfo siginfo;
|
||||
n = read(event->fd, &siginfo, sizeof(siginfo));
|
||||
if (n < 0)
|
||||
{
|
||||
swWarn("read from signalfd failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_OK;
|
||||
}
|
||||
if (siginfo.ssi_signo >= SW_SIGNO_MAX)
|
||||
{
|
||||
swWarn("unknown signal[%d].", siginfo.ssi_signo);
|
||||
return SW_OK;
|
||||
}
|
||||
if (signals[siginfo.ssi_signo].active)
|
||||
{
|
||||
if (signals[siginfo.ssi_signo].callback)
|
||||
{
|
||||
signals[siginfo.ssi_signo].callback(siginfo.ssi_signo);
|
||||
}
|
||||
else
|
||||
{
|
||||
swWarn("signal[%d] callback is null.", siginfo.ssi_signo);
|
||||
}
|
||||
}
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
#endif
|
240
vendor/swoole/src/os/timer.c
vendored
Executable file
240
vendor/swoole/src/os/timer.c
vendored
Executable file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include "Server.h"
|
||||
|
||||
#ifdef HAVE_TIMERFD
|
||||
#include <sys/timerfd.h>
|
||||
#endif
|
||||
|
||||
static int swSystemTimer_signal_set(swTimer *timer, long interval);
|
||||
static int swSystemTimer_timerfd_set(swTimer *timer, long interval);
|
||||
static int swSystemTimer_set(swTimer *timer, long new_interval);
|
||||
|
||||
/**
|
||||
* create timer
|
||||
*/
|
||||
int swSystemTimer_init(int interval, int use_pipe)
|
||||
{
|
||||
swTimer *timer = &SwooleG.timer;
|
||||
timer->lasttime = interval;
|
||||
|
||||
#ifndef HAVE_TIMERFD
|
||||
SwooleG.use_timerfd = 0;
|
||||
#endif
|
||||
|
||||
if (SwooleG.use_timerfd)
|
||||
{
|
||||
if (swSystemTimer_timerfd_set(timer, interval) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
timer->use_pipe = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (use_pipe)
|
||||
{
|
||||
if (swPipeNotify_auto(&timer->pipe, 0, 0) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
timer->fd = timer->pipe.getFd(&timer->pipe, 0);
|
||||
timer->use_pipe = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer->fd = 1;
|
||||
timer->use_pipe = 0;
|
||||
}
|
||||
|
||||
if (swSystemTimer_signal_set(timer, interval) < 0)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
swSignal_add(SIGALRM, swSystemTimer_signal_handler);
|
||||
}
|
||||
|
||||
if (timer->fd > 1)
|
||||
{
|
||||
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_TIMER, swSystemTimer_event_handler);
|
||||
SwooleG.main_reactor->add(SwooleG.main_reactor, SwooleG.timer.fd, SW_FD_TIMER);
|
||||
}
|
||||
timer->set = swSystemTimer_set;
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* timerfd
|
||||
*/
|
||||
static int swSystemTimer_timerfd_set(swTimer *timer, long interval)
|
||||
{
|
||||
#ifdef HAVE_TIMERFD
|
||||
struct timeval now;
|
||||
int sec = interval / 1000;
|
||||
int msec = (((float) interval / 1000) - sec) * 1000;
|
||||
|
||||
if (gettimeofday(&now, NULL) < 0)
|
||||
{
|
||||
swWarn("gettimeofday() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
struct itimerspec timer_set;
|
||||
bzero(&timer_set, sizeof(timer_set));
|
||||
|
||||
if (interval < 0)
|
||||
{
|
||||
if (timer->fd == 0)
|
||||
{
|
||||
return SW_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
timer_set.it_interval.tv_sec = sec;
|
||||
timer_set.it_interval.tv_nsec = msec * 1000 * 1000;
|
||||
|
||||
timer_set.it_value.tv_sec = now.tv_sec + sec;
|
||||
timer_set.it_value.tv_nsec = (now.tv_usec * 1000) + timer_set.it_interval.tv_nsec;
|
||||
|
||||
if (timer_set.it_value.tv_nsec > 1e9)
|
||||
{
|
||||
timer_set.it_value.tv_nsec = timer_set.it_value.tv_nsec - 1e9;
|
||||
timer_set.it_value.tv_sec += 1;
|
||||
}
|
||||
|
||||
if (timer->fd == 0)
|
||||
{
|
||||
timer->fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
if (timer->fd < 0)
|
||||
{
|
||||
swWarn("timerfd_create() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timerfd_settime(timer->fd, TFD_TIMER_ABSTIME, &timer_set, NULL) == -1)
|
||||
{
|
||||
swWarn("timerfd_settime() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
return SW_OK;
|
||||
#else
|
||||
swWarn("kernel not support timerfd.");
|
||||
return SW_ERR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* setitimer
|
||||
*/
|
||||
static int swSystemTimer_signal_set(swTimer *timer, long interval)
|
||||
{
|
||||
struct itimerval timer_set;
|
||||
int sec = interval / 1000;
|
||||
int msec = (((float) interval / 1000) - sec) * 1000;
|
||||
|
||||
struct timeval now;
|
||||
if (gettimeofday(&now, NULL) < 0)
|
||||
{
|
||||
swWarn("gettimeofday() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
bzero(&timer_set, sizeof(timer_set));
|
||||
|
||||
if (interval > 0)
|
||||
{
|
||||
timer_set.it_interval.tv_sec = sec;
|
||||
timer_set.it_interval.tv_usec = msec * 1000;
|
||||
|
||||
timer_set.it_value.tv_sec = sec;
|
||||
timer_set.it_value.tv_usec = timer_set.it_interval.tv_usec;
|
||||
|
||||
if (timer_set.it_value.tv_usec > 1e6)
|
||||
{
|
||||
timer_set.it_value.tv_usec = timer_set.it_value.tv_usec - 1e6;
|
||||
timer_set.it_value.tv_sec += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (setitimer(ITIMER_REAL, &timer_set, NULL) < 0)
|
||||
{
|
||||
swWarn("setitimer() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return SW_ERR;
|
||||
}
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
void swSystemTimer_free(swTimer *timer)
|
||||
{
|
||||
if (timer->use_pipe)
|
||||
{
|
||||
timer->pipe.close(&timer->pipe);
|
||||
}
|
||||
else if (timer->fd > 2)
|
||||
{
|
||||
if (close(timer->fd) < 0)
|
||||
{
|
||||
swSysError("close(%d) failed.", timer->fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static long current_interval = 0;
|
||||
|
||||
static int swSystemTimer_set(swTimer *timer, long new_interval)
|
||||
{
|
||||
if (new_interval == current_interval)
|
||||
{
|
||||
return SW_OK;
|
||||
}
|
||||
current_interval = new_interval;
|
||||
if (SwooleG.use_timerfd)
|
||||
{
|
||||
return swSystemTimer_timerfd_set(timer, new_interval);
|
||||
}
|
||||
else
|
||||
{
|
||||
return swSystemTimer_signal_set(timer, new_interval);
|
||||
}
|
||||
}
|
||||
|
||||
int swSystemTimer_event_handler(swReactor *reactor, swEvent *event)
|
||||
{
|
||||
uint64_t exp;
|
||||
swTimer *timer = &SwooleG.timer;
|
||||
|
||||
if (read(timer->fd, &exp, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
SwooleG.signal_alarm = 0;
|
||||
return swTimer_select(timer);
|
||||
}
|
||||
|
||||
void swSystemTimer_signal_handler(int sig)
|
||||
{
|
||||
SwooleG.signal_alarm = 1;
|
||||
uint64_t flag = 1;
|
||||
|
||||
if (SwooleG.timer.use_pipe)
|
||||
{
|
||||
SwooleG.timer.pipe.write(&SwooleG.timer.pipe, &flag, sizeof(flag));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user