removed all aio* files. all relevant functions are available in a different project, mio
This commit is contained in:
		| @ -5,16 +5,11 @@ AM_CPPFLAGS = \ | ||||
| 	-I$(top_srcdir)/include | ||||
|  | ||||
| noinst_HEADERS = \ | ||||
| 	aio-prv.h \ | ||||
| 	fs-prv.h \ | ||||
| 	glob-imp.h | ||||
|  | ||||
| lib_LTLIBRARIES = libqsesi.la | ||||
| libqsesi_la_SOURCES =  \ | ||||
| 	aio.c \ | ||||
| 	aio-pro.c  \ | ||||
| 	aio-sck.c  \ | ||||
| 	aio-tmr.c  \ | ||||
| 	cnd.c \ | ||||
| 	dir.c \ | ||||
| 	fio.c  \ | ||||
|  | ||||
| @ -138,10 +138,8 @@ am__installdirs = "$(DESTDIR)$(libdir)" | ||||
| LTLIBRARIES = $(lib_LTLIBRARIES) | ||||
| am__DEPENDENCIES_1 = | ||||
| libqsesi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) | ||||
| am_libqsesi_la_OBJECTS = libqsesi_la-aio.lo libqsesi_la-aio-pro.lo \ | ||||
| 	libqsesi_la-aio-sck.lo libqsesi_la-aio-tmr.lo \ | ||||
| 	libqsesi_la-cnd.lo libqsesi_la-dir.lo libqsesi_la-fio.lo \ | ||||
| 	libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \ | ||||
| am_libqsesi_la_OBJECTS = libqsesi_la-cnd.lo libqsesi_la-dir.lo \ | ||||
| 	libqsesi_la-fio.lo libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \ | ||||
| 	libqsesi_la-fs-copy.lo libqsesi_la-fs-delete.lo \ | ||||
| 	libqsesi_la-fs-err.lo libqsesi_la-fs-make.lo \ | ||||
| 	libqsesi_la-fs-move.lo libqsesi_la-glob.lo libqsesi_la-intr.lo \ | ||||
| @ -424,16 +422,11 @@ AM_CPPFLAGS = \ | ||||
| 	-I$(top_srcdir)/include | ||||
|  | ||||
| noinst_HEADERS = \ | ||||
| 	aio-prv.h \ | ||||
| 	fs-prv.h \ | ||||
| 	glob-imp.h | ||||
|  | ||||
| lib_LTLIBRARIES = libqsesi.la $(am__append_1) | ||||
| libqsesi_la_SOURCES = \ | ||||
| 	aio.c \ | ||||
| 	aio-pro.c  \ | ||||
| 	aio-sck.c  \ | ||||
| 	aio-tmr.c  \ | ||||
| 	cnd.c \ | ||||
| 	dir.c \ | ||||
| 	fio.c  \ | ||||
| @ -564,10 +557,6 @@ distclean-compile: | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TcpServer.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-pro.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-sck.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-tmr.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-cnd.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-dir.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fio.Plo@am__quote@ | ||||
| @ -620,34 +609,6 @@ distclean-compile: | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< | ||||
|  | ||||
| libqsesi_la-aio.lo: aio.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio.Tpo -c -o libqsesi_la-aio.lo `test -f 'aio.c' || echo '$(srcdir)/'`aio.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio.Tpo $(DEPDIR)/libqsesi_la-aio.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio.c' object='libqsesi_la-aio.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio.lo `test -f 'aio.c' || echo '$(srcdir)/'`aio.c | ||||
|  | ||||
| libqsesi_la-aio-pro.lo: aio-pro.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-pro.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-pro.Tpo -c -o libqsesi_la-aio-pro.lo `test -f 'aio-pro.c' || echo '$(srcdir)/'`aio-pro.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-pro.Tpo $(DEPDIR)/libqsesi_la-aio-pro.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio-pro.c' object='libqsesi_la-aio-pro.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-pro.lo `test -f 'aio-pro.c' || echo '$(srcdir)/'`aio-pro.c | ||||
|  | ||||
| libqsesi_la-aio-sck.lo: aio-sck.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-sck.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-sck.Tpo -c -o libqsesi_la-aio-sck.lo `test -f 'aio-sck.c' || echo '$(srcdir)/'`aio-sck.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-sck.Tpo $(DEPDIR)/libqsesi_la-aio-sck.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio-sck.c' object='libqsesi_la-aio-sck.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-sck.lo `test -f 'aio-sck.c' || echo '$(srcdir)/'`aio-sck.c | ||||
|  | ||||
| libqsesi_la-aio-tmr.lo: aio-tmr.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-tmr.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-tmr.Tpo -c -o libqsesi_la-aio-tmr.lo `test -f 'aio-tmr.c' || echo '$(srcdir)/'`aio-tmr.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-tmr.Tpo $(DEPDIR)/libqsesi_la-aio-tmr.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio-tmr.c' object='libqsesi_la-aio-tmr.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-tmr.lo `test -f 'aio-tmr.c' || echo '$(srcdir)/'`aio-tmr.c | ||||
|  | ||||
| libqsesi_la-cnd.lo: cnd.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-cnd.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-cnd.Tpo -c -o libqsesi_la-cnd.lo `test -f 'cnd.c' || echo '$(srcdir)/'`cnd.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-cnd.Tpo $(DEPDIR)/libqsesi_la-cnd.Plo | ||||
|  | ||||
| @ -1,853 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. 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. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR 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. | ||||
|  */ | ||||
|  | ||||
| #include <qse/si/aio-pro.h> | ||||
| #include "aio-prv.h" | ||||
|  | ||||
| #include <qse/cmn/str.h> | ||||
|  | ||||
| #include <unistd.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <sys/wait.h> | ||||
| #include <signal.h> | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| struct slave_info_t | ||||
| { | ||||
| 	qse_aio_dev_pro_make_t* mi; | ||||
| 	qse_aio_syshnd_t pfd; | ||||
| 	int dev_capa; | ||||
| 	qse_aio_dev_pro_sid_t id; | ||||
| }; | ||||
|  | ||||
| typedef struct slave_info_t slave_info_t; | ||||
|  | ||||
| static qse_aio_dev_pro_slave_t* make_slave (qse_aio_t* aio, slave_info_t* si); | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| struct param_t | ||||
| { | ||||
| 	qse_mchar_t* mcmd; | ||||
| 	qse_mchar_t* fixed_argv[4]; | ||||
| 	qse_mchar_t** argv; | ||||
| }; | ||||
| typedef struct param_t param_t; | ||||
|  | ||||
| static void free_param (qse_aio_t* aio, param_t* param) | ||||
| { | ||||
| 	if (param->argv && param->argv != param->fixed_argv)  | ||||
| 		QSE_MMGR_FREE (aio->mmgr, param->argv); | ||||
| 	if (param->mcmd) QSE_MMGR_FREE (aio->mmgr, param->mcmd); | ||||
| 	QSE_MEMSET (param, 0, QSE_SIZEOF(*param)); | ||||
| } | ||||
|  | ||||
| static int make_param (qse_aio_t* aio, const qse_mchar_t* cmd, int flags, param_t* param) | ||||
| { | ||||
| 	int fcnt = 0; | ||||
| 	qse_mchar_t* mcmd = QSE_NULL; | ||||
|  | ||||
| 	QSE_MEMSET (param, 0, QSE_SIZEOF(*param)); | ||||
|  | ||||
| 	if (flags & QSE_AIO_DEV_PRO_SHELL) | ||||
| 	{ | ||||
| 		mcmd = (qse_mchar_t*)cmd; | ||||
|  | ||||
| 		param->argv = param->fixed_argv; | ||||
| 		param->argv[0] = QSE_MT("/bin/sh"); | ||||
| 		param->argv[1] = QSE_MT("-c"); | ||||
| 		param->argv[2] = mcmd; | ||||
| 		param->argv[3] = QSE_NULL; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		int i; | ||||
| 		qse_mchar_t** argv; | ||||
| 		qse_mchar_t* mcmdptr; | ||||
|  | ||||
| 		mcmd = qse_mbsdup (cmd, aio->mmgr); | ||||
| 		if (!mcmd)  | ||||
| 		{ | ||||
| 			aio->errnum = QSE_AIO_ENOMEM; | ||||
| 			goto oops; | ||||
| 		} | ||||
|  | ||||
| 		fcnt = qse_mbsspl (mcmd, QSE_MT(""), QSE_MT('\"'), QSE_MT('\"'), QSE_MT('\\'));  | ||||
| 		if (fcnt <= 0)  | ||||
| 		{ | ||||
| 			/* no field or an error */ | ||||
| 			aio->errnum = QSE_AIO_EINVAL; | ||||
| 			goto oops; | ||||
| 		} | ||||
|  | ||||
| 		if (fcnt < QSE_COUNTOF(param->fixed_argv)) | ||||
| 		{ | ||||
| 			param->argv = param->fixed_argv; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			param->argv = QSE_MMGR_ALLOC (aio->mmgr, (fcnt + 1) * QSE_SIZEOF(argv[0])); | ||||
| 			if (param->argv == QSE_NULL)  | ||||
| 			{ | ||||
| 				aio->errnum = QSE_AIO_ENOMEM; | ||||
| 				goto oops; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		mcmdptr = mcmd; | ||||
| 		for (i = 0; i < fcnt; i++) | ||||
| 		{ | ||||
| 			param->argv[i] = mcmdptr; | ||||
| 			while (*mcmdptr != QSE_MT('\0')) mcmdptr++; | ||||
| 			mcmdptr++; | ||||
| 		} | ||||
| 		param->argv[i] = QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (mcmd && mcmd != (qse_mchar_t*)cmd) param->mcmd = mcmd; | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	if (mcmd && mcmd != cmd) QSE_MMGR_FREE (aio->mmgr, mcmd); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static pid_t standard_fork_and_exec (qse_aio_t* aio, int pfds[], int flags, param_t* param) | ||||
| { | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	pid = fork (); | ||||
| 	if (pid == -1)  | ||||
| 	{ | ||||
| 		aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (pid == 0) | ||||
| 	{ | ||||
| 		/* slave process */ | ||||
|  | ||||
| 		qse_aio_syshnd_t devnull = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| /* TODO: close all uneeded fds */ | ||||
|  | ||||
| 		if (flags & QSE_AIO_DEV_PRO_WRITEIN) | ||||
| 		{ | ||||
| 			/* slave should read */ | ||||
| 			close (pfds[1]); | ||||
| 			pfds[1] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 			/* let the pipe be standard input */ | ||||
| 			if (dup2 (pfds[0], 0) <= -1) goto slave_oops; | ||||
|  | ||||
| 			close (pfds[0]); | ||||
| 			pfds[0] = QSE_AIO_SYSHND_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		if (flags & QSE_AIO_DEV_PRO_READOUT) | ||||
| 		{ | ||||
| 			/* slave should write */ | ||||
| 			close (pfds[2]); | ||||
| 			pfds[2] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 			if (dup2(pfds[3], 1) == -1) goto slave_oops; | ||||
|  | ||||
| 			if (flags & QSE_AIO_DEV_PRO_ERRTOOUT) | ||||
| 			{ | ||||
| 				if (dup2(pfds[3], 2) == -1) goto slave_oops; | ||||
| 			} | ||||
|  | ||||
| 			close (pfds[3]); | ||||
| 			pfds[3] = QSE_AIO_SYSHND_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		if (flags & QSE_AIO_DEV_PRO_READERR) | ||||
| 		{ | ||||
| 			close (pfds[4]); | ||||
| 			pfds[4] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 			if (dup2(pfds[5], 2) == -1) goto slave_oops; | ||||
|  | ||||
| 			if (flags & QSE_AIO_DEV_PRO_OUTTOERR) | ||||
| 			{ | ||||
| 				if (dup2(pfds[5], 1) == -1) goto slave_oops; | ||||
| 			} | ||||
|  | ||||
| 			close (pfds[5]); | ||||
| 			pfds[5] = QSE_AIO_SYSHND_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		if ((flags & QSE_AIO_DEV_PRO_INTONUL) || | ||||
| 		    (flags & QSE_AIO_DEV_PRO_OUTTONUL) || | ||||
| 		    (flags & QSE_AIO_DEV_PRO_ERRTONUL)) | ||||
| 		{ | ||||
| 		#if defined(O_LARGEFILE) | ||||
| 			devnull = open (QSE_MT("/dev/null"), O_RDWR | O_LARGEFILE, 0); | ||||
| 		#else | ||||
| 			devnull = open (QSE_MT("/dev/null"), O_RDWR, 0); | ||||
| 		#endif | ||||
| 			if (devnull == QSE_AIO_SYSHND_INVALID) goto slave_oops; | ||||
| 		} | ||||
|  | ||||
| 		execv (param->argv[0], param->argv); | ||||
|  | ||||
| 		/* if exec fails, free 'param' parameter which is an inherited pointer */ | ||||
| 		free_param (aio, param);  | ||||
|  | ||||
| 	slave_oops: | ||||
| 		if (devnull != QSE_AIO_SYSHND_INVALID) close(devnull); | ||||
| 		_exit (128); | ||||
| 	} | ||||
|  | ||||
| 	/* parent process */ | ||||
| 	return pid; | ||||
| } | ||||
|  | ||||
| static int dev_pro_make_master (qse_aio_dev_t* dev, void* ctx) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* rdev = (qse_aio_dev_pro_t*)dev; | ||||
| 	qse_aio_dev_pro_make_t* info = (qse_aio_dev_pro_make_t*)ctx; | ||||
| 	qse_aio_syshnd_t pfds[6]; | ||||
| 	int i, minidx = -1, maxidx = -1; | ||||
| 	param_t param; | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_WRITEIN) | ||||
| 	{ | ||||
| 		if (pipe(&pfds[0]) == -1) | ||||
| 		{ | ||||
| 			dev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 			goto oops; | ||||
| 		} | ||||
| 		minidx = 0; maxidx = 1; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READOUT) | ||||
| 	{ | ||||
| 		if (pipe(&pfds[2]) == -1) | ||||
| 		{ | ||||
| 			dev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 			goto oops; | ||||
| 		} | ||||
| 		if (minidx == -1) minidx = 2; | ||||
| 		maxidx = 3; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READERR) | ||||
| 	{ | ||||
| 		if (pipe(&pfds[4]) == -1) | ||||
| 		{ | ||||
| 			dev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 			goto oops; | ||||
| 		} | ||||
| 		if (minidx == -1) minidx = 4; | ||||
| 		maxidx = 5; | ||||
| 	} | ||||
|  | ||||
| 	if (maxidx == -1) | ||||
| 	{ | ||||
| 		dev->aio->errnum = QSE_AIO_EINVAL; | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (make_param (rdev->aio, info->cmd, info->flags, ¶m) <= -1) goto oops; | ||||
|  | ||||
| /* TODO: more advanced fork and exec .. */ | ||||
| 	pid = standard_fork_and_exec (rdev->aio, pfds, info->flags, ¶m); | ||||
| 	if (pid <= -1)  | ||||
| 	{ | ||||
| 		free_param (rdev->aio, ¶m); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	free_param (rdev->aio, ¶m); | ||||
| 	rdev->child_pid = pid; | ||||
|  | ||||
| 	/* this is the parent process */ | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_WRITEIN) | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * 012345 | ||||
| 		 * rw---- | ||||
| 		 * X | ||||
| 		 * WRITE => 1 | ||||
| 		 */ | ||||
| 		close (pfds[0]); | ||||
| 		pfds[0] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 		if (qse_aio_makesyshndasync (dev->aio, pfds[1]) <= -1) goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READOUT) | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * 012345 | ||||
| 		 * --rw-- | ||||
| 		 *    X | ||||
| 		 * READ => 2 | ||||
| 		 */ | ||||
| 		close (pfds[3]); | ||||
| 		pfds[3] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 		if (qse_aio_makesyshndasync (dev->aio, pfds[2]) <= -1) goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READERR) | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * 012345 | ||||
| 		 * ----rw | ||||
| 		 *      X | ||||
| 		 * READ => 4 | ||||
| 		 */ | ||||
| 		close (pfds[5]); | ||||
| 		pfds[5] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 		if (qse_aio_makesyshndasync (dev->aio, pfds[4]) <= -1) goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (pfds[1] != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		/* hand over pfds[2] to the first slave device */ | ||||
| 		slave_info_t si; | ||||
|  | ||||
| 		si.mi = info; | ||||
| 		si.pfd = pfds[1]; | ||||
| 		si.dev_capa = QSE_AIO_DEV_CAPA_OUT | QSE_AIO_DEV_CAPA_OUT_QUEUED | QSE_AIO_DEV_CAPA_STREAM; | ||||
| 		si.id = QSE_AIO_DEV_PRO_IN; | ||||
|  | ||||
| 		rdev->slave[QSE_AIO_DEV_PRO_IN] = make_slave (dev->aio, &si); | ||||
| 		if (!rdev->slave[QSE_AIO_DEV_PRO_IN]) goto oops; | ||||
|  | ||||
| 		pfds[1] = QSE_AIO_SYSHND_INVALID; | ||||
| 		rdev->slave_count++; | ||||
| 	} | ||||
|  | ||||
| 	if (pfds[2] != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		/* hand over pfds[2] to the first slave device */ | ||||
| 		slave_info_t si; | ||||
|  | ||||
| 		si.mi = info; | ||||
| 		si.pfd = pfds[2]; | ||||
| 		si.dev_capa = QSE_AIO_DEV_CAPA_IN | QSE_AIO_DEV_CAPA_STREAM; | ||||
| 		si.id = QSE_AIO_DEV_PRO_OUT; | ||||
|  | ||||
| 		rdev->slave[QSE_AIO_DEV_PRO_OUT] = make_slave (dev->aio, &si); | ||||
| 		if (!rdev->slave[QSE_AIO_DEV_PRO_OUT]) goto oops; | ||||
|  | ||||
| 		pfds[2] = QSE_AIO_SYSHND_INVALID; | ||||
| 		rdev->slave_count++; | ||||
| 	} | ||||
|  | ||||
| 	if (pfds[4] != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		/* hand over pfds[4] to the second slave device */ | ||||
| 		slave_info_t si; | ||||
|  | ||||
| 		si.mi = info; | ||||
| 		si.pfd = pfds[4]; | ||||
| 		si.dev_capa = QSE_AIO_DEV_CAPA_IN | QSE_AIO_DEV_CAPA_STREAM; | ||||
| 		si.id = QSE_AIO_DEV_PRO_ERR; | ||||
|  | ||||
| 		rdev->slave[QSE_AIO_DEV_PRO_ERR] = make_slave (dev->aio, &si); | ||||
| 		if (!rdev->slave[QSE_AIO_DEV_PRO_ERR]) goto oops; | ||||
|  | ||||
| 		pfds[4] = QSE_AIO_SYSHND_INVALID; | ||||
| 		rdev->slave_count++; | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < QSE_COUNTOF(rdev->slave); i++)  | ||||
| 	{ | ||||
| 		if (rdev->slave[i]) rdev->slave[i]->master = rdev; | ||||
| 	} | ||||
|  | ||||
| 	rdev->dev_capa = QSE_AIO_DEV_CAPA_VIRTUAL; /* the master device doesn't perform I/O */ | ||||
| 	rdev->flags = info->flags; | ||||
| 	rdev->on_read = info->on_read; | ||||
| 	rdev->on_write = info->on_write; | ||||
| 	rdev->on_close = info->on_close; | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	for (i = minidx; i < maxidx; i++) | ||||
| 	{ | ||||
| 		if (pfds[i] != QSE_AIO_SYSHND_INVALID) close (pfds[i]); | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->mcmd)  | ||||
| 	{ | ||||
| 		QSE_MMGR_FREE (rdev->aio->mmgr, rdev->mcmd); | ||||
| 		free_param (rdev->aio, ¶m); | ||||
| 	} | ||||
|  | ||||
| 	for (i = QSE_COUNTOF(rdev->slave); i > 0; ) | ||||
| 	{ | ||||
| 		i--; | ||||
| 		if (rdev->slave[i]) | ||||
| 		{ | ||||
| 			qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)rdev->slave[i]); | ||||
| 			rdev->slave[i] = QSE_NULL; | ||||
| 		} | ||||
| 	} | ||||
| 	rdev->slave_count = 0; | ||||
|  | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int dev_pro_make_slave (qse_aio_dev_t* dev, void* ctx) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* rdev = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	slave_info_t* si = (slave_info_t*)ctx; | ||||
|  | ||||
| 	rdev->dev_capa = si->dev_capa; | ||||
| 	rdev->id = si->id; | ||||
| 	rdev->pfd = si->pfd; | ||||
| 	/* keep rdev->master to QSE_NULL. it's set to the right master | ||||
| 	 * device in dev_pro_make() */ | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int dev_pro_kill_master (qse_aio_dev_t* dev, int force) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* rdev = (qse_aio_dev_pro_t*)dev; | ||||
| 	int i, status; | ||||
| 	pid_t wpid; | ||||
|  | ||||
| 	if (rdev->slave_count > 0) | ||||
| 	{ | ||||
| 		for (i = 0; i < QSE_COUNTOF(rdev->slave); i++) | ||||
| 		{ | ||||
| 			if (rdev->slave[i]) | ||||
| 			{ | ||||
| 				qse_aio_dev_pro_slave_t* sdev = rdev->slave[i]; | ||||
|  | ||||
| 				/* nullify the pointer to the slave device | ||||
| 				 * before calling qse_aio_killdev() on the slave device. | ||||
| 				 * the slave device can check this pointer to tell from | ||||
| 				 * self-initiated termination or master-driven termination */ | ||||
| 				rdev->slave[i] = QSE_NULL; | ||||
|  | ||||
| 				qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)sdev); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->child_pid >= 0) | ||||
| 	{ | ||||
| 		if (!(rdev->flags & QSE_AIO_DEV_PRO_FORGET_CHILD)) | ||||
| 		{ | ||||
| 			int killed = 0; | ||||
|  | ||||
| 		await_child: | ||||
| 			wpid = waitpid (rdev->child_pid, &status, WNOHANG); | ||||
| 			if (wpid == 0) | ||||
| 			{ | ||||
| 				if (force && !killed) | ||||
| 				{ | ||||
| 					if (!(rdev->flags & QSE_AIO_DEV_PRO_FORGET_DIEHARD_CHILD)) | ||||
| 					{ | ||||
| 						kill (rdev->child_pid, SIGKILL); | ||||
| 						killed = 1; | ||||
| 						goto await_child; | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					/* child process is still alive */ | ||||
| 					rdev->aio->errnum = QSE_AIO_EAGAIN; | ||||
| 					return -1;  /* call me again */ | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			/* wpid == rdev->child_pid => full success | ||||
| 			 * wpid == -1 && errno == ECHILD => no such process. it's waitpid()'ed by some other part of the program? | ||||
| 			 * other cases ==> can't really handle properly. forget it by returning success | ||||
| 			 * no need not worry about EINTR because errno can't have the value when WNOHANG is set. | ||||
| 			 */ | ||||
| 		} | ||||
|  | ||||
| printf (">>>>>>>>>>>>>>>>>>> REAPED CHILD %d\n", (int)rdev->child_pid); | ||||
| 		rdev->child_pid = -1; | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->on_close) rdev->on_close (rdev, QSE_AIO_DEV_PRO_MASTER); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int dev_pro_kill_slave (qse_aio_dev_t* dev, int force) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* rdev = (qse_aio_dev_pro_slave_t*)dev; | ||||
|  | ||||
| 	if (rdev->master) | ||||
| 	{ | ||||
| 		qse_aio_dev_pro_t* master; | ||||
|  | ||||
| 		master = rdev->master; | ||||
| 		rdev->master = QSE_NULL; | ||||
|  | ||||
| 		/* indicate EOF */ | ||||
| 		if (master->on_close) master->on_close (master, rdev->id); | ||||
|  | ||||
| 		QSE_ASSERT (master->slave_count > 0); | ||||
| 		master->slave_count--; | ||||
|  | ||||
| 		if (master->slave[rdev->id]) | ||||
| 		{ | ||||
| 			/* this call is started by the slave device itself. | ||||
| 			 * if this is the last slave, kill the master also */ | ||||
| 			if (master->slave_count <= 0)  | ||||
| 			{ | ||||
| 				qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)master); | ||||
| 				/* the master pointer is not valid from this point onwards | ||||
| 				 * as the actual master device object is freed in qse_aio_killdev() */ | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* this call is initiated by this slave device itself. | ||||
| 			 * if it were by the master device, it would be QSE_NULL as | ||||
| 			 * nullified by the dev_pro_kill() */ | ||||
| 			master->slave[rdev->id] = QSE_NULL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->pfd != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		close (rdev->pfd); | ||||
| 		rdev->pfd = QSE_AIO_SYSHND_INVALID; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int dev_pro_read_slave (qse_aio_dev_t* dev, void* buf, qse_aio_iolen_t* len, qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	ssize_t x; | ||||
|  | ||||
| 	x = read (pro->pfd, buf, *len); | ||||
| 	if (x <= -1) | ||||
| 	{ | ||||
| 		if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0;  /* no data available */ | ||||
| 		if (errno == EINTR) return 0; | ||||
| 		pro->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	*len = x; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int dev_pro_write_slave (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t* len, const qse_aio_devaddr_t* dstaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	ssize_t x; | ||||
|  | ||||
| 	x = write (pro->pfd, data, *len); | ||||
| 	if (x <= -1) | ||||
| 	{ | ||||
| 		if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0;  /* no data can be written */ | ||||
| 		if (errno == EINTR) return 0; | ||||
| 		pro->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	*len = x; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static qse_aio_syshnd_t dev_pro_getsyshnd (qse_aio_dev_t* dev) | ||||
| { | ||||
| 	return QSE_AIO_SYSHND_INVALID; | ||||
| } | ||||
|  | ||||
| static qse_aio_syshnd_t dev_pro_getsyshnd_slave (qse_aio_dev_t* dev) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return (qse_aio_syshnd_t)pro->pfd; | ||||
| } | ||||
|  | ||||
| static int dev_pro_ioctl (qse_aio_dev_t* dev, int cmd, void* arg) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* rdev = (qse_aio_dev_pro_t*)dev; | ||||
|  | ||||
| 	switch (cmd) | ||||
| 	{ | ||||
| 		case QSE_AIO_DEV_PRO_CLOSE: | ||||
| 		{ | ||||
| 			qse_aio_dev_pro_sid_t sid = *(qse_aio_dev_pro_sid_t*)arg; | ||||
|  | ||||
| 			if (sid < QSE_AIO_DEV_PRO_IN || sid > QSE_AIO_DEV_PRO_ERR) | ||||
| 			{ | ||||
| 				rdev->aio->errnum = QSE_AIO_EINVAL; | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			if (rdev->slave[sid]) | ||||
| 			{ | ||||
| 				/* unlike dev_pro_kill_master(), i don't nullify rdev->slave[sid]. | ||||
| 				 * so i treat the closing ioctl as if it's a kill request  | ||||
| 				 * initiated by the slave device itself. */ | ||||
| 				qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)rdev->slave[sid]); | ||||
| 			} | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_KILL_CHILD: | ||||
| 			if (rdev->child_pid >= 0) | ||||
| 			{ | ||||
| 				if (kill (rdev->child_pid, SIGKILL) == -1) | ||||
| 				{ | ||||
| 					rdev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			return 0; | ||||
|  | ||||
| 		default: | ||||
| 			dev->aio->errnum = QSE_AIO_EINVAL; | ||||
| 			return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static qse_aio_dev_mth_t dev_pro_methods =  | ||||
| { | ||||
| 	dev_pro_make_master, | ||||
| 	dev_pro_kill_master, | ||||
| 	dev_pro_getsyshnd, | ||||
|  | ||||
| 	QSE_NULL, | ||||
| 	QSE_NULL, | ||||
| 	dev_pro_ioctl | ||||
| }; | ||||
|  | ||||
| static qse_aio_dev_mth_t dev_pro_methods_slave = | ||||
| { | ||||
| 	dev_pro_make_slave, | ||||
| 	dev_pro_kill_slave, | ||||
| 	dev_pro_getsyshnd_slave, | ||||
|  | ||||
| 	dev_pro_read_slave, | ||||
| 	dev_pro_write_slave, | ||||
| 	dev_pro_ioctl | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static int pro_ready (qse_aio_dev_t* dev, int events) | ||||
| { | ||||
| 	/* virtual device. no I/O */ | ||||
| 	dev->aio->errnum = QSE_AIO_EINTERN; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int pro_on_read (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t len, const qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	/* virtual device. no I/O */ | ||||
| 	dev->aio->errnum = QSE_AIO_EINTERN; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int pro_on_write (qse_aio_dev_t* dev, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_devaddr_t* dstaddr) | ||||
| { | ||||
| 	/* virtual device. no I/O */ | ||||
| 	dev->aio->errnum = QSE_AIO_EINTERN; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks = | ||||
| { | ||||
| 	pro_ready, | ||||
| 	pro_on_read, | ||||
| 	pro_on_write | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static int pro_ready_slave (qse_aio_dev_t* dev, int events) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* pro = (qse_aio_dev_pro_t*)dev; | ||||
|  | ||||
| 	if (events & QSE_AIO_DEV_EVENT_ERR) | ||||
| 	{ | ||||
| 		pro->aio->errnum = QSE_AIO_EDEVERR; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (events & QSE_AIO_DEV_EVENT_HUP) | ||||
| 	{ | ||||
| 		if (events & (QSE_AIO_DEV_EVENT_PRI | QSE_AIO_DEV_EVENT_IN | QSE_AIO_DEV_EVENT_OUT))  | ||||
| 		{ | ||||
| 			/* probably half-open? */ | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		pro->aio->errnum = QSE_AIO_EDEVHUP; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 1; /* the device is ok. carry on reading or writing */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static int pro_on_read_slave_out (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t len, const qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return pro->master->on_read (pro->master, data, len, QSE_AIO_DEV_PRO_OUT); | ||||
| } | ||||
|  | ||||
| static int pro_on_read_slave_err (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t len, const qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return pro->master->on_read (pro->master, data, len, QSE_AIO_DEV_PRO_ERR); | ||||
| } | ||||
|  | ||||
| static int pro_on_write_slave (qse_aio_dev_t* dev, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_devaddr_t* dstaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return pro->master->on_write (pro->master, wrlen, wrctx); | ||||
| } | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks_slave_in = | ||||
| { | ||||
| 	pro_ready_slave, | ||||
| 	QSE_NULL, | ||||
| 	pro_on_write_slave | ||||
| }; | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks_slave_out = | ||||
| { | ||||
| 	pro_ready_slave, | ||||
| 	pro_on_read_slave_out, | ||||
| 	QSE_NULL | ||||
| }; | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks_slave_err = | ||||
| { | ||||
| 	pro_ready_slave, | ||||
| 	pro_on_read_slave_err, | ||||
| 	QSE_NULL | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static qse_aio_dev_pro_slave_t* make_slave (qse_aio_t* aio, slave_info_t* si) | ||||
| { | ||||
| 	switch (si->id) | ||||
| 	{ | ||||
| 		case QSE_AIO_DEV_PRO_IN: | ||||
| 			return (qse_aio_dev_pro_slave_t*)qse_aio_makedev ( | ||||
| 				aio, QSE_SIZEOF(qse_aio_dev_pro_t),  | ||||
| 				&dev_pro_methods_slave, &dev_pro_event_callbacks_slave_in, si); | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_OUT: | ||||
| 			return (qse_aio_dev_pro_slave_t*)qse_aio_makedev ( | ||||
| 				aio, QSE_SIZEOF(qse_aio_dev_pro_t),  | ||||
| 				&dev_pro_methods_slave, &dev_pro_event_callbacks_slave_out, si); | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_ERR: | ||||
| 			return (qse_aio_dev_pro_slave_t*)qse_aio_makedev ( | ||||
| 				aio, QSE_SIZEOF(qse_aio_dev_pro_t),  | ||||
| 				&dev_pro_methods_slave, &dev_pro_event_callbacks_slave_err, si); | ||||
|  | ||||
| 		default: | ||||
| 			aio->errnum = QSE_AIO_EINVAL; | ||||
| 			return QSE_NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| qse_aio_dev_pro_t* qse_aio_dev_pro_make (qse_aio_t* aio, qse_size_t xtnsize, const qse_aio_dev_pro_make_t* info) | ||||
| { | ||||
| 	return (qse_aio_dev_pro_t*)qse_aio_makedev ( | ||||
| 		aio, QSE_SIZEOF(qse_aio_dev_pro_t) + xtnsize,  | ||||
| 		&dev_pro_methods, &dev_pro_event_callbacks, (void*)info); | ||||
| } | ||||
|  | ||||
| void qse_aio_dev_pro_kill (qse_aio_dev_pro_t* dev) | ||||
| { | ||||
| 	qse_aio_killdev (dev->aio, (qse_aio_dev_t*)dev); | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_write (qse_aio_dev_pro_t* dev, const void* data, qse_aio_iolen_t dlen, void* wrctx) | ||||
| { | ||||
| 	if (dev->slave[0]) | ||||
| 	{ | ||||
| 		return qse_aio_dev_write ((qse_aio_dev_t*)dev->slave[0], data, dlen, wrctx, QSE_NULL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		dev->aio->errnum = QSE_AIO_ENOCAPA; /* TODO: is it the right error number? */ | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_timedwrite (qse_aio_dev_pro_t* dev, const void* data, qse_aio_iolen_t dlen, const qse_ntime_t* tmout, void* wrctx) | ||||
| { | ||||
| 	if (dev->slave[0]) | ||||
| 	{ | ||||
| 		return qse_aio_dev_timedwrite ((qse_aio_dev_t*)dev->slave[0], data, dlen, tmout, wrctx, QSE_NULL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		dev->aio->errnum = QSE_AIO_ENOCAPA; /* TODO: is it the right error number? */ | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_close (qse_aio_dev_pro_t* dev, qse_aio_dev_pro_sid_t sid) | ||||
| { | ||||
| 	return qse_aio_dev_ioctl ((qse_aio_dev_t*)dev, QSE_AIO_DEV_PRO_CLOSE, &sid); | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_killchild (qse_aio_dev_pro_t* dev) | ||||
| { | ||||
| 	return qse_aio_dev_ioctl ((qse_aio_dev_t*)dev, QSE_AIO_DEV_PRO_KILL_CHILD, QSE_NULL); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| qse_aio_dev_pro_t* qse_aio_dev_pro_getdev (qse_aio_dev_pro_t* pro, qse_aio_dev_pro_sid_t sid) | ||||
| { | ||||
| 	switch (type) | ||||
| 	{ | ||||
| 		case QSE_AIO_DEV_PRO_IN: | ||||
| 			return XXX; | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_OUT: | ||||
| 			return XXX; | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_ERR: | ||||
| 			return XXX; | ||||
| 	} | ||||
|  | ||||
| 	pro->dev->aio = QSE_AIO_EINVAL; | ||||
| 	return QSE_NULL; | ||||
| } | ||||
| #endif | ||||
| @ -1,115 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. 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. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_LIB_SI_AIO_PRV_H_ | ||||
| #define _QSE_LIB_SI_AIO_PRV_H_ | ||||
|  | ||||
| #include <qse/si/aio.h> | ||||
| #include "../cmn/mem-prv.h" | ||||
|  | ||||
|  | ||||
| typedef struct qse_aio_mux_t qse_aio_mux_t; | ||||
|  | ||||
| struct qse_aio_t | ||||
| { | ||||
| 	qse_mmgr_t* mmgr; | ||||
|  | ||||
| 	qse_aio_errnum_t errnum; | ||||
| 	qse_aio_stopreq_t stopreq;  /* stop request to abort qse_aio_loop() */ | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_aio_dev_t* head; | ||||
| 		qse_aio_dev_t* tail; | ||||
| 	} actdev; /* active devices */ | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_aio_dev_t* head; | ||||
| 		qse_aio_dev_t* tail; | ||||
| 	} hltdev; /* halted devices */ | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_aio_dev_t* head; | ||||
| 		qse_aio_dev_t* tail; | ||||
| 	} zmbdev; /* zombie devices */ | ||||
|  | ||||
| 	qse_uint8_t bigbuf[65535]; /* TODO: make this dynamic depending on devices added. device may indicate a buffer size required??? */ | ||||
|  | ||||
| 	unsigned int renew_watch: 1; | ||||
| 	unsigned int in_exec: 1; | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_size_t     capa; | ||||
| 		qse_size_t     size; | ||||
| 		qse_aio_tmrjob_t*  jobs; | ||||
| 	} tmr; | ||||
|  | ||||
| 	/* platform specific fields below */ | ||||
| #if defined(_WIN32) | ||||
| 	HANDLE iocp; | ||||
| #else | ||||
| 	qse_aio_mux_t* mux; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| int qse_aio_makesyshndasync ( | ||||
| 	qse_aio_t*       aio, | ||||
| 	qse_aio_syshnd_t hnd | ||||
| ); | ||||
|  | ||||
| qse_aio_errnum_t qse_aio_syserrtoerrnum ( | ||||
| 	int no | ||||
| ); | ||||
|  | ||||
| void qse_aio_cleartmrjobs ( | ||||
| 	qse_aio_t* aio | ||||
| ); | ||||
|  | ||||
| void qse_aio_firetmrjobs ( | ||||
| 	qse_aio_t*         aio, | ||||
| 	const qse_ntime_t* tmbase, | ||||
| 	qse_size_t*    firecnt | ||||
| ); | ||||
|  | ||||
| int qse_aio_gettmrtmout ( | ||||
| 	qse_aio_t*         aio, | ||||
| 	const qse_ntime_t* tmbase, | ||||
| 	qse_ntime_t*       tmout | ||||
| ); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										1712
									
								
								qse/lib/si/aio-sck.c
									
									
									
									
									
								
							
							
						
						
									
										1712
									
								
								qse/lib/si/aio-sck.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,234 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. 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. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR 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. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include "aio-prv.h" | ||||
|  | ||||
| #define HEAP_PARENT(x) (((x) - 1) / 2) | ||||
| #define HEAP_LEFT(x)   ((x) * 2 + 1) | ||||
| #define HEAP_RIGHT(x)  ((x) * 2 + 2) | ||||
|  | ||||
| #define YOUNGER_THAN(x,y) (qse_cmptime(&(x)->when, &(y)->when) < 0) | ||||
|  | ||||
| void qse_aio_cleartmrjobs (qse_aio_t* aio) | ||||
| { | ||||
| 	while (aio->tmr.size > 0) qse_aio_deltmrjob (aio, 0); | ||||
| } | ||||
|  | ||||
| static qse_aio_tmridx_t sift_up (qse_aio_t* aio, qse_aio_tmridx_t index, int notify) | ||||
| { | ||||
| 	qse_aio_tmridx_t parent; | ||||
|  | ||||
| 	parent = HEAP_PARENT(index); | ||||
| 	if (index > 0 && YOUNGER_THAN(&aio->tmr.jobs[index], &aio->tmr.jobs[parent])) | ||||
| 	{ | ||||
| 		qse_aio_tmrjob_t item; | ||||
|  | ||||
| 		item = aio->tmr.jobs[index];  | ||||
|  | ||||
| 		do | ||||
| 		{ | ||||
| 			/* move down the parent to my current position */ | ||||
| 			aio->tmr.jobs[index] = aio->tmr.jobs[parent]; | ||||
| 			if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
|  | ||||
| 			/* traverse up */ | ||||
| 			index = parent; | ||||
| 			parent = HEAP_PARENT(parent); | ||||
| 		} | ||||
| 		while (index > 0 && YOUNGER_THAN(&item, &aio->tmr.jobs[parent])); | ||||
|  | ||||
| 		aio->tmr.jobs[index] = item; | ||||
| 		if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	} | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| static qse_aio_tmridx_t sift_down (qse_aio_t* aio, qse_aio_tmridx_t index, int notify) | ||||
| { | ||||
| 	qse_size_t base = aio->tmr.size / 2; | ||||
|  | ||||
| 	if (index < base) /* at least 1 child is under the 'index' position */ | ||||
| 	{ | ||||
| 		qse_aio_tmrjob_t item; | ||||
|  | ||||
| 		item = aio->tmr.jobs[index]; | ||||
|  | ||||
| 		do | ||||
| 		{ | ||||
| 			qse_aio_tmridx_t left, right, younger; | ||||
|  | ||||
| 			left = HEAP_LEFT(index); | ||||
| 			right = HEAP_RIGHT(index); | ||||
|  | ||||
| 			if (right < aio->tmr.size && YOUNGER_THAN(&aio->tmr.jobs[right], &aio->tmr.jobs[left])) | ||||
| 			{ | ||||
| 				younger = right; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				younger = left; | ||||
| 			} | ||||
|  | ||||
| 			if (YOUNGER_THAN(&item, &aio->tmr.jobs[younger])) break; | ||||
|  | ||||
| 			aio->tmr.jobs[index] = aio->tmr.jobs[younger]; | ||||
| 			if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
|  | ||||
| 			index = younger; | ||||
| 		} | ||||
| 		while (index < base); | ||||
| 		 | ||||
| 		aio->tmr.jobs[index] = item; | ||||
| 		if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	} | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| void qse_aio_deltmrjob (qse_aio_t* aio, qse_aio_tmridx_t index) | ||||
| { | ||||
| 	qse_aio_tmrjob_t item; | ||||
|  | ||||
| 	QSE_ASSERT (index < aio->tmr.size); | ||||
|  | ||||
| 	item = aio->tmr.jobs[index]; | ||||
| 	if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = QSE_AIO_TMRIDX_INVALID; | ||||
|  | ||||
| 	aio->tmr.size = aio->tmr.size - 1; | ||||
| 	if (aio->tmr.size > 0 && index != aio->tmr.size) | ||||
| 	{ | ||||
| 		aio->tmr.jobs[index] = aio->tmr.jobs[aio->tmr.size]; | ||||
| 		if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 		YOUNGER_THAN(&aio->tmr.jobs[index], &item)? sift_up(aio, index, 1): sift_down(aio, index, 1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| qse_aio_tmridx_t qse_aio_instmrjob (qse_aio_t* aio, const qse_aio_tmrjob_t* job) | ||||
| { | ||||
| 	qse_aio_tmridx_t index = aio->tmr.size; | ||||
|  | ||||
| 	if (index >= aio->tmr.capa) | ||||
| 	{ | ||||
| 		qse_aio_tmrjob_t* tmp; | ||||
| 		qse_size_t new_capa; | ||||
|  | ||||
| 		QSE_ASSERT (aio->tmr.capa >= 1); | ||||
| 		new_capa = aio->tmr.capa * 2; | ||||
| 		tmp = (qse_aio_tmrjob_t*)QSE_MMGR_REALLOC (aio->mmgr, aio->tmr.jobs, new_capa * QSE_SIZEOF(*tmp)); | ||||
| 		if (tmp == QSE_NULL)  | ||||
| 		{ | ||||
| 			aio->errnum = QSE_AIO_ENOMEM; | ||||
| 			return QSE_AIO_TMRIDX_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		aio->tmr.jobs = tmp; | ||||
| 		aio->tmr.capa = new_capa; | ||||
| 	} | ||||
|  | ||||
| 	aio->tmr.size = aio->tmr.size + 1; | ||||
| 	aio->tmr.jobs[index] = *job; | ||||
| 	if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	return sift_up (aio, index, 0); | ||||
| } | ||||
|  | ||||
| qse_aio_tmridx_t qse_aio_updtmrjob (qse_aio_t* aio, qse_aio_tmridx_t index, const qse_aio_tmrjob_t* job) | ||||
| { | ||||
| 	qse_aio_tmrjob_t item; | ||||
| 	item = aio->tmr.jobs[index]; | ||||
| 	aio->tmr.jobs[index] = *job; | ||||
| 	if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	return YOUNGER_THAN(job, &item)? sift_up (aio, index, 0): sift_down (aio, index, 0); | ||||
| } | ||||
|  | ||||
| void qse_aio_firetmrjobs (qse_aio_t* aio, const qse_ntime_t* tm, qse_size_t* firecnt) | ||||
| { | ||||
| 	qse_ntime_t now; | ||||
| 	qse_aio_tmrjob_t tmrjob; | ||||
| 	qse_size_t count = 0; | ||||
|  | ||||
| 	/* if the current time is not specified, get it from the system */ | ||||
| 	if (tm) now = *tm; | ||||
| 	else qse_gettime (&now); | ||||
|  | ||||
| 	while (aio->tmr.size > 0) | ||||
| 	{ | ||||
| 		if (qse_cmptime(&aio->tmr.jobs[0].when, &now) > 0) break; | ||||
|  | ||||
| 		tmrjob = aio->tmr.jobs[0]; /* copy the scheduled job */ | ||||
| 		qse_aio_deltmrjob (aio, 0); /* deschedule the job */ | ||||
|  | ||||
| 		count++; | ||||
| 		tmrjob.handler (aio, &now, &tmrjob); /* then fire the job */ | ||||
| 	} | ||||
|  | ||||
| 	if (firecnt) *firecnt = count; | ||||
| } | ||||
|  | ||||
| int qse_aio_gettmrtmout (qse_aio_t* aio, const qse_ntime_t* tm, qse_ntime_t* tmout) | ||||
| { | ||||
| 	qse_ntime_t now; | ||||
|  | ||||
| 	/* time-out can't be calculated when there's no job scheduled */ | ||||
| 	if (aio->tmr.size <= 0)  | ||||
| 	{ | ||||
| 		aio->errnum = QSE_AIO_ENOENT; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* if the current time is not specified, get it from the system */ | ||||
| 	if (tm) now = *tm; | ||||
| 	else qse_gettime (&now); | ||||
|  | ||||
| 	qse_subtime (&aio->tmr.jobs[0].when, &now, tmout); | ||||
| 	if (tmout->sec < 0) qse_cleartime (tmout); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| qse_aio_tmrjob_t* qse_aio_gettmrjob (qse_aio_t* aio, qse_aio_tmridx_t index) | ||||
| { | ||||
| 	if (index < 0 || index >= aio->tmr.size) | ||||
| 	{ | ||||
| 		aio->errnum = QSE_AIO_ENOENT; | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	return &aio->tmr.jobs[index]; | ||||
| } | ||||
|  | ||||
| int qse_aio_gettmrjobdeadline (qse_aio_t* aio, qse_aio_tmridx_t index, qse_ntime_t* deadline) | ||||
| { | ||||
| 	if (index < 0 || index >= aio->tmr.size) | ||||
| 	{ | ||||
| 		aio->errnum = QSE_AIO_ENOENT; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	*deadline = aio->tmr.jobs[index].when; | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										1468
									
								
								qse/lib/si/aio.c
									
									
									
									
									
								
							
							
						
						
									
										1468
									
								
								qse/lib/si/aio.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user